summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code')
-rw-r--r--src/3rdparty/assimp/code/3DSConverter.cpp1518
-rw-r--r--src/3rdparty/assimp/code/3DSExporter.cpp565
-rw-r--r--src/3rdparty/assimp/code/3DSExporter.h98
-rw-r--r--src/3rdparty/assimp/code/3DSHelper.h906
-rw-r--r--src/3rdparty/assimp/code/3DSLoader.cpp2397
-rw-r--r--src/3rdparty/assimp/code/3DSLoader.h410
-rw-r--r--src/3rdparty/assimp/code/ACLoader.cpp1539
-rw-r--r--src/3rdparty/assimp/code/ACLoader.h353
-rw-r--r--src/3rdparty/assimp/code/ASELoader.cpp2317
-rw-r--r--src/3rdparty/assimp/code/ASELoader.h218
-rw-r--r--src/3rdparty/assimp/code/ASEParser.cpp3789
-rw-r--r--src/3rdparty/assimp/code/ASEParser.h945
-rw-r--r--src/3rdparty/assimp/code/AssbinExporter.cpp768
-rw-r--r--src/3rdparty/assimp/code/AssbinExporter.h49
-rw-r--r--src/3rdparty/assimp/code/AssbinLoader.cpp686
-rw-r--r--src/3rdparty/assimp/code/AssbinLoader.h105
-rw-r--r--src/3rdparty/assimp/code/Assimp.cpp741
-rw-r--r--src/3rdparty/assimp/code/AssimpCExport.cpp105
-rw-r--r--src/3rdparty/assimp/code/AssimpPCH.cpp135
-rw-r--r--src/3rdparty/assimp/code/AssimpPCH.h166
-rw-r--r--src/3rdparty/assimp/code/AssxmlExporter.cpp648
-rw-r--r--src/3rdparty/assimp/code/AssxmlExporter.h49
-rw-r--r--src/3rdparty/assimp/code/B3DImporter.cpp979
-rw-r--r--src/3rdparty/assimp/code/B3DImporter.h146
-rw-r--r--src/3rdparty/assimp/code/BVHLoader.cpp779
-rw-r--r--src/3rdparty/assimp/code/BVHLoader.h164
-rw-r--r--src/3rdparty/assimp/code/BaseImporter.cpp865
-rw-r--r--src/3rdparty/assimp/code/BaseImporter.h586
-rw-r--r--src/3rdparty/assimp/code/BaseProcess.cpp62
-rw-r--r--src/3rdparty/assimp/code/BaseProcess.h380
-rw-r--r--src/3rdparty/assimp/code/Bitmap.cpp191
-rw-r--r--src/3rdparty/assimp/code/Bitmap.h107
-rw-r--r--src/3rdparty/assimp/code/BlenderBMesh.cpp164
-rw-r--r--src/3rdparty/assimp/code/BlenderBMesh.h97
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.cpp519
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.h933
-rw-r--r--src/3rdparty/assimp/code/BlenderDNA.inl1018
-rw-r--r--src/3rdparty/assimp/code/BlenderIntermediate.h264
-rw-r--r--src/3rdparty/assimp/code/BlenderLoader.cpp2066
-rw-r--r--src/3rdparty/assimp/code/BlenderLoader.h306
-rw-r--r--src/3rdparty/assimp/code/BlenderModifier.cpp438
-rw-r--r--src/3rdparty/assimp/code/BlenderModifier.h125
-rw-r--r--src/3rdparty/assimp/code/BlenderScene.cpp303
-rw-r--r--src/3rdparty/assimp/code/BlenderScene.h964
-rw-r--r--src/3rdparty/assimp/code/BlenderSceneGen.h28
-rw-r--r--src/3rdparty/assimp/code/BlenderTessellator.cpp530
-rw-r--r--src/3rdparty/assimp/code/BlenderTessellator.h272
-rw-r--r--src/3rdparty/assimp/code/BlobIOSystem.h434
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt23
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp99
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp81
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp26
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/make_shared.hpp57
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp37
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/noncopyable.hpp36
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp45
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp79
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp79
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp228
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp257
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp20
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp72
-rw-r--r--src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp283
-rw-r--r--src/3rdparty/assimp/code/ByteSwap.h285
-rw-r--r--src/3rdparty/assimp/code/ByteSwapper.h286
-rw-r--r--src/3rdparty/assimp/code/C4DImporter.cpp650
-rw-r--r--src/3rdparty/assimp/code/C4DImporter.h123
-rw-r--r--src/3rdparty/assimp/code/CInterfaceIOWrapper.h194
-rw-r--r--src/3rdparty/assimp/code/CMakeLists.txt1284
-rw-r--r--src/3rdparty/assimp/code/COBLoader.cpp2007
-rw-r--r--src/3rdparty/assimp/code/COBLoader.h178
-rw-r--r--src/3rdparty/assimp/code/COBScene.h257
-rw-r--r--src/3rdparty/assimp/code/CSMLoader.cpp443
-rw-r--r--src/3rdparty/assimp/code/CSMLoader.h51
-rw-r--r--src/3rdparty/assimp/code/CalcTangentsProcess.cpp395
-rw-r--r--src/3rdparty/assimp/code/CalcTangentsProcess.h100
-rw-r--r--src/3rdparty/assimp/code/ColladaExporter.cpp1287
-rw-r--r--src/3rdparty/assimp/code/ColladaExporter.h155
-rw-r--r--src/3rdparty/assimp/code/ColladaHelper.h722
-rw-r--r--src/3rdparty/assimp/code/ColladaLoader.cpp1598
-rw-r--r--src/3rdparty/assimp/code/ColladaLoader.h163
-rw-r--r--src/3rdparty/assimp/code/ColladaParser.cpp4907
-rw-r--r--src/3rdparty/assimp/code/ColladaParser.h519
-rw-r--r--src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp798
-rw-r--r--src/3rdparty/assimp/code/ComputeUVMappingProcess.h170
-rw-r--r--src/3rdparty/assimp/code/ConvertToLHProcess.cpp347
-rw-r--r--src/3rdparty/assimp/code/ConvertToLHProcess.h140
-rw-r--r--src/3rdparty/assimp/code/D3MFImporter.cpp388
-rw-r--r--src/3rdparty/assimp/code/D3MFImporter.h68
-rw-r--r--src/3rdparty/assimp/code/D3MFOpcPackage.cpp591
-rw-r--r--src/3rdparty/assimp/code/D3MFOpcPackage.h76
-rw-r--r--src/3rdparty/assimp/code/DXFHelper.h257
-rw-r--r--src/3rdparty/assimp/code/DXFLoader.cpp1509
-rw-r--r--src/3rdparty/assimp/code/DXFLoader.h152
-rw-r--r--src/3rdparty/assimp/code/DeboneProcess.cpp743
-rw-r--r--src/3rdparty/assimp/code/DeboneProcess.h130
-rw-r--r--src/3rdparty/assimp/code/DefaultIOStream.cpp121
-rw-r--r--src/3rdparty/assimp/code/DefaultIOStream.h125
-rw-r--r--src/3rdparty/assimp/code/DefaultIOSystem.cpp152
-rw-r--r--src/3rdparty/assimp/code/DefaultIOSystem.h75
-rw-r--r--src/3rdparty/assimp/code/DefaultLogger.cpp498
-rw-r--r--src/3rdparty/assimp/code/DefaultProgressHandler.h39
-rw-r--r--src/3rdparty/assimp/code/Defines.h49
-rw-r--r--src/3rdparty/assimp/code/Exceptional.h93
-rw-r--r--src/3rdparty/assimp/code/Exporter.cpp688
-rw-r--r--src/3rdparty/assimp/code/FBXAnimation.cpp391
-rw-r--r--src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp527
-rw-r--r--src/3rdparty/assimp/code/FBXCompileConfig.h44
-rw-r--r--src/3rdparty/assimp/code/FBXConverter.cpp6062
-rw-r--r--src/3rdparty/assimp/code/FBXConverter.h35
-rw-r--r--src/3rdparty/assimp/code/FBXDeformer.cpp147
-rw-r--r--src/3rdparty/assimp/code/FBXDocument.cpp934
-rw-r--r--src/3rdparty/assimp/code/FBXDocument.h1776
-rw-r--r--src/3rdparty/assimp/code/FBXDocumentUtil.cpp110
-rw-r--r--src/3rdparty/assimp/code/FBXDocumentUtil.h108
-rw-r--r--src/3rdparty/assimp/code/FBXImportSettings.h190
-rw-r--r--src/3rdparty/assimp/code/FBXImporter.cpp193
-rw-r--r--src/3rdparty/assimp/code/FBXImporter.h75
-rw-r--r--src/3rdparty/assimp/code/FBXMaterial.cpp406
-rw-r--r--src/3rdparty/assimp/code/FBXMeshGeometry.cpp901
-rw-r--r--src/3rdparty/assimp/code/FBXMeshGeometry.h180
-rw-r--r--src/3rdparty/assimp/code/FBXModel.cpp154
-rw-r--r--src/3rdparty/assimp/code/FBXNodeAttribute.cpp74
-rw-r--r--src/3rdparty/assimp/code/FBXParser.cpp1834
-rw-r--r--src/3rdparty/assimp/code/FBXParser.h153
-rw-r--r--src/3rdparty/assimp/code/FBXProperties.cpp238
-rw-r--r--src/3rdparty/assimp/code/FBXProperties.h170
-rw-r--r--src/3rdparty/assimp/code/FBXTokenizer.cpp322
-rw-r--r--src/3rdparty/assimp/code/FBXTokenizer.h144
-rw-r--r--src/3rdparty/assimp/code/FBXUtil.cpp86
-rw-r--r--src/3rdparty/assimp/code/FBXUtil.h32
-rw-r--r--src/3rdparty/assimp/code/FileLogStream.h61
-rw-r--r--src/3rdparty/assimp/code/FileSystemFilter.h480
-rw-r--r--src/3rdparty/assimp/code/FindDegenerates.cpp277
-rw-r--r--src/3rdparty/assimp/code/FindDegenerates.h98
-rw-r--r--src/3rdparty/assimp/code/FindInstancesProcess.cpp396
-rw-r--r--src/3rdparty/assimp/code/FindInstancesProcess.h94
-rw-r--r--src/3rdparty/assimp/code/FindInvalidDataProcess.cpp566
-rw-r--r--src/3rdparty/assimp/code/FindInvalidDataProcess.h75
-rw-r--r--src/3rdparty/assimp/code/FixNormalsStep.cpp178
-rw-r--r--src/3rdparty/assimp/code/FixNormalsStep.h64
-rw-r--r--src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp143
-rw-r--r--src/3rdparty/assimp/code/GenFaceNormalsProcess.h56
-rw-r--r--src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp319
-rw-r--r--src/3rdparty/assimp/code/GenVertexNormalsProcess.h106
-rw-r--r--src/3rdparty/assimp/code/GenericProperty.h129
-rw-r--r--src/3rdparty/assimp/code/HMPFileData.h129
-rw-r--r--src/3rdparty/assimp/code/HMPLoader.cpp806
-rw-r--r--src/3rdparty/assimp/code/HMPLoader.h164
-rw-r--r--src/3rdparty/assimp/code/HalfLifeFileData.h179
-rw-r--r--src/3rdparty/assimp/code/Hash.h27
-rw-r--r--src/3rdparty/assimp/code/IFCBoolean.cpp1347
-rw-r--r--src/3rdparty/assimp/code/IFCCurve.cpp850
-rw-r--r--src/3rdparty/assimp/code/IFCGeometry.cpp1473
-rw-r--r--src/3rdparty/assimp/code/IFCLoader.cpp1508
-rw-r--r--src/3rdparty/assimp/code/IFCLoader.h112
-rw-r--r--src/3rdparty/assimp/code/IFCMaterial.cpp269
-rw-r--r--src/3rdparty/assimp/code/IFCOpenings.cpp2980
-rw-r--r--src/3rdparty/assimp/code/IFCProfile.cpp232
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen.h6566
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen1.cpp4596
-rw-r--r--src/3rdparty/assimp/code/IFCReaderGen2.cpp2146
-rw-r--r--src/3rdparty/assimp/code/IFCUtil.cpp903
-rw-r--r--src/3rdparty/assimp/code/IFCUtil.h442
-rw-r--r--src/3rdparty/assimp/code/IFF.h88
-rw-r--r--src/3rdparty/assimp/code/IRRLoader.cpp2699
-rw-r--r--src/3rdparty/assimp/code/IRRLoader.h471
-rw-r--r--src/3rdparty/assimp/code/IRRMeshLoader.cpp894
-rw-r--r--src/3rdparty/assimp/code/IRRMeshLoader.h66
-rw-r--r--src/3rdparty/assimp/code/IRRShared.cpp805
-rw-r--r--src/3rdparty/assimp/code/IRRShared.h117
-rw-r--r--src/3rdparty/assimp/code/Importer.cpp1487
-rw-r--r--src/3rdparty/assimp/code/Importer.h247
-rw-r--r--src/3rdparty/assimp/code/ImporterRegistry.cpp228
-rw-r--r--src/3rdparty/assimp/code/ImproveCacheLocality.cpp608
-rw-r--r--src/3rdparty/assimp/code/ImproveCacheLocality.h64
-rw-r--r--src/3rdparty/assimp/code/JoinVerticesProcess.cpp684
-rw-r--r--src/3rdparty/assimp/code/JoinVerticesProcess.h80
-rw-r--r--src/3rdparty/assimp/code/LWOAnimation.cpp985
-rw-r--r--src/3rdparty/assimp/code/LWOAnimation.h418
-rw-r--r--src/3rdparty/assimp/code/LWOBLoader.cpp664
-rw-r--r--src/3rdparty/assimp/code/LWOFileData.h672
-rw-r--r--src/3rdparty/assimp/code/LWOLoader.cpp2481
-rw-r--r--src/3rdparty/assimp/code/LWOLoader.h714
-rw-r--r--src/3rdparty/assimp/code/LWOMaterial.cpp1569
-rw-r--r--src/3rdparty/assimp/code/LWSLoader.cpp1510
-rw-r--r--src/3rdparty/assimp/code/LWSLoader.h254
-rw-r--r--src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp259
-rw-r--r--src/3rdparty/assimp/code/LimitBoneWeightsProcess.h122
-rw-r--r--src/3rdparty/assimp/code/LineSplitter.h342
-rw-r--r--src/3rdparty/assimp/code/LogAux.h150
-rw-r--r--src/3rdparty/assimp/code/MD2FileData.h123
-rw-r--r--src/3rdparty/assimp/code/MD2Loader.cpp661
-rw-r--r--src/3rdparty/assimp/code/MD2Loader.h100
-rw-r--r--src/3rdparty/assimp/code/MD2NormalTable.h346
-rw-r--r--src/3rdparty/assimp/code/MD3FileData.h297
-rw-r--r--src/3rdparty/assimp/code/MD3Loader.cpp1801
-rw-r--r--src/3rdparty/assimp/code/MD3Loader.h320
-rw-r--r--src/3rdparty/assimp/code/MD4FileData.h182
-rw-r--r--src/3rdparty/assimp/code/MD5Loader.cpp1223
-rw-r--r--src/3rdparty/assimp/code/MD5Loader.h247
-rw-r--r--src/3rdparty/assimp/code/MD5Parser.cpp752
-rw-r--r--src/3rdparty/assimp/code/MD5Parser.h469
-rw-r--r--src/3rdparty/assimp/code/MDCFileData.h175
-rw-r--r--src/3rdparty/assimp/code/MDCLoader.cpp762
-rw-r--r--src/3rdparty/assimp/code/MDCLoader.h110
-rw-r--r--src/3rdparty/assimp/code/MDCNormalTable.h516
-rw-r--r--src/3rdparty/assimp/code/MDLDefaultColorMap.h146
-rw-r--r--src/3rdparty/assimp/code/MDLFileData.h894
-rw-r--r--src/3rdparty/assimp/code/MDLLoader.cpp3389
-rw-r--r--src/3rdparty/assimp/code/MDLLoader.h719
-rw-r--r--src/3rdparty/assimp/code/MDLMaterialLoader.cpp1438
-rw-r--r--src/3rdparty/assimp/code/MS3DLoader.cpp1066
-rw-r--r--src/3rdparty/assimp/code/MS3DLoader.h183
-rw-r--r--src/3rdparty/assimp/code/Macros.h49
-rw-r--r--src/3rdparty/assimp/code/MakeVerboseFormat.cpp318
-rw-r--r--src/3rdparty/assimp/code/MakeVerboseFormat.h80
-rw-r--r--src/3rdparty/assimp/code/MaterialSystem.cpp942
-rw-r--r--src/3rdparty/assimp/code/MaterialSystem.h30
-rw-r--r--src/3rdparty/assimp/code/MathFunctions.h77
-rw-r--r--src/3rdparty/assimp/code/MemoryIOWrapper.h265
-rw-r--r--src/3rdparty/assimp/code/NDOLoader.cpp461
-rw-r--r--src/3rdparty/assimp/code/NDOLoader.h119
-rw-r--r--src/3rdparty/assimp/code/NFFLoader.cpp2351
-rw-r--r--src/3rdparty/assimp/code/NFFLoader.h291
-rw-r--r--src/3rdparty/assimp/code/OFFLoader.cpp335
-rw-r--r--src/3rdparty/assimp/code/OFFLoader.h64
-rw-r--r--src/3rdparty/assimp/code/ObjExporter.cpp520
-rw-r--r--src/3rdparty/assimp/code/ObjExporter.h150
-rw-r--r--src/3rdparty/assimp/code/ObjFileData.h562
-rw-r--r--src/3rdparty/assimp/code/ObjFileImporter.cpp1198
-rw-r--r--src/3rdparty/assimp/code/ObjFileImporter.h115
-rw-r--r--src/3rdparty/assimp/code/ObjFileMtlImporter.cpp671
-rw-r--r--src/3rdparty/assimp/code/ObjFileMtlImporter.h114
-rw-r--r--src/3rdparty/assimp/code/ObjFileParser.cpp1258
-rw-r--r--src/3rdparty/assimp/code/ObjFileParser.h192
-rw-r--r--src/3rdparty/assimp/code/ObjTools.h335
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.cpp1675
-rw-r--r--src/3rdparty/assimp/code/OgreBinarySerializer.h693
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.cpp166
-rw-r--r--src/3rdparty/assimp/code/OgreImporter.h86
-rw-r--r--src/3rdparty/assimp/code/OgreMaterial.cpp1023
-rw-r--r--src/3rdparty/assimp/code/OgreParsingUtils.h110
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.cpp1639
-rw-r--r--src/3rdparty/assimp/code/OgreStructs.h895
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.cpp1511
-rw-r--r--src/3rdparty/assimp/code/OgreXmlSerializer.h118
-rw-r--r--src/3rdparty/assimp/code/OpenGEXExporter.cpp56
-rw-r--r--src/3rdparty/assimp/code/OpenGEXExporter.h66
-rw-r--r--src/3rdparty/assimp/code/OpenGEXImporter.cpp1190
-rw-r--r--src/3rdparty/assimp/code/OpenGEXImporter.h209
-rw-r--r--src/3rdparty/assimp/code/OpenGEXStructs.h265
-rw-r--r--src/3rdparty/assimp/code/OptimizeGraph.cpp519
-rw-r--r--src/3rdparty/assimp/code/OptimizeGraph.h133
-rw-r--r--src/3rdparty/assimp/code/OptimizeMeshes.cpp334
-rw-r--r--src/3rdparty/assimp/code/OptimizeMeshes.h212
-rw-r--r--src/3rdparty/assimp/code/ParsingUtils.h180
-rw-r--r--src/3rdparty/assimp/code/PlyExporter.cpp503
-rw-r--r--src/3rdparty/assimp/code/PlyExporter.h55
-rw-r--r--src/3rdparty/assimp/code/PlyLoader.cpp1924
-rw-r--r--src/3rdparty/assimp/code/PlyLoader.h208
-rw-r--r--src/3rdparty/assimp/code/PlyParser.cpp1538
-rw-r--r--src/3rdparty/assimp/code/PlyParser.h594
-rw-r--r--src/3rdparty/assimp/code/PolyTools.h245
-rw-r--r--src/3rdparty/assimp/code/PostStepRegistry.cpp153
-rw-r--r--src/3rdparty/assimp/code/PretransformVertices.cpp1160
-rw-r--r--src/3rdparty/assimp/code/PretransformVertices.h201
-rw-r--r--src/3rdparty/assimp/code/ProcessHelper.cpp622
-rw-r--r--src/3rdparty/assimp/code/ProcessHelper.h355
-rw-r--r--src/3rdparty/assimp/code/Profiler.h74
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileData.h230
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileImporter.cpp1181
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileImporter.h98
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileParser.cpp302
-rw-r--r--src/3rdparty/assimp/code/Q3BSPFileParser.h54
-rw-r--r--src/3rdparty/assimp/code/Q3BSPZipArchive.cpp342
-rw-r--r--src/3rdparty/assimp/code/Q3BSPZipArchive.h124
-rw-r--r--src/3rdparty/assimp/code/Q3DLoader.cpp1073
-rw-r--r--src/3rdparty/assimp/code/Q3DLoader.h139
-rw-r--r--src/3rdparty/assimp/code/RawLoader.cpp510
-rw-r--r--src/3rdparty/assimp/code/RawLoader.h114
-rw-r--r--src/3rdparty/assimp/code/RemoveComments.cpp113
-rw-r--r--src/3rdparty/assimp/code/RemoveComments.h69
-rw-r--r--src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp291
-rw-r--r--src/3rdparty/assimp/code/RemoveRedundantMaterials.h92
-rw-r--r--src/3rdparty/assimp/code/RemoveVCProcess.cpp488
-rw-r--r--src/3rdparty/assimp/code/RemoveVCProcess.h118
-rw-r--r--src/3rdparty/assimp/code/SGSpatialSort.cpp215
-rw-r--r--src/3rdparty/assimp/code/SGSpatialSort.h171
-rw-r--r--src/3rdparty/assimp/code/SIBImporter.cpp926
-rw-r--r--src/3rdparty/assimp/code/SIBImporter.h119
-rw-r--r--src/3rdparty/assimp/code/SMDLoader.cpp1875
-rw-r--r--src/3rdparty/assimp/code/SMDLoader.h577
-rw-r--r--src/3rdparty/assimp/code/STEPFile.h1824
-rw-r--r--src/3rdparty/assimp/code/STEPFileEncoding.cpp772
-rw-r--r--src/3rdparty/assimp/code/STEPFileEncoding.h38
-rw-r--r--src/3rdparty/assimp/code/STEPFileReader.cpp879
-rw-r--r--src/3rdparty/assimp/code/STEPFileReader.h44
-rw-r--r--src/3rdparty/assimp/code/STLExporter.cpp218
-rw-r--r--src/3rdparty/assimp/code/STLExporter.h42
-rw-r--r--src/3rdparty/assimp/code/STLLoader.cpp777
-rw-r--r--src/3rdparty/assimp/code/STLLoader.h98
-rw-r--r--src/3rdparty/assimp/code/SceneCombiner.cpp2014
-rw-r--r--src/3rdparty/assimp/code/SceneCombiner.h541
-rw-r--r--src/3rdparty/assimp/code/ScenePreprocessor.cpp401
-rw-r--r--src/3rdparty/assimp/code/ScenePreprocessor.h117
-rw-r--r--src/3rdparty/assimp/code/ScenePrivate.h69
-rw-r--r--src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp413
-rw-r--r--src/3rdparty/assimp/code/SkeletonMeshBuilder.h111
-rw-r--r--src/3rdparty/assimp/code/SmoothingGroups.h79
-rw-r--r--src/3rdparty/assimp/code/SmoothingGroups.inl154
-rw-r--r--src/3rdparty/assimp/code/SortByPTypeProcess.cpp657
-rw-r--r--src/3rdparty/assimp/code/SortByPTypeProcess.h46
-rw-r--r--src/3rdparty/assimp/code/SpatialSort.cpp484
-rw-r--r--src/3rdparty/assimp/code/SpatialSort.h216
-rw-r--r--src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp646
-rw-r--r--src/3rdparty/assimp/code/SplitByBoneCountProcess.h86
-rw-r--r--src/3rdparty/assimp/code/SplitLargeMeshes.cpp1120
-rw-r--r--src/3rdparty/assimp/code/SplitLargeMeshes.h191
-rw-r--r--src/3rdparty/assimp/code/StandardShapes.cpp687
-rw-r--r--src/3rdparty/assimp/code/StandardShapes.h286
-rw-r--r--src/3rdparty/assimp/code/StdOStreamLogStream.h84
-rw-r--r--src/3rdparty/assimp/code/StepExporter.cpp370
-rw-r--r--src/3rdparty/assimp/code/StepExporter.h109
-rw-r--r--src/3rdparty/assimp/code/StreamReader.h550
-rw-r--r--src/3rdparty/assimp/code/StreamWriter.h239
-rw-r--r--src/3rdparty/assimp/code/StringComparison.h166
-rw-r--r--src/3rdparty/assimp/code/StringUtils.h111
-rw-r--r--src/3rdparty/assimp/code/Subdivision.cpp970
-rw-r--r--src/3rdparty/assimp/code/Subdivision.h138
-rw-r--r--src/3rdparty/assimp/code/TargetAnimation.cpp350
-rw-r--r--src/3rdparty/assimp/code/TargetAnimation.h186
-rw-r--r--src/3rdparty/assimp/code/TerragenLoader.cpp395
-rw-r--r--src/3rdparty/assimp/code/TerragenLoader.h50
-rw-r--r--src/3rdparty/assimp/code/TextureTransform.cpp972
-rw-r--r--src/3rdparty/assimp/code/TextureTransform.h276
-rw-r--r--src/3rdparty/assimp/code/TinyFormatter.h164
-rw-r--r--src/3rdparty/assimp/code/TriangulateProcess.cpp793
-rw-r--r--src/3rdparty/assimp/code/TriangulateProcess.h64
-rw-r--r--src/3rdparty/assimp/code/UnrealLoader.cpp713
-rw-r--r--src/3rdparty/assimp/code/UnrealLoader.h216
-rw-r--r--src/3rdparty/assimp/code/ValidateDataStructure.cpp1617
-rw-r--r--src/3rdparty/assimp/code/ValidateDataStructure.h223
-rw-r--r--src/3rdparty/assimp/code/Version.cpp169
-rw-r--r--src/3rdparty/assimp/code/Vertex.h381
-rw-r--r--src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp176
-rw-r--r--src/3rdparty/assimp/code/VertexTriangleAdjacency.h116
-rw-r--r--src/3rdparty/assimp/code/Win32DebugLogStream.h36
-rw-r--r--src/3rdparty/assimp/code/XFileExporter.cpp532
-rw-r--r--src/3rdparty/assimp/code/XFileExporter.h135
-rw-r--r--src/3rdparty/assimp/code/XFileHelper.h205
-rw-r--r--src/3rdparty/assimp/code/XFileImporter.cpp1145
-rw-r--r--src/3rdparty/assimp/code/XFileImporter.h164
-rw-r--r--src/3rdparty/assimp/code/XFileParser.cpp2355
-rw-r--r--src/3rdparty/assimp/code/XFileParser.h194
-rw-r--r--src/3rdparty/assimp/code/XGLLoader.cpp1503
-rw-r--r--src/3rdparty/assimp/code/XGLLoader.h265
-rw-r--r--src/3rdparty/assimp/code/XMLTools.h81
-rw-r--r--src/3rdparty/assimp/code/assbin_chunks.h118
-rw-r--r--src/3rdparty/assimp/code/fast_atof.h469
-rw-r--r--src/3rdparty/assimp/code/glTFAsset.h964
-rw-r--r--src/3rdparty/assimp/code/glTFAsset.inl1269
-rw-r--r--src/3rdparty/assimp/code/glTFAssetWriter.h89
-rw-r--r--src/3rdparty/assimp/code/glTFAssetWriter.inl492
-rw-r--r--src/3rdparty/assimp/code/glTFExporter.cpp366
-rw-r--r--src/3rdparty/assimp/code/glTFExporter.h108
-rw-r--r--src/3rdparty/assimp/code/glTFImporter.cpp654
-rw-r--r--src/3rdparty/assimp/code/glTFImporter.h90
-rw-r--r--src/3rdparty/assimp/code/irrXMLWrapper.h155
-rw-r--r--src/3rdparty/assimp/code/qnan.h74
370 files changed, 110971 insertions, 94646 deletions
diff --git a/src/3rdparty/assimp/code/3DSConverter.cpp b/src/3rdparty/assimp/code/3DSConverter.cpp
index 3498a4b21..cb6fd9077 100644
--- a/src/3rdparty/assimp/code/3DSConverter.cpp
+++ b/src/3rdparty/assimp/code/3DSConverter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,28 +25,33 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the 3ds importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
#include "3DSLoader.h"
#include "TargetAnimation.h"
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include "StringComparison.h"
+#include <memory>
+#include <cctype>
using namespace Assimp;
@@ -54,808 +59,809 @@ using namespace Assimp;
// Setup final material indices, generae a default material if necessary
void Discreet3DSImporter::ReplaceDefaultMaterial()
{
-
- // Try to find an existing material that matches the
- // typical default material setting:
- // - no textures
- // - diffuse color (in grey!)
- // NOTE: This is here to workaround the fact that some
- // exporters are writing a default material, too.
- unsigned int idx = 0xcdcdcdcd;
- for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
- {
- std::string s = mScene->mMaterials[i].mName;
- for (std::string::iterator it = s.begin(); it != s.end(); ++it)
- *it = ::tolower(*it);
-
- if (std::string::npos == s.find("default"))continue;
-
- if (mScene->mMaterials[i].mDiffuse.r !=
- mScene->mMaterials[i].mDiffuse.g ||
- mScene->mMaterials[i].mDiffuse.r !=
- mScene->mMaterials[i].mDiffuse.b)continue;
-
- if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 ||
- mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
- mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
- mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
- mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
- mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 )
- {
- continue;
- }
- idx = i;
- }
- if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size();
-
- // now iterate through all meshes and through all faces and
- // find all faces that are using the default material
- unsigned int cnt = 0;
- for (std::vector<D3DS::Mesh>::iterator
- i = mScene->mMeshes.begin();
- i != mScene->mMeshes.end();++i)
- {
- for (std::vector<unsigned int>::iterator
- a = (*i).mFaceMaterials.begin();
- a != (*i).mFaceMaterials.end();++a)
- {
- // NOTE: The additional check seems to be necessary,
- // some exporters seem to generate invalid data here
- if (0xcdcdcdcd == (*a))
- {
- (*a) = idx;
- ++cnt;
- }
- else if ( (*a) >= mScene->mMaterials.size())
- {
- (*a) = idx;
- DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
- ++cnt;
- }
- }
- }
- if (cnt && idx == mScene->mMaterials.size())
- {
- // We need to create our own default material
- D3DS::Material sMat;
- sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
- sMat.mName = "%%%DEFAULT";
- mScene->mMaterials.push_back(sMat);
-
- DefaultLogger::get()->info("3DS: Generating default material");
- }
+
+ // Try to find an existing material that matches the
+ // typical default material setting:
+ // - no textures
+ // - diffuse color (in grey!)
+ // NOTE: This is here to workaround the fact that some
+ // exporters are writing a default material, too.
+ unsigned int idx = 0xcdcdcdcd;
+ for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
+ {
+ std::string s = mScene->mMaterials[i].mName;
+ for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
+ *it = static_cast< char >( ::tolower( *it ) );
+ }
+
+ if (std::string::npos == s.find("default"))continue;
+
+ if (mScene->mMaterials[i].mDiffuse.r !=
+ mScene->mMaterials[i].mDiffuse.g ||
+ mScene->mMaterials[i].mDiffuse.r !=
+ mScene->mMaterials[i].mDiffuse.b)continue;
+
+ if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 ||
+ mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
+ mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
+ mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
+ mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
+ mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 )
+ {
+ continue;
+ }
+ idx = i;
+ }
+ if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size();
+
+ // now iterate through all meshes and through all faces and
+ // find all faces that are using the default material
+ unsigned int cnt = 0;
+ for (std::vector<D3DS::Mesh>::iterator
+ i = mScene->mMeshes.begin();
+ i != mScene->mMeshes.end();++i)
+ {
+ for (std::vector<unsigned int>::iterator
+ a = (*i).mFaceMaterials.begin();
+ a != (*i).mFaceMaterials.end();++a)
+ {
+ // NOTE: The additional check seems to be necessary,
+ // some exporters seem to generate invalid data here
+ if (0xcdcdcdcd == (*a))
+ {
+ (*a) = idx;
+ ++cnt;
+ }
+ else if ( (*a) >= mScene->mMaterials.size())
+ {
+ (*a) = idx;
+ DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
+ ++cnt;
+ }
+ }
+ }
+ if (cnt && idx == mScene->mMaterials.size())
+ {
+ // We need to create our own default material
+ D3DS::Material sMat;
+ sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
+ sMat.mName = "%%%DEFAULT";
+ mScene->mMaterials.push_back(sMat);
+
+ DefaultLogger::get()->info("3DS: Generating default material");
+ }
}
// ------------------------------------------------------------------------------------------------
// Check whether all indices are valid. Otherwise we'd crash before the validation step is reached
void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
{
- for (std::vector< D3DS::Face >::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i)
- {
- // check whether all indices are in range
- for (unsigned int a = 0; a < 3;++a)
- {
- if ((*i).mIndices[a] >= sMesh.mPositions.size())
- {
- DefaultLogger::get()->warn("3DS: Vertex index overflow)");
- (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
- }
- if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
- {
- DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
- (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
- }
- }
- }
+ for (std::vector< D3DS::Face >::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i)
+ {
+ // check whether all indices are in range
+ for (unsigned int a = 0; a < 3;++a)
+ {
+ if ((*i).mIndices[a] >= sMesh.mPositions.size())
+ {
+ DefaultLogger::get()->warn("3DS: Vertex index overflow)");
+ (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
+ }
+ if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
+ {
+ DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
+ (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Generate out unique verbose format representation
void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh)
{
- // TODO: really necessary? I don't think. Just a waste of memory and time
- // to do it now in a separate buffer.
-
- // Allocate output storage
- std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3);
- std::vector<aiVector3D> vNew2;
- if (sMesh.mTexCoords.size())
- vNew2.resize(sMesh.mFaces.size() * 3);
-
- for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i)
- {
- D3DS::Face& face = sMesh.mFaces[i];
-
- // Positions
- for (unsigned int a = 0; a < 3;++a,++base)
- {
- vNew[base] = sMesh.mPositions[face.mIndices[a]];
- if (sMesh.mTexCoords.size())
- vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
-
- face.mIndices[a] = base;
- }
- }
- sMesh.mPositions = vNew;
- sMesh.mTexCoords = vNew2;
+ // TODO: really necessary? I don't think. Just a waste of memory and time
+ // to do it now in a separate buffer.
+
+ // Allocate output storage
+ std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3);
+ std::vector<aiVector3D> vNew2;
+ if (sMesh.mTexCoords.size())
+ vNew2.resize(sMesh.mFaces.size() * 3);
+
+ for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i)
+ {
+ D3DS::Face& face = sMesh.mFaces[i];
+
+ // Positions
+ for (unsigned int a = 0; a < 3;++a,++base)
+ {
+ vNew[base] = sMesh.mPositions[face.mIndices[a]];
+ if (sMesh.mTexCoords.size())
+ vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
+
+ face.mIndices[a] = base;
+ }
+ }
+ sMesh.mPositions = vNew;
+ sMesh.mTexCoords = vNew2;
}
// ------------------------------------------------------------------------------------------------
// Convert a 3DS texture to texture keys in an aiMaterial
void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
{
- // Setup the texture name
- aiString tex;
- tex.Set( texture.mMapName);
- mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
-
- // Setup the texture blend factor
- if (is_not_qnan(texture.mTextureBlend))
- mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
-
- // Setup the texture mapping mode
- mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
- mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
-
- // Mirroring - double the scaling values
- // FIXME: this is not really correct ...
- if (texture.mMapMode == aiTextureMapMode_Mirror)
- {
- texture.mScaleU *= 2.f;
- texture.mScaleV *= 2.f;
- texture.mOffsetU /= 2.f;
- texture.mOffsetV /= 2.f;
- }
-
- // Setup texture UV transformations
- mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+ // Setup the texture name
+ aiString tex;
+ tex.Set( texture.mMapName);
+ mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
+
+ // Setup the texture blend factor
+ if (is_not_qnan(texture.mTextureBlend))
+ mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+
+ // Setup the texture mapping mode
+ mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
+ mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
+
+ // Mirroring - double the scaling values
+ // FIXME: this is not really correct ...
+ if (texture.mMapMode == aiTextureMapMode_Mirror)
+ {
+ texture.mScaleU *= 2.f;
+ texture.mScaleV *= 2.f;
+ texture.mOffsetU /= 2.f;
+ texture.mOffsetV /= 2.f;
+ }
+
+ // Setup texture UV transformations
+ mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------
// Convert a 3DS material to an aiMaterial
void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
- aiMaterial& mat)
+ aiMaterial& mat)
{
- // NOTE: Pass the background image to the viewer by bypassing the
- // material system. This is an evil hack, never do it again!
- if (0 != mBackgroundImage.length() && bHasBG)
- {
- aiString tex;
- tex.Set( mBackgroundImage);
- mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
-
- // Be sure this is only done for the first material
- mBackgroundImage = std::string("");
- }
-
- // At first add the base ambient color of the scene to the material
- oldMat.mAmbient.r += mClrAmbient.r;
- oldMat.mAmbient.g += mClrAmbient.g;
- oldMat.mAmbient.b += mClrAmbient.b;
-
- aiString name;
- name.Set( oldMat.mName);
- mat.AddProperty( &name, AI_MATKEY_NAME);
-
- // Material colors
- mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
- mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
- mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-
- // Phong shininess and shininess strength
- if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
- D3DS::Discreet3DS::Metal == oldMat.mShading)
- {
- if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength)
- {
- oldMat.mShading = D3DS::Discreet3DS::Gouraud;
- }
- else
- {
- mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
- mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
- }
- }
-
- // Opacity
- mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
-
- // Bump height scaling
- mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
-
- // Two sided rendering?
- if (oldMat.mTwoSided)
- {
- int i = 1;
- mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
- }
-
- // Shading mode
- aiShadingMode eShading = aiShadingMode_NoShading;
- switch (oldMat.mShading)
- {
- case D3DS::Discreet3DS::Flat:
- eShading = aiShadingMode_Flat; break;
-
- // I don't know what "Wire" shading should be,
- // assume it is simple lambertian diffuse shading
- case D3DS::Discreet3DS::Wire:
- {
- // Set the wireframe flag
- unsigned int iWire = 1;
- mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
- }
-
- case D3DS::Discreet3DS::Gouraud:
- eShading = aiShadingMode_Gouraud; break;
-
- // assume cook-torrance shading for metals.
- case D3DS::Discreet3DS::Phong :
- eShading = aiShadingMode_Phong; break;
-
- case D3DS::Discreet3DS::Metal :
- eShading = aiShadingMode_CookTorrance; break;
-
- // FIX to workaround a warning with GCC 4 who complained
- // about a missing case Blinn: here - Blinn isn't a valid
- // value in the 3DS Loader, it is just needed for ASE
- case D3DS::Discreet3DS::Blinn :
- eShading = aiShadingMode_Blinn; break;
- }
- mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
-
- // DIFFUSE texture
- if( oldMat.sTexDiffuse.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
-
- // SPECULAR texture
- if( oldMat.sTexSpecular.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
-
- // OPACITY texture
- if( oldMat.sTexOpacity.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
-
- // EMISSIVE texture
- if( oldMat.sTexEmissive.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
-
- // BUMP texture
- if( oldMat.sTexBump.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
-
- // SHININESS texture
- if( oldMat.sTexShininess.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
-
- // REFLECTION texture
- if( oldMat.sTexReflective.mMapName.length() > 0)
- CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION);
-
- // Store the name of the material itself, too
- if( oldMat.mName.length()) {
- aiString tex;
- tex.Set( oldMat.mName);
- mat.AddProperty( &tex, AI_MATKEY_NAME);
- }
+ // NOTE: Pass the background image to the viewer by bypassing the
+ // material system. This is an evil hack, never do it again!
+ if (0 != mBackgroundImage.length() && bHasBG)
+ {
+ aiString tex;
+ tex.Set( mBackgroundImage);
+ mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
+
+ // Be sure this is only done for the first material
+ mBackgroundImage = std::string("");
+ }
+
+ // At first add the base ambient color of the scene to the material
+ oldMat.mAmbient.r += mClrAmbient.r;
+ oldMat.mAmbient.g += mClrAmbient.g;
+ oldMat.mAmbient.b += mClrAmbient.b;
+
+ aiString name;
+ name.Set( oldMat.mName);
+ mat.AddProperty( &name, AI_MATKEY_NAME);
+
+ // Material colors
+ mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+ mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+ mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+
+ // Phong shininess and shininess strength
+ if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
+ D3DS::Discreet3DS::Metal == oldMat.mShading)
+ {
+ if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength)
+ {
+ oldMat.mShading = D3DS::Discreet3DS::Gouraud;
+ }
+ else
+ {
+ mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+ mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+ }
+ }
+
+ // Opacity
+ mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
+
+ // Bump height scaling
+ mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
+
+ // Two sided rendering?
+ if (oldMat.mTwoSided)
+ {
+ int i = 1;
+ mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
+ }
+
+ // Shading mode
+ aiShadingMode eShading = aiShadingMode_NoShading;
+ switch (oldMat.mShading)
+ {
+ case D3DS::Discreet3DS::Flat:
+ eShading = aiShadingMode_Flat; break;
+
+ // I don't know what "Wire" shading should be,
+ // assume it is simple lambertian diffuse shading
+ case D3DS::Discreet3DS::Wire:
+ {
+ // Set the wireframe flag
+ unsigned int iWire = 1;
+ mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+ }
+
+ case D3DS::Discreet3DS::Gouraud:
+ eShading = aiShadingMode_Gouraud; break;
+
+ // assume cook-torrance shading for metals.
+ case D3DS::Discreet3DS::Phong :
+ eShading = aiShadingMode_Phong; break;
+
+ case D3DS::Discreet3DS::Metal :
+ eShading = aiShadingMode_CookTorrance; break;
+
+ // FIX to workaround a warning with GCC 4 who complained
+ // about a missing case Blinn: here - Blinn isn't a valid
+ // value in the 3DS Loader, it is just needed for ASE
+ case D3DS::Discreet3DS::Blinn :
+ eShading = aiShadingMode_Blinn; break;
+ }
+ mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+
+ // DIFFUSE texture
+ if( oldMat.sTexDiffuse.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
+
+ // SPECULAR texture
+ if( oldMat.sTexSpecular.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
+
+ // OPACITY texture
+ if( oldMat.sTexOpacity.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
+
+ // EMISSIVE texture
+ if( oldMat.sTexEmissive.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
+
+ // BUMP texture
+ if( oldMat.sTexBump.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
+
+ // SHININESS texture
+ if( oldMat.sTexShininess.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
+
+ // REFLECTION texture
+ if( oldMat.sTexReflective.mMapName.length() > 0)
+ CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION);
+
+ // Store the name of the material itself, too
+ if( oldMat.mName.length()) {
+ aiString tex;
+ tex.Set( oldMat.mName);
+ mat.AddProperty( &tex, AI_MATKEY_NAME);
+ }
}
// ------------------------------------------------------------------------------------------------
// Split meshes by their materials and generate output aiMesh'es
void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
{
- std::vector<aiMesh*> avOutMeshes;
- avOutMeshes.reserve(mScene->mMeshes.size() * 2);
-
- unsigned int iFaceCnt = 0,num = 0;
- aiString name;
-
- // we need to split all meshes by their materials
- for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) {
- boost::scoped_array< std::vector<unsigned int> > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
-
- name.length = ASSIMP_itoa10(name.data,num++);
-
- unsigned int iNum = 0;
- for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin();
- a != (*i).mFaceMaterials.end();++a,++iNum)
- {
- aiSplit[*a].push_back(iNum);
- }
- // now generate submeshes
- for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
- {
- if (aiSplit[p].empty()) {
- continue;
- }
- aiMesh* meshOut = new aiMesh();
- meshOut->mName = name;
- meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // be sure to setup the correct material index
- meshOut->mMaterialIndex = p;
-
- // use the color data as temporary storage
- meshOut->mColors[0] = (aiColor4D*)(&*i);
- avOutMeshes.push_back(meshOut);
-
- // convert vertices
- meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
- meshOut->mNumVertices = meshOut->mNumFaces*3;
-
- // allocate enough storage for faces
- meshOut->mFaces = new aiFace[meshOut->mNumFaces];
- iFaceCnt += meshOut->mNumFaces;
-
- meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
- meshOut->mNormals = new aiVector3D[meshOut->mNumVertices];
- if ((*i).mTexCoords.size())
- {
- meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices];
- }
- for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
- {
- unsigned int index = aiSplit[p][q];
- aiFace& face = meshOut->mFaces[q];
-
- face.mIndices = new unsigned int[3];
- face.mNumIndices = 3;
-
- for (unsigned int a = 0; a < 3;++a,++base)
- {
- unsigned int idx = (*i).mFaces[index].mIndices[a];
- meshOut->mVertices[base] = (*i).mPositions[idx];
- meshOut->mNormals [base] = (*i).mNormals[idx];
-
- if ((*i).mTexCoords.size())
- meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
-
- face.mIndices[a] = base;
- }
- }
- }
- }
-
- // Copy them to the output array
- pcOut->mNumMeshes = (unsigned int)avOutMeshes.size();
- pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes]();
- for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) {
- pcOut->mMeshes[a] = avOutMeshes[a];
- }
-
- // We should have at least one face here
- if (!iFaceCnt) {
- throw DeadlyImportError("No faces loaded. The mesh is empty");
- }
+ std::vector<aiMesh*> avOutMeshes;
+ avOutMeshes.reserve(mScene->mMeshes.size() * 2);
+
+ unsigned int iFaceCnt = 0,num = 0;
+ aiString name;
+
+ // we need to split all meshes by their materials
+ for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) {
+ std::unique_ptr< std::vector<unsigned int>[] > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
+
+ name.length = ASSIMP_itoa10(name.data,num++);
+
+ unsigned int iNum = 0;
+ for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin();
+ a != (*i).mFaceMaterials.end();++a,++iNum)
+ {
+ aiSplit[*a].push_back(iNum);
+ }
+ // now generate submeshes
+ for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
+ {
+ if (aiSplit[p].empty()) {
+ continue;
+ }
+ aiMesh* meshOut = new aiMesh();
+ meshOut->mName = name;
+ meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // be sure to setup the correct material index
+ meshOut->mMaterialIndex = p;
+
+ // use the color data as temporary storage
+ meshOut->mColors[0] = (aiColor4D*)(&*i);
+ avOutMeshes.push_back(meshOut);
+
+ // convert vertices
+ meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
+ meshOut->mNumVertices = meshOut->mNumFaces*3;
+
+ // allocate enough storage for faces
+ meshOut->mFaces = new aiFace[meshOut->mNumFaces];
+ iFaceCnt += meshOut->mNumFaces;
+
+ meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
+ meshOut->mNormals = new aiVector3D[meshOut->mNumVertices];
+ if ((*i).mTexCoords.size())
+ {
+ meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices];
+ }
+ for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
+ {
+ unsigned int index = aiSplit[p][q];
+ aiFace& face = meshOut->mFaces[q];
+
+ face.mIndices = new unsigned int[3];
+ face.mNumIndices = 3;
+
+ for (unsigned int a = 0; a < 3;++a,++base)
+ {
+ unsigned int idx = (*i).mFaces[index].mIndices[a];
+ meshOut->mVertices[base] = (*i).mPositions[idx];
+ meshOut->mNormals [base] = (*i).mNormals[idx];
+
+ if ((*i).mTexCoords.size())
+ meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
+
+ face.mIndices[a] = base;
+ }
+ }
+ }
+ }
+
+ // Copy them to the output array
+ pcOut->mNumMeshes = (unsigned int)avOutMeshes.size();
+ pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes]();
+ for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) {
+ pcOut->mMeshes[a] = avOutMeshes[a];
+ }
+
+ // We should have at least one face here
+ if (!iFaceCnt) {
+ throw DeadlyImportError("No faces loaded. The mesh is empty");
+ }
}
// ------------------------------------------------------------------------------------------------
// Add a node to the scenegraph and setup its final transformation
void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
- D3DS::Node* pcIn, aiMatrix4x4& /*absTrafo*/)
+ D3DS::Node* pcIn, aiMatrix4x4& /*absTrafo*/)
{
- std::vector<unsigned int> iArray;
- iArray.reserve(3);
-
- aiMatrix4x4 abs;
-
- // Find all meshes with the same name as the node
- for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
- {
- const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
- ai_assert(NULL != pcMesh);
-
- if (pcIn->mName == pcMesh->mName)
- iArray.push_back(a);
- }
- if (!iArray.empty())
- {
- // The matrix should be identical for all meshes with the
- // same name. It HAS to be identical for all meshes .....
- D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]);
-
- // Compute the inverse of the transformation matrix to move the
- // vertices back to their relative and local space
- aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat;
- mInv.Inverse();mInvTransposed.Transpose();
- aiVector3D pivot = pcIn->vPivot;
-
- pcOut->mNumMeshes = (unsigned int)iArray.size();
- pcOut->mMeshes = new unsigned int[iArray.size()];
- for (unsigned int i = 0;i < iArray.size();++i) {
- const unsigned int iIndex = iArray[i];
- aiMesh* const mesh = pcSOut->mMeshes[iIndex];
-
- if (mesh->mColors[1] == NULL)
- {
- // Transform the vertices back into their local space
- // fixme: consider computing normals after this, so we don't need to transform them
- const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices;
- aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals;
-
- for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
- *pvCurrent = mInv * (*pvCurrent);
- *t2 = mInvTransposed * (*t2);
- }
-
- // Handle negative transformation matrix determinant -> invert vertex x
- if (imesh->mMat.Determinant() < 0.0f)
- {
- /* we *must* have normals */
- for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
- pvCurrent->x *= -1.f;
- t2->x *= -1.f;
- }
- DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
- }
-
- // Handle pivot point
- if (pivot.x || pivot.y || pivot.z)
- {
- for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent) {
- *pvCurrent -= pivot;
- }
- }
-
- mesh->mColors[1] = (aiColor4D*)1;
- }
- else
- mesh->mColors[1] = (aiColor4D*)1;
-
- // Setup the mesh index
- pcOut->mMeshes[i] = iIndex;
- }
- }
-
- // Setup the name of the node
- // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
- if (pcIn->mInstanceNumber > 1)
- {
- char tmp[12];
- ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
- std::string tempStr = pcIn->mName + "_inst_";
- tempStr += tmp;
- pcOut->mName.Set(tempStr);
- }
- else
- pcOut->mName.Set(pcIn->mName);
-
- // Now build the transformation matrix of the node
- // ROTATION
- if (pcIn->aRotationKeys.size()){
-
- // FIX to get to Assimp's quaternion conventions
- for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
- (*it).mValue.w *= -1.f;
- }
-
- pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() );
- }
- else if (pcIn->aCameraRollKeys.size())
- {
- aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue),
- pcOut->mTransformation);
- }
-
- // SCALING
- aiMatrix4x4& m = pcOut->mTransformation;
- if (pcIn->aScalingKeys.size())
- {
- const aiVector3D& v = pcIn->aScalingKeys[0].mValue;
- m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x;
- m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y;
- m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z;
- }
-
- // TRANSLATION
- if (pcIn->aPositionKeys.size())
- {
- const aiVector3D& v = pcIn->aPositionKeys[0].mValue;
- m.a4 += v.x;
- m.b4 += v.y;
- m.c4 += v.z;
- }
-
- // Generate animation channels for the node
- if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 ||
- pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 ||
- pcIn->aTargetPositionKeys.size() > 1)
- {
- aiAnimation* anim = pcSOut->mAnimations[0];
- ai_assert(NULL != anim);
-
- if (pcIn->aCameraRollKeys.size() > 1)
- {
- DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
-
- // Camera roll keys - in fact they're just rotations
- // around the camera's z axis. The angles are given
- // in degrees (and they're clockwise).
- pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size());
- for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i)
- {
- aiQuatKey& q = pcIn->aRotationKeys[i];
- aiFloatKey& f = pcIn->aCameraRollKeys[i];
-
- q.mTime = f.mTime;
-
- // FIX to get to Assimp quaternion conventions
- q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue));
- }
- }
+ std::vector<unsigned int> iArray;
+ iArray.reserve(3);
+
+ aiMatrix4x4 abs;
+
+ // Find all meshes with the same name as the node
+ for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
+ {
+ const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
+ ai_assert(NULL != pcMesh);
+
+ if (pcIn->mName == pcMesh->mName)
+ iArray.push_back(a);
+ }
+ if (!iArray.empty())
+ {
+ // The matrix should be identical for all meshes with the
+ // same name. It HAS to be identical for all meshes .....
+ D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]);
+
+ // Compute the inverse of the transformation matrix to move the
+ // vertices back to their relative and local space
+ aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat;
+ mInv.Inverse();mInvTransposed.Transpose();
+ aiVector3D pivot = pcIn->vPivot;
+
+ pcOut->mNumMeshes = (unsigned int)iArray.size();
+ pcOut->mMeshes = new unsigned int[iArray.size()];
+ for (unsigned int i = 0;i < iArray.size();++i) {
+ const unsigned int iIndex = iArray[i];
+ aiMesh* const mesh = pcSOut->mMeshes[iIndex];
+
+ if (mesh->mColors[1] == NULL)
+ {
+ // Transform the vertices back into their local space
+ // fixme: consider computing normals after this, so we don't need to transform them
+ const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices;
+ aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals;
+
+ for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
+ *pvCurrent = mInv * (*pvCurrent);
+ *t2 = mInvTransposed * (*t2);
+ }
+
+ // Handle negative transformation matrix determinant -> invert vertex x
+ if (imesh->mMat.Determinant() < 0.0f)
+ {
+ /* we *must* have normals */
+ for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
+ pvCurrent->x *= -1.f;
+ t2->x *= -1.f;
+ }
+ DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
+ }
+
+ // Handle pivot point
+ if (pivot.x || pivot.y || pivot.z)
+ {
+ for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent) {
+ *pvCurrent -= pivot;
+ }
+ }
+
+ mesh->mColors[1] = (aiColor4D*)1;
+ }
+ else
+ mesh->mColors[1] = (aiColor4D*)1;
+
+ // Setup the mesh index
+ pcOut->mMeshes[i] = iIndex;
+ }
+ }
+
+ // Setup the name of the node
+ // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
+ if (pcIn->mInstanceNumber > 1)
+ {
+ char tmp[12];
+ ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
+ std::string tempStr = pcIn->mName + "_inst_";
+ tempStr += tmp;
+ pcOut->mName.Set(tempStr);
+ }
+ else
+ pcOut->mName.Set(pcIn->mName);
+
+ // Now build the transformation matrix of the node
+ // ROTATION
+ if (pcIn->aRotationKeys.size()){
+
+ // FIX to get to Assimp's quaternion conventions
+ for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
+ (*it).mValue.w *= -1.f;
+ }
+
+ pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() );
+ }
+ else if (pcIn->aCameraRollKeys.size())
+ {
+ aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue),
+ pcOut->mTransformation);
+ }
+
+ // SCALING
+ aiMatrix4x4& m = pcOut->mTransformation;
+ if (pcIn->aScalingKeys.size())
+ {
+ const aiVector3D& v = pcIn->aScalingKeys[0].mValue;
+ m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x;
+ m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y;
+ m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z;
+ }
+
+ // TRANSLATION
+ if (pcIn->aPositionKeys.size())
+ {
+ const aiVector3D& v = pcIn->aPositionKeys[0].mValue;
+ m.a4 += v.x;
+ m.b4 += v.y;
+ m.c4 += v.z;
+ }
+
+ // Generate animation channels for the node
+ if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 ||
+ pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 ||
+ pcIn->aTargetPositionKeys.size() > 1)
+ {
+ aiAnimation* anim = pcSOut->mAnimations[0];
+ ai_assert(NULL != anim);
+
+ if (pcIn->aCameraRollKeys.size() > 1)
+ {
+ DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
+
+ // Camera roll keys - in fact they're just rotations
+ // around the camera's z axis. The angles are given
+ // in degrees (and they're clockwise).
+ pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size());
+ for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i)
+ {
+ aiQuatKey& q = pcIn->aRotationKeys[i];
+ aiFloatKey& f = pcIn->aCameraRollKeys[i];
+
+ q.mTime = f.mTime;
+
+ // FIX to get to Assimp quaternion conventions
+ q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue));
+ }
+ }
#if 0
- if (pcIn->aTargetPositionKeys.size() > 1)
- {
- DefaultLogger::get()->debug("3DS: Converting target track ...");
-
- // Camera or spot light - need to convert the separate
- // target position channel to our representation
- TargetAnimationHelper helper;
-
- if (pcIn->aPositionKeys.empty())
- {
- // We can just pass zero here ...
- helper.SetFixedMainAnimationChannel(aiVector3D());
- }
- else helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
- helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
-
- // Do the conversion
- std::vector<aiVectorKey> distanceTrack;
- helper.Process(&distanceTrack);
-
- // Now add a new node as child, name it <ourName>.Target
- // and assign the distance track to it. This is that the
- // information where the target is and how it moves is
- // not lost
- D3DS::Node* nd = new D3DS::Node();
- pcIn->push_back(nd);
-
- nd->mName = pcIn->mName + ".Target";
-
- aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
- nda->mNodeName.Set(nd->mName);
-
- nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
- nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
- ::memcpy(nda->mPositionKeys,&distanceTrack[0],
- sizeof(aiVectorKey)*nda->mNumPositionKeys);
- }
+ if (pcIn->aTargetPositionKeys.size() > 1)
+ {
+ DefaultLogger::get()->debug("3DS: Converting target track ...");
+
+ // Camera or spot light - need to convert the separate
+ // target position channel to our representation
+ TargetAnimationHelper helper;
+
+ if (pcIn->aPositionKeys.empty())
+ {
+ // We can just pass zero here ...
+ helper.SetFixedMainAnimationChannel(aiVector3D());
+ }
+ else helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
+ helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
+
+ // Do the conversion
+ std::vector<aiVectorKey> distanceTrack;
+ helper.Process(&distanceTrack);
+
+ // Now add a new node as child, name it <ourName>.Target
+ // and assign the distance track to it. This is that the
+ // information where the target is and how it moves is
+ // not lost
+ D3DS::Node* nd = new D3DS::Node();
+ pcIn->push_back(nd);
+
+ nd->mName = pcIn->mName + ".Target";
+
+ aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+ nda->mNodeName.Set(nd->mName);
+
+ nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
+ nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
+ ::memcpy(nda->mPositionKeys,&distanceTrack[0],
+ sizeof(aiVectorKey)*nda->mNumPositionKeys);
+ }
#endif
- // Cameras or lights define their transformation in their parent node and in the
- // corresponding light or camera chunks. However, we read and process the latter
- // to to be able to return valid cameras/lights even if no scenegraph is given.
- for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) {
- if (pcSOut->mCameras[n]->mName == pcOut->mName) {
- pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
- }
- }
- for (unsigned int n = 0; n < pcSOut->mNumLights;++n) {
- if (pcSOut->mLights[n]->mName == pcOut->mName) {
- pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
- }
- }
-
- // Allocate a new node anim and setup its name
- aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
- nda->mNodeName.Set(pcIn->mName);
-
- // POSITION keys
- if (pcIn->aPositionKeys.size() > 0)
- {
- nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
- nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
- ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
- sizeof(aiVectorKey)*nda->mNumPositionKeys);
- }
-
- // ROTATION keys
- if (pcIn->aRotationKeys.size() > 0)
- {
- nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
- nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
-
- // Rotations are quaternion offsets
- aiQuaternion abs;
- for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
- {
- const aiQuatKey& q = pcIn->aRotationKeys[n];
-
- abs = (n ? abs * q.mValue : q.mValue);
- nda->mRotationKeys[n].mTime = q.mTime;
- nda->mRotationKeys[n].mValue = abs.Normalize();
- }
- }
-
- // SCALING keys
- if (pcIn->aScalingKeys.size() > 0)
- {
- nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
- nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
- ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
- sizeof(aiVectorKey)*nda->mNumScalingKeys);
- }
- }
-
- // Allocate storage for children
- pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
- pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
-
- // Recursively process all children
- const unsigned int size = pcIn->mChildren.size();
- for (unsigned int i = 0; i < size;++i)
- {
- pcOut->mChildren[i] = new aiNode();
- pcOut->mChildren[i]->mParent = pcOut;
- AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs);
- }
+ // Cameras or lights define their transformation in their parent node and in the
+ // corresponding light or camera chunks. However, we read and process the latter
+ // to to be able to return valid cameras/lights even if no scenegraph is given.
+ for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) {
+ if (pcSOut->mCameras[n]->mName == pcOut->mName) {
+ pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
+ }
+ }
+ for (unsigned int n = 0; n < pcSOut->mNumLights;++n) {
+ if (pcSOut->mLights[n]->mName == pcOut->mName) {
+ pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
+ }
+ }
+
+ // Allocate a new node anim and setup its name
+ aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+ nda->mNodeName.Set(pcIn->mName);
+
+ // POSITION keys
+ if (pcIn->aPositionKeys.size() > 0)
+ {
+ nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
+ nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
+ ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
+ sizeof(aiVectorKey)*nda->mNumPositionKeys);
+ }
+
+ // ROTATION keys
+ if (pcIn->aRotationKeys.size() > 0)
+ {
+ nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
+ nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
+
+ // Rotations are quaternion offsets
+ aiQuaternion abs1;
+ for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
+ {
+ const aiQuatKey& q = pcIn->aRotationKeys[n];
+
+ abs1 = (n ? abs1 * q.mValue : q.mValue);
+ nda->mRotationKeys[n].mTime = q.mTime;
+ nda->mRotationKeys[n].mValue = abs1.Normalize();
+ }
+ }
+
+ // SCALING keys
+ if (pcIn->aScalingKeys.size() > 0)
+ {
+ nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
+ nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
+ ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
+ sizeof(aiVectorKey)*nda->mNumScalingKeys);
+ }
+ }
+
+ // Allocate storage for children
+ pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
+ pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
+
+ // Recursively process all children
+ const unsigned int size = pcIn->mChildren.size();
+ for (unsigned int i = 0; i < size;++i)
+ {
+ pcOut->mChildren[i] = new aiNode();
+ pcOut->mChildren[i]->mParent = pcOut;
+ AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs);
+ }
}
// ------------------------------------------------------------------------------------------------
// Find out how many node animation channels we'll have finally
void CountTracks(D3DS::Node* node, unsigned int& cnt)
{
- //////////////////////////////////////////////////////////////////////////////
- // We will never generate more than one channel for a node, so
- // this is rather easy here.
-
- if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 ||
- node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 ||
- node->aTargetPositionKeys.size() > 1)
- {
- ++cnt;
-
- // account for the additional channel for the camera/spotlight target position
- if (node->aTargetPositionKeys.size() > 1)++cnt;
- }
-
- // Recursively process all children
- for (unsigned int i = 0; i < node->mChildren.size();++i)
- CountTracks(node->mChildren[i],cnt);
+ //////////////////////////////////////////////////////////////////////////////
+ // We will never generate more than one channel for a node, so
+ // this is rather easy here.
+
+ if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 ||
+ node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 ||
+ node->aTargetPositionKeys.size() > 1)
+ {
+ ++cnt;
+
+ // account for the additional channel for the camera/spotlight target position
+ if (node->aTargetPositionKeys.size() > 1)++cnt;
+ }
+
+ // Recursively process all children
+ for (unsigned int i = 0; i < node->mChildren.size();++i)
+ CountTracks(node->mChildren[i],cnt);
}
// ------------------------------------------------------------------------------------------------
// Generate the output node graph
void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
{
- pcOut->mRootNode = new aiNode();
- if (0 == mRootNode->mChildren.size())
- {
- //////////////////////////////////////////////////////////////////////////////
- // It seems the file is so messed up that it has not even a hierarchy.
- // generate a flat hiearachy which looks like this:
- //
- // ROOT_NODE
- // |
- // ----------------------------------------
- // | | | | |
- // MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 ....
- //
- DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
-
- pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
- mScene->mCameras.size() + mScene->mLights.size();
-
- pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
- pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
-
- // Build dummy nodes for all meshes
- unsigned int a = 0;
- for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a)
- {
- aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
- pcNode->mParent = pcOut->mRootNode;
- pcNode->mMeshes = new unsigned int[1];
- pcNode->mMeshes[0] = i;
- pcNode->mNumMeshes = 1;
-
- // Build a name for the node
- pcNode->mName.length = sprintf(pcNode->mName.data,"3DSMesh_%i",i);
- }
-
- // Build dummy nodes for all cameras
- for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a)
- {
- aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
- pcNode->mParent = pcOut->mRootNode;
-
- // Build a name for the node
- pcNode->mName = mScene->mCameras[i]->mName;
- }
-
- // Build dummy nodes for all lights
- for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a)
- {
- aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
- pcNode->mParent = pcOut->mRootNode;
-
- // Build a name for the node
- pcNode->mName = mScene->mLights[i]->mName;
- }
- }
- else
- {
- // First of all: find out how many scaling, rotation and translation
- // animation tracks we'll have afterwards
- unsigned int numChannel = 0;
- CountTracks(mRootNode,numChannel);
-
- if (numChannel)
- {
- // Allocate a primary animation channel
- pcOut->mNumAnimations = 1;
- pcOut->mAnimations = new aiAnimation*[1];
- aiAnimation* anim = pcOut->mAnimations[0] = new aiAnimation();
-
- anim->mName.Set("3DSMasterAnim");
-
- // Allocate enough storage for all node animation channels,
- // but don't set the mNumChannels member - we'll use it to
- // index into the array
- anim->mChannels = new aiNodeAnim*[numChannel];
- }
-
- aiMatrix4x4 m;
- AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m);
- }
-
- // We used the first and second vertex color set to store some temporary values so we need to cleanup here
- for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a)
- {
- pcOut->mMeshes[a]->mColors[0] = NULL;
- pcOut->mMeshes[a]->mColors[1] = NULL;
- }
-
- pcOut->mRootNode->mTransformation = aiMatrix4x4(
- 1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,
- 0.f,-1.f,0.f,0.f,
- 0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation;
-
- // If the root node is unnamed name it "<3DSRoot>"
- if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) ||
- (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') )
- {
- pcOut->mRootNode->mName.Set("<3DSRoot>");
- }
+ pcOut->mRootNode = new aiNode();
+ if (0 == mRootNode->mChildren.size())
+ {
+ //////////////////////////////////////////////////////////////////////////////
+ // It seems the file is so messed up that it has not even a hierarchy.
+ // generate a flat hiearachy which looks like this:
+ //
+ // ROOT_NODE
+ // |
+ // ----------------------------------------
+ // | | | | |
+ // MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 ....
+ //
+ DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
+
+ pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
+ mScene->mCameras.size() + mScene->mLights.size();
+
+ pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
+ pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
+
+ // Build dummy nodes for all meshes
+ unsigned int a = 0;
+ for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a)
+ {
+ aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+ pcNode->mParent = pcOut->mRootNode;
+ pcNode->mMeshes = new unsigned int[1];
+ pcNode->mMeshes[0] = i;
+ pcNode->mNumMeshes = 1;
+
+ // Build a name for the node
+ pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u",i);
+ }
+
+ // Build dummy nodes for all cameras
+ for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a)
+ {
+ aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+ pcNode->mParent = pcOut->mRootNode;
+
+ // Build a name for the node
+ pcNode->mName = mScene->mCameras[i]->mName;
+ }
+
+ // Build dummy nodes for all lights
+ for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a)
+ {
+ aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+ pcNode->mParent = pcOut->mRootNode;
+
+ // Build a name for the node
+ pcNode->mName = mScene->mLights[i]->mName;
+ }
+ }
+ else
+ {
+ // First of all: find out how many scaling, rotation and translation
+ // animation tracks we'll have afterwards
+ unsigned int numChannel = 0;
+ CountTracks(mRootNode,numChannel);
+
+ if (numChannel)
+ {
+ // Allocate a primary animation channel
+ pcOut->mNumAnimations = 1;
+ pcOut->mAnimations = new aiAnimation*[1];
+ aiAnimation* anim = pcOut->mAnimations[0] = new aiAnimation();
+
+ anim->mName.Set("3DSMasterAnim");
+
+ // Allocate enough storage for all node animation channels,
+ // but don't set the mNumChannels member - we'll use it to
+ // index into the array
+ anim->mChannels = new aiNodeAnim*[numChannel];
+ }
+
+ aiMatrix4x4 m;
+ AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m);
+ }
+
+ // We used the first and second vertex color set to store some temporary values so we need to cleanup here
+ for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a)
+ {
+ pcOut->mMeshes[a]->mColors[0] = NULL;
+ pcOut->mMeshes[a]->mColors[1] = NULL;
+ }
+
+ pcOut->mRootNode->mTransformation = aiMatrix4x4(
+ 1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,
+ 0.f,-1.f,0.f,0.f,
+ 0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation;
+
+ // If the root node is unnamed name it "<3DSRoot>"
+ if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) ||
+ (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') )
+ {
+ pcOut->mRootNode->mName.Set("<3DSRoot>");
+ }
}
// ------------------------------------------------------------------------------------------------
// Convert all meshes in the scene and generate the final output scene.
void Discreet3DSImporter::ConvertScene(aiScene* pcOut)
{
- // Allocate enough storage for all output materials
- pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
- pcOut->mMaterials = new aiMaterial*[pcOut->mNumMaterials];
-
- // ... and convert the 3DS materials to aiMaterial's
- for (unsigned int i = 0; i < pcOut->mNumMaterials;++i)
- {
- aiMaterial* pcNew = new aiMaterial();
- ConvertMaterial(mScene->mMaterials[i],*pcNew);
- pcOut->mMaterials[i] = pcNew;
- }
-
- // Generate the output mesh list
- ConvertMeshes(pcOut);
-
- // Now copy all light sources to the output scene
- pcOut->mNumLights = (unsigned int)mScene->mLights.size();
- if (pcOut->mNumLights)
- {
- pcOut->mLights = new aiLight*[pcOut->mNumLights];
- ::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights);
- }
-
- // Now copy all cameras to the output scene
- pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
- if (pcOut->mNumCameras)
- {
- pcOut->mCameras = new aiCamera*[pcOut->mNumCameras];
- ::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras);
- }
+ // Allocate enough storage for all output materials
+ pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
+ pcOut->mMaterials = new aiMaterial*[pcOut->mNumMaterials];
+
+ // ... and convert the 3DS materials to aiMaterial's
+ for (unsigned int i = 0; i < pcOut->mNumMaterials;++i)
+ {
+ aiMaterial* pcNew = new aiMaterial();
+ ConvertMaterial(mScene->mMaterials[i],*pcNew);
+ pcOut->mMaterials[i] = pcNew;
+ }
+
+ // Generate the output mesh list
+ ConvertMeshes(pcOut);
+
+ // Now copy all light sources to the output scene
+ pcOut->mNumLights = (unsigned int)mScene->mLights.size();
+ if (pcOut->mNumLights)
+ {
+ pcOut->mLights = new aiLight*[pcOut->mNumLights];
+ ::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights);
+ }
+
+ // Now copy all cameras to the output scene
+ pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
+ if (pcOut->mNumCameras)
+ {
+ pcOut->mCameras = new aiCamera*[pcOut->mNumCameras];
+ ::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras);
+ }
}
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
diff --git a/src/3rdparty/assimp/code/3DSExporter.cpp b/src/3rdparty/assimp/code/3DSExporter.cpp
new file mode 100644
index 000000000..5bb79408f
--- /dev/null
+++ b/src/3rdparty/assimp/code/3DSExporter.cpp
@@ -0,0 +1,565 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
+
+#include "3DSExporter.h"
+#include "3DSLoader.h"
+#include "SceneCombiner.h"
+#include "SplitLargeMeshes.h"
+#include "StringComparison.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Exporter.hpp>
+#include <memory>
+
+using namespace Assimp;
+namespace Assimp {
+
+namespace {
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // Scope utility to write a 3DS file chunk.
+ //
+ // Upon construction, the chunk header is written with the chunk type (flags)
+ // filled out, but the chunk size left empty. Upon destruction, the correct chunk
+ // size based on the then-position of the output stream cursor is filled in.
+ class ChunkWriter {
+ enum {
+ CHUNK_SIZE_NOT_SET = 0xdeadbeef
+ , SIZE_OFFSET = 2
+ };
+ public:
+
+ ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
+ : writer(writer)
+ {
+ chunk_start_pos = writer.GetCurrentPos();
+ writer.PutU2(chunk_type);
+ writer.PutU4(CHUNK_SIZE_NOT_SET);
+ }
+
+ ~ChunkWriter() {
+ std::size_t head_pos = writer.GetCurrentPos();
+
+ ai_assert(head_pos > chunk_start_pos);
+ const std::size_t chunk_size = head_pos - chunk_start_pos;
+
+ writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
+ writer.PutU4(chunk_size);
+ writer.SetCurrentPos(head_pos);
+ }
+
+ private:
+ StreamWriterLE& writer;
+ std::size_t chunk_start_pos;
+ };
+
+
+ // Return an unique name for a given |mesh| attached to |node| that
+ // preserves the mesh's given name if it has one. |index| is the index
+ // of the mesh in |aiScene::mMeshes|.
+ std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
+ static const std::string underscore = "_";
+ char postfix[10] = {0};
+ ASSIMP_itoa10(postfix, index);
+
+ std::string result = node.mName.C_Str();
+ if (mesh.mName.length > 0) {
+ result += underscore + mesh.mName.C_Str();
+ }
+ return result + underscore + postfix;
+ }
+
+ // Return an unique name for a given |mat| with original position |index|
+ // in |aiScene::mMaterials|. The name preserves the original material
+ // name if possible.
+ std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
+ static const std::string underscore = "_";
+ char postfix[10] = {0};
+ ASSIMP_itoa10(postfix, index);
+
+ aiString mat_name;
+ if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
+ return mat_name.C_Str() + underscore + postfix;
+ }
+
+ return "Material" + underscore + postfix;
+ }
+
+ // Collect world transformations for each node
+ void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
+ const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
+ trafos[node] = parent * node->mTransformation;
+ for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+ CollectTrafos(node->mChildren[i], trafos);
+ }
+ }
+
+ // Generate a flat list of the meshes (by index) assigned to each node
+ void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
+ for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+ meshes.insert(std::make_pair(node, node->mMeshes[i]));
+ }
+ for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+ CollectMeshes(node->mChildren[i], meshes);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ std::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
+ if(!outfile) {
+ throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
+ }
+
+ // TODO: This extra copy should be avoided and all of this made a preprocess
+ // requirement of the 3DS exporter.
+ //
+ // 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
+ // SplitLargeMeshes can do this, but it requires the correct limit to be set
+ // which is not possible with the current way of specifying preprocess steps
+ // in |Exporter::ExportFormatEntry|.
+ aiScene* scenecopy_tmp;
+ SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+ std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
+
+ SplitLargeMeshesProcess_Triangle tri_splitter;
+ tri_splitter.SetLimit(0xffff);
+ tri_splitter.Execute(scenecopy.get());
+
+ SplitLargeMeshesProcess_Vertex vert_splitter;
+ vert_splitter.SetLimit(0xffff);
+ vert_splitter.Execute(scenecopy.get());
+
+ // Invoke the actual exporter
+ Discreet3DSExporter exporter(outfile, scenecopy.get());
+}
+
+} // end of namespace Assimp
+
+// ------------------------------------------------------------------------------------------------
+Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* scene)
+: scene(scene)
+, writer(outfile)
+{
+ CollectTrafos(scene->mRootNode, trafos);
+ CollectMeshes(scene->mRootNode, meshes);
+
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
+
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
+ WriteMaterials();
+ WriteMeshes();
+
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
+ writer.PutF4(1.0f);
+ }
+ }
+
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
+ WriteHierarchy(*scene->mRootNode, -1, -1);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
+{
+ // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+
+ // Assimp node names are unique and distinct from all mesh-node
+ // names we generate; thus we can use them as-is
+ WriteString(node.mName);
+
+ // Two unknown int16 values - it is even unclear if 0 is a safe value
+ // but luckily importers do not know better either.
+ writer.PutI4(0);
+
+ int16_t hierarchy_pos = static_cast<int16_t>(seq);
+ if (sibling_level != -1) {
+ hierarchy_pos = sibling_level;
+ }
+
+ // Write the hierarchy position
+ writer.PutI2(hierarchy_pos);
+ }
+ }
+
+ // TODO: write transformation chunks
+
+ ++seq;
+ sibling_level = seq;
+
+ // Write all children
+ for (unsigned int i = 0; i < node.mNumChildren; ++i) {
+ seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
+ }
+
+ // Write all meshes as separate nodes to be able to reference the meshes by name
+ for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
+ const bool first_child = node.mNumChildren == 0 && i == 0;
+
+ const unsigned int mesh_idx = node.mMeshes[i];
+ const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+ WriteString(GetMeshName(mesh, mesh_idx, node));
+
+ writer.PutI4(0);
+ writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
+ ++seq;
+ }
+ }
+ return seq;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMaterials()
+{
+ for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
+ const aiMaterial& mat = *scene->mMaterials[i];
+
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
+ const std::string& name = GetMaterialName(mat, i);
+ WriteString(name);
+ }
+
+ aiColor3D color;
+ if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
+ WriteColor(color);
+ }
+
+ if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
+ WriteColor(color);
+ }
+
+ if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
+ WriteColor(color);
+ }
+
+ if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
+ WriteColor(color);
+ }
+
+ aiShadingMode shading_mode = aiShadingMode_Flat;
+ if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
+
+ Discreet3DS::shadetype3ds shading_mode_out;
+ switch(shading_mode) {
+ case aiShadingMode_Flat:
+ case aiShadingMode_NoShading:
+ shading_mode_out = Discreet3DS::Flat;
+ break;
+
+ case aiShadingMode_Gouraud:
+ case aiShadingMode_Toon:
+ case aiShadingMode_OrenNayar:
+ case aiShadingMode_Minnaert:
+ shading_mode_out = Discreet3DS::Gouraud;
+ break;
+
+ case aiShadingMode_Phong:
+ case aiShadingMode_Blinn:
+ case aiShadingMode_CookTorrance:
+ case aiShadingMode_Fresnel:
+ shading_mode_out = Discreet3DS::Phong;
+ break;
+
+ default:
+ shading_mode_out = Discreet3DS::Flat;
+ ai_assert(false);
+ };
+ writer.PutU2(static_cast<uint16_t>(shading_mode_out));
+ }
+
+
+ float f;
+ if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
+ WritePercentChunk(f);
+ }
+
+ if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
+ WritePercentChunk(f);
+ }
+
+ int twosided;
+ if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
+ writer.PutI2(1);
+ }
+
+ WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
+ WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
+ WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
+ WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
+ WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
+ WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
+ WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
+{
+ aiString path;
+ aiTextureMapMode map_mode[2] = {
+ aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
+ };
+ float blend = 1.0f;
+ if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
+ return;
+ }
+
+ // TODO: handle embedded textures properly
+ if (path.data[0] == '*') {
+ DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
+ return;
+ }
+
+ ChunkWriter chunk(writer, chunk_flags);
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
+ WriteString(path);
+ }
+
+ WritePercentChunk(blend);
+
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
+ uint16_t val = 0; // WRAP
+ if (map_mode[0] == aiTextureMapMode_Mirror) {
+ val = 0x2;
+ }
+ else if (map_mode[0] == aiTextureMapMode_Decal) {
+ val = 0x10;
+ }
+ writer.PutU2(val);
+ }
+ // TODO: export texture transformation (i.e. UV offset, scale, rotation)
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMeshes()
+{
+ // NOTE: 3DS allows for instances. However:
+ // i) not all importers support reading them
+ // ii) instances are not as flexible as they are in assimp, in particular,
+ // nodes can carry (and instance) only one mesh.
+ //
+ // This exporter currently deep clones all instanced meshes, i.e. for each mesh
+ // attached to a node a full TRIMESH chunk is written to the file.
+ //
+ // Furthermore, the TRIMESH is transformed into world space so that it will
+ // appear correctly if importers don't read the scene hierarchy at all.
+ for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
+ const aiNode& node = *(*it).first;
+ const unsigned int mesh_idx = (*it).second;
+
+ const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+ // This should not happen if the SLM step is correctly executed
+ // before the scene is handed to the exporter
+ ai_assert(mesh.mNumVertices <= 0xffff);
+ ai_assert(mesh.mNumFaces <= 0xffff);
+
+ const aiMatrix4x4& trafo = trafos[&node];
+
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
+
+ // Mesh name is tied to the node it is attached to so it can later be referenced
+ const std::string& name = GetMeshName(mesh, mesh_idx, node);
+ WriteString(name);
+
+
+ // TRIMESH chunk
+ ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
+
+ // Vertices in world space
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
+
+ const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+ writer.PutU2(count);
+ for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+ const aiVector3D& v = trafo * mesh.mVertices[i];
+ writer.PutF4(v.x);
+ writer.PutF4(v.y);
+ writer.PutF4(v.z);
+ }
+ }
+
+ // UV coordinates
+ if (mesh.HasTextureCoords(0)) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
+ const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+ writer.PutU2(count);
+
+ for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+ const aiVector3D& v = mesh.mTextureCoords[0][i];
+ writer.PutF4(v.x);
+ writer.PutF4(v.y);
+ }
+ }
+
+ // Faces (indices)
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
+
+ ai_assert(mesh.mNumFaces <= 0xffff);
+
+ // Count triangles, discard lines and points
+ uint16_t count = 0;
+ for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+ const aiFace& f = mesh.mFaces[i];
+ if (f.mNumIndices < 3) {
+ continue;
+ }
+ // TRIANGULATE step is a pre-requisite so we should not see polys here
+ ai_assert(f.mNumIndices == 3);
+ ++count;
+ }
+
+ writer.PutU2(count);
+ for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+ const aiFace& f = mesh.mFaces[i];
+ if (f.mNumIndices < 3) {
+ continue;
+ }
+
+ for (unsigned int j = 0; j < 3; ++j) {
+ ai_assert(f.mIndices[j] <= 0xffff);
+ writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
+ }
+
+ // Edge visibility flag
+ writer.PutI2(0x0);
+ }
+
+ // TODO: write smoothing groups (CHUNK_SMOOLIST)
+
+ WriteFaceMaterialChunk(mesh);
+ }
+
+ // Transformation matrix by which the mesh vertices have been pre-transformed with.
+ {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
+ for (unsigned int r = 0; r < 4; ++r) {
+ for (unsigned int c = 0; c < 3; ++c) {
+ writer.PutF4(trafo[r][c]);
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
+{
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
+ const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
+ WriteString(name);
+
+ // Because assimp splits meshes by material, only a single
+ // FACEMAT chunk needs to be written
+ ai_assert(mesh.mNumFaces <= 0xffff);
+ const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
+ writer.PutU2(count);
+
+ for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+ writer.PutU2(static_cast<uint16_t>(i));
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const std::string& s) {
+ for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
+ writer.PutI1(*it);
+ }
+ writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const aiString& s) {
+ for (std::size_t i = 0; i < s.length; ++i) {
+ writer.PutI1(s.data[i]);
+ }
+ writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
+ writer.PutF4(color.r);
+ writer.PutF4(color.g);
+ writer.PutF4(color.b);
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WritePercentChunk(float f) {
+ ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
+ writer.PutF4(f);
+}
+
+
+#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/3DSExporter.h b/src/3rdparty/assimp/code/3DSExporter.h
new file mode 100644
index 000000000..321539cff
--- /dev/null
+++ b/src/3rdparty/assimp/code/3DSExporter.h
@@ -0,0 +1,98 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file 3DSExporter.h
+ * 3DS Exporter Main Header
+ */
+#ifndef AI_3DSEXPORTER_H_INC
+#define AI_3DSEXPORTER_H_INC
+
+#include <map>
+#include <memory>
+
+#include "StreamWriter.h"
+#include "./../include/assimp/material.h"
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to a 3DS file. */
+// ------------------------------------------------------------------------------------------------
+class Discreet3DSExporter
+{
+public:
+ Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
+
+private:
+
+ void WriteMeshes();
+ void WriteMaterials();
+ void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
+
+ void WriteFaceMaterialChunk(const aiMesh& mesh);
+
+ int WriteHierarchy(const aiNode& node, int level, int sibling_level);
+
+ void WriteString(const std::string& s);
+ void WriteString(const aiString& s);
+ void WriteColor(const aiColor3D& color);
+ void WritePercentChunk(float f);
+
+private:
+
+ const aiScene* const scene;
+ StreamWriterLE writer;
+
+ std::map<const aiNode*, aiMatrix4x4> trafos;
+
+ typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+ MeshesByNodeMap meshes;
+
+};
+
+}
+
+#endif
diff --git a/src/3rdparty/assimp/code/3DSHelper.h b/src/3rdparty/assimp/code/3DSHelper.h
index 8da7f0838..5911b9d47 100644
--- a/src/3rdparty/assimp/code/3DSHelper.h
+++ b/src/3rdparty/assimp/code/3DSHelper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,9 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SpatialSort.h"
#include "SmoothingGroups.h"
+#include "StringUtils.h"
+#include "qnan.h"
+#include "./../include/assimp/material.h"
+#include "./../include/assimp/camera.h"
+#include "./../include/assimp/light.h"
+#include "./../include/assimp/anim.h"
+#include <stdio.h> //sprintf
-namespace Assimp {
-namespace D3DS {
+namespace Assimp {
+namespace D3DS {
#include "./../include/assimp/Compiler/pushpack1.h"
@@ -59,253 +66,253 @@ namespace D3DS {
class Discreet3DS
{
private:
- inline Discreet3DS() {}
+ inline Discreet3DS() {}
public:
- //! data structure for a single chunk in a .3ds file
- struct Chunk
- {
- uint16_t Flag;
- uint32_t Size;
- } PACK_STRUCT;
-
-
- //! Used for shading field in material3ds structure
- //! From AutoDesk 3ds SDK
- typedef enum
- {
- // translated to gouraud shading with wireframe active
- Wire = 0x0,
-
- // if this material is set, no vertex normals will
- // be calculated for the model. Face normals + gouraud
- Flat = 0x1,
-
- // standard gouraud shading
- Gouraud = 0x2,
-
- // phong shading
- Phong = 0x3,
-
- // cooktorrance or anistropic phong shading ...
- // the exact meaning is unknown, if you know it
- // feel free to tell me ;-)
- Metal = 0x4,
-
- // required by the ASE loader
- Blinn = 0x5
- } shadetype3ds;
-
- // Flags for animated keys
- enum
- {
- KEY_USE_TENS = 0x1,
- KEY_USE_CONT = 0x2,
- KEY_USE_BIAS = 0x4,
- KEY_USE_EASE_TO = 0x8,
- KEY_USE_EASE_FROM = 0x10
- } ;
-
- enum
- {
-
- // ********************************************************************
- // Basic chunks which can be found everywhere in the file
- CHUNK_VERSION = 0x0002,
- CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
- CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
-
- // Linear color values (gamma = 2.2?)
- CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
- CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
-
- CHUNK_PERCENTW = 0x0030, // int2 percentage
- CHUNK_PERCENTF = 0x0031, // float4 percentage
- // ********************************************************************
-
- // Prj master chunk
- CHUNK_PRJ = 0xC23D,
-
- // MDLI master chunk
- CHUNK_MLI = 0x3DAA,
-
- // Primary main chunk of the .3ds file
- CHUNK_MAIN = 0x4D4D,
-
- // Mesh main chunk
- CHUNK_OBJMESH = 0x3D3D,
-
- // Specifies the background color of the .3ds file
- // This is passed through the material system for
- // viewing purposes.
- CHUNK_BKGCOLOR = 0x1200,
-
- // Specifies the ambient base color of the scene.
- // This is added to all materials in the file
- CHUNK_AMBCOLOR = 0x2100,
-
- // Specifies the background image for the whole scene
- // This value is passed through the material system
- // to the viewer
- CHUNK_BIT_MAP = 0x1100,
- CHUNK_BIT_MAP_EXISTS = 0x1101,
-
- // ********************************************************************
- // Viewport related stuff. Ignored
- CHUNK_DEFAULT_VIEW = 0x3000,
- CHUNK_VIEW_TOP = 0x3010,
- CHUNK_VIEW_BOTTOM = 0x3020,
- CHUNK_VIEW_LEFT = 0x3030,
- CHUNK_VIEW_RIGHT = 0x3040,
- CHUNK_VIEW_FRONT = 0x3050,
- CHUNK_VIEW_BACK = 0x3060,
- CHUNK_VIEW_USER = 0x3070,
- CHUNK_VIEW_CAMERA = 0x3080,
- // ********************************************************************
-
- // Mesh chunks
- CHUNK_OBJBLOCK = 0x4000,
- CHUNK_TRIMESH = 0x4100,
- CHUNK_VERTLIST = 0x4110,
- CHUNK_VERTFLAGS = 0x4111,
- CHUNK_FACELIST = 0x4120,
- CHUNK_FACEMAT = 0x4130,
- CHUNK_MAPLIST = 0x4140,
- CHUNK_SMOOLIST = 0x4150,
- CHUNK_TRMATRIX = 0x4160,
- CHUNK_MESHCOLOR = 0x4165,
- CHUNK_TXTINFO = 0x4170,
- CHUNK_LIGHT = 0x4600,
- CHUNK_CAMERA = 0x4700,
- CHUNK_HIERARCHY = 0x4F00,
-
- // Specifies the global scaling factor. This is applied
- // to the root node's transformation matrix
- CHUNK_MASTER_SCALE = 0x0100,
-
- // ********************************************************************
- // Material chunks
- CHUNK_MAT_MATERIAL = 0xAFFF,
-
- // asciiz containing the name of the material
- CHUNK_MAT_MATNAME = 0xA000,
- CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
- CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
- CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
-
- // Specifies the shininess of the material
- // followed by percentage chunk
- CHUNK_MAT_SHININESS = 0xA040,
- CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
-
- // Specifies the shading mode to be used
- // followed by a short
- CHUNK_MAT_SHADING = 0xA100,
-
- // NOTE: Emissive color (self illumination) seems not
- // to be a color but a single value, type is unknown.
- // Make the parser accept both of them.
- // followed by percentage chunk (?)
- CHUNK_MAT_SELF_ILLUM = 0xA080,
-
- // Always followed by percentage chunk (?)
- CHUNK_MAT_SELF_ILPCT = 0xA084,
-
- // Always followed by percentage chunk
- CHUNK_MAT_TRANSPARENCY = 0xA050,
-
- // Diffuse texture channel 0
- CHUNK_MAT_TEXTURE = 0xA200,
-
- // Contains opacity information for each texel
- CHUNK_MAT_OPACMAP = 0xA210,
-
- // Contains a reflection map to be used to reflect
- // the environment. This is partially supported.
- CHUNK_MAT_REFLMAP = 0xA220,
-
- // Self Illumination map (emissive colors)
- CHUNK_MAT_SELFIMAP = 0xA33d,
-
- // Bumpmap. Not specified whether it is a heightmap
- // or a normal map. Assme it is a heightmap since
- // artist normally prefer this format.
- CHUNK_MAT_BUMPMAP = 0xA230,
-
- // Specular map. Seems to influence the specular color
- CHUNK_MAT_SPECMAP = 0xA204,
-
- // Holds shininess data.
- CHUNK_MAT_MAT_SHINMAP = 0xA33C,
-
- // Scaling in U/V direction.
- // (need to gen separate UV coordinate set
- // and do this by hand)
- CHUNK_MAT_MAP_USCALE = 0xA354,
- CHUNK_MAT_MAP_VSCALE = 0xA356,
-
- // Translation in U/V direction.
- // (need to gen separate UV coordinate set
- // and do this by hand)
- CHUNK_MAT_MAP_UOFFSET = 0xA358,
- CHUNK_MAT_MAP_VOFFSET = 0xA35a,
-
- // UV-coordinates rotation around the z-axis
- // Assumed to be in radians.
- CHUNK_MAT_MAP_ANG = 0xA35C,
-
- // Tiling flags for 3DS files
- CHUNK_MAT_MAP_TILING = 0xa351,
-
- // Specifies the file name of a texture
- CHUNK_MAPFILE = 0xA300,
-
- // Specifies whether a materail requires two-sided rendering
- CHUNK_MAT_TWO_SIDE = 0xA081,
- // ********************************************************************
-
- // Main keyframer chunk. Contains translation/rotation/scaling data
- CHUNK_KEYFRAMER = 0xB000,
-
- // Supported sub chunks
- CHUNK_TRACKINFO = 0xB002,
- CHUNK_TRACKOBJNAME = 0xB010,
- CHUNK_TRACKDUMMYOBJNAME = 0xB011,
- CHUNK_TRACKPIVOT = 0xB013,
- CHUNK_TRACKPOS = 0xB020,
- CHUNK_TRACKROTATE = 0xB021,
- CHUNK_TRACKSCALE = 0xB022,
-
- // ********************************************************************
- // Keyframes for various other stuff in the file
- // Partially ignored
- CHUNK_AMBIENTKEY = 0xB001,
- CHUNK_TRACKMORPH = 0xB026,
- CHUNK_TRACKHIDE = 0xB029,
- CHUNK_OBJNUMBER = 0xB030,
- CHUNK_TRACKCAMERA = 0xB003,
- CHUNK_TRACKFOV = 0xB023,
- CHUNK_TRACKROLL = 0xB024,
- CHUNK_TRACKCAMTGT = 0xB004,
- CHUNK_TRACKLIGHT = 0xB005,
- CHUNK_TRACKLIGTGT = 0xB006,
- CHUNK_TRACKSPOTL = 0xB007,
- CHUNK_FRAMES = 0xB008,
- // ********************************************************************
-
- // light sub-chunks
- CHUNK_DL_OFF = 0x4620,
- CHUNK_DL_OUTER_RANGE = 0x465A,
- CHUNK_DL_INNER_RANGE = 0x4659,
- CHUNK_DL_MULTIPLIER = 0x465B,
- CHUNK_DL_EXCLUDE = 0x4654,
- CHUNK_DL_ATTENUATE = 0x4625,
- CHUNK_DL_SPOTLIGHT = 0x4610,
-
- // camera sub-chunks
- CHUNK_CAM_RANGES = 0x4720
- };
+ //! data structure for a single chunk in a .3ds file
+ struct Chunk
+ {
+ uint16_t Flag;
+ uint32_t Size;
+ } PACK_STRUCT;
+
+
+ //! Used for shading field in material3ds structure
+ //! From AutoDesk 3ds SDK
+ typedef enum
+ {
+ // translated to gouraud shading with wireframe active
+ Wire = 0x0,
+
+ // if this material is set, no vertex normals will
+ // be calculated for the model. Face normals + gouraud
+ Flat = 0x1,
+
+ // standard gouraud shading
+ Gouraud = 0x2,
+
+ // phong shading
+ Phong = 0x3,
+
+ // cooktorrance or anistropic phong shading ...
+ // the exact meaning is unknown, if you know it
+ // feel free to tell me ;-)
+ Metal = 0x4,
+
+ // required by the ASE loader
+ Blinn = 0x5
+ } shadetype3ds;
+
+ // Flags for animated keys
+ enum
+ {
+ KEY_USE_TENS = 0x1,
+ KEY_USE_CONT = 0x2,
+ KEY_USE_BIAS = 0x4,
+ KEY_USE_EASE_TO = 0x8,
+ KEY_USE_EASE_FROM = 0x10
+ } ;
+
+ enum
+ {
+
+ // ********************************************************************
+ // Basic chunks which can be found everywhere in the file
+ CHUNK_VERSION = 0x0002,
+ CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
+ CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
+
+ // Linear color values (gamma = 2.2?)
+ CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
+ CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
+
+ CHUNK_PERCENTW = 0x0030, // int2 percentage
+ CHUNK_PERCENTF = 0x0031, // float4 percentage
+ // ********************************************************************
+
+ // Prj master chunk
+ CHUNK_PRJ = 0xC23D,
+
+ // MDLI master chunk
+ CHUNK_MLI = 0x3DAA,
+
+ // Primary main chunk of the .3ds file
+ CHUNK_MAIN = 0x4D4D,
+
+ // Mesh main chunk
+ CHUNK_OBJMESH = 0x3D3D,
+
+ // Specifies the background color of the .3ds file
+ // This is passed through the material system for
+ // viewing purposes.
+ CHUNK_BKGCOLOR = 0x1200,
+
+ // Specifies the ambient base color of the scene.
+ // This is added to all materials in the file
+ CHUNK_AMBCOLOR = 0x2100,
+
+ // Specifies the background image for the whole scene
+ // This value is passed through the material system
+ // to the viewer
+ CHUNK_BIT_MAP = 0x1100,
+ CHUNK_BIT_MAP_EXISTS = 0x1101,
+
+ // ********************************************************************
+ // Viewport related stuff. Ignored
+ CHUNK_DEFAULT_VIEW = 0x3000,
+ CHUNK_VIEW_TOP = 0x3010,
+ CHUNK_VIEW_BOTTOM = 0x3020,
+ CHUNK_VIEW_LEFT = 0x3030,
+ CHUNK_VIEW_RIGHT = 0x3040,
+ CHUNK_VIEW_FRONT = 0x3050,
+ CHUNK_VIEW_BACK = 0x3060,
+ CHUNK_VIEW_USER = 0x3070,
+ CHUNK_VIEW_CAMERA = 0x3080,
+ // ********************************************************************
+
+ // Mesh chunks
+ CHUNK_OBJBLOCK = 0x4000,
+ CHUNK_TRIMESH = 0x4100,
+ CHUNK_VERTLIST = 0x4110,
+ CHUNK_VERTFLAGS = 0x4111,
+ CHUNK_FACELIST = 0x4120,
+ CHUNK_FACEMAT = 0x4130,
+ CHUNK_MAPLIST = 0x4140,
+ CHUNK_SMOOLIST = 0x4150,
+ CHUNK_TRMATRIX = 0x4160,
+ CHUNK_MESHCOLOR = 0x4165,
+ CHUNK_TXTINFO = 0x4170,
+ CHUNK_LIGHT = 0x4600,
+ CHUNK_CAMERA = 0x4700,
+ CHUNK_HIERARCHY = 0x4F00,
+
+ // Specifies the global scaling factor. This is applied
+ // to the root node's transformation matrix
+ CHUNK_MASTER_SCALE = 0x0100,
+
+ // ********************************************************************
+ // Material chunks
+ CHUNK_MAT_MATERIAL = 0xAFFF,
+
+ // asciiz containing the name of the material
+ CHUNK_MAT_MATNAME = 0xA000,
+ CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
+ CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
+ CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
+
+ // Specifies the shininess of the material
+ // followed by percentage chunk
+ CHUNK_MAT_SHININESS = 0xA040,
+ CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
+
+ // Specifies the shading mode to be used
+ // followed by a short
+ CHUNK_MAT_SHADING = 0xA100,
+
+ // NOTE: Emissive color (self illumination) seems not
+ // to be a color but a single value, type is unknown.
+ // Make the parser accept both of them.
+ // followed by percentage chunk (?)
+ CHUNK_MAT_SELF_ILLUM = 0xA080,
+
+ // Always followed by percentage chunk (?)
+ CHUNK_MAT_SELF_ILPCT = 0xA084,
+
+ // Always followed by percentage chunk
+ CHUNK_MAT_TRANSPARENCY = 0xA050,
+
+ // Diffuse texture channel 0
+ CHUNK_MAT_TEXTURE = 0xA200,
+
+ // Contains opacity information for each texel
+ CHUNK_MAT_OPACMAP = 0xA210,
+
+ // Contains a reflection map to be used to reflect
+ // the environment. This is partially supported.
+ CHUNK_MAT_REFLMAP = 0xA220,
+
+ // Self Illumination map (emissive colors)
+ CHUNK_MAT_SELFIMAP = 0xA33d,
+
+ // Bumpmap. Not specified whether it is a heightmap
+ // or a normal map. Assme it is a heightmap since
+ // artist normally prefer this format.
+ CHUNK_MAT_BUMPMAP = 0xA230,
+
+ // Specular map. Seems to influence the specular color
+ CHUNK_MAT_SPECMAP = 0xA204,
+
+ // Holds shininess data.
+ CHUNK_MAT_MAT_SHINMAP = 0xA33C,
+
+ // Scaling in U/V direction.
+ // (need to gen separate UV coordinate set
+ // and do this by hand)
+ CHUNK_MAT_MAP_USCALE = 0xA354,
+ CHUNK_MAT_MAP_VSCALE = 0xA356,
+
+ // Translation in U/V direction.
+ // (need to gen separate UV coordinate set
+ // and do this by hand)
+ CHUNK_MAT_MAP_UOFFSET = 0xA358,
+ CHUNK_MAT_MAP_VOFFSET = 0xA35a,
+
+ // UV-coordinates rotation around the z-axis
+ // Assumed to be in radians.
+ CHUNK_MAT_MAP_ANG = 0xA35C,
+
+ // Tiling flags for 3DS files
+ CHUNK_MAT_MAP_TILING = 0xa351,
+
+ // Specifies the file name of a texture
+ CHUNK_MAPFILE = 0xA300,
+
+ // Specifies whether a materail requires two-sided rendering
+ CHUNK_MAT_TWO_SIDE = 0xA081,
+ // ********************************************************************
+
+ // Main keyframer chunk. Contains translation/rotation/scaling data
+ CHUNK_KEYFRAMER = 0xB000,
+
+ // Supported sub chunks
+ CHUNK_TRACKINFO = 0xB002,
+ CHUNK_TRACKOBJNAME = 0xB010,
+ CHUNK_TRACKDUMMYOBJNAME = 0xB011,
+ CHUNK_TRACKPIVOT = 0xB013,
+ CHUNK_TRACKPOS = 0xB020,
+ CHUNK_TRACKROTATE = 0xB021,
+ CHUNK_TRACKSCALE = 0xB022,
+
+ // ********************************************************************
+ // Keyframes for various other stuff in the file
+ // Partially ignored
+ CHUNK_AMBIENTKEY = 0xB001,
+ CHUNK_TRACKMORPH = 0xB026,
+ CHUNK_TRACKHIDE = 0xB029,
+ CHUNK_OBJNUMBER = 0xB030,
+ CHUNK_TRACKCAMERA = 0xB003,
+ CHUNK_TRACKFOV = 0xB023,
+ CHUNK_TRACKROLL = 0xB024,
+ CHUNK_TRACKCAMTGT = 0xB004,
+ CHUNK_TRACKLIGHT = 0xB005,
+ CHUNK_TRACKLIGTGT = 0xB006,
+ CHUNK_TRACKSPOTL = 0xB007,
+ CHUNK_FRAMES = 0xB008,
+ // ********************************************************************
+
+ // light sub-chunks
+ CHUNK_DL_OFF = 0x4620,
+ CHUNK_DL_OUTER_RANGE = 0x465A,
+ CHUNK_DL_INNER_RANGE = 0x4659,
+ CHUNK_DL_MULTIPLIER = 0x465B,
+ CHUNK_DL_EXCLUDE = 0x4654,
+ CHUNK_DL_ATTENUATE = 0x4625,
+ CHUNK_DL_SPOTLIGHT = 0x4610,
+
+ // camera sub-chunks
+ CHUNK_CAM_RANGES = 0x4720
+ };
};
// ---------------------------------------------------------------------------
@@ -318,38 +325,39 @@ struct Face : public FaceWithSmoothingGroup
/** Helper structure representing a texture */
struct Texture
{
- //! Default constructor
- Texture()
- : mOffsetU (0.0f)
- , mOffsetV (0.0f)
- , mScaleU (1.0f)
- , mScaleV (1.0f)
- , mRotation (0.0f)
- , mMapMode (aiTextureMapMode_Wrap)
- , iUVSrc (0)
- {
- mTextureBlend = get_qnan();
- }
-
- //! Specifies the blend factor for the texture
- float mTextureBlend;
-
- //! Specifies the filename of the texture
- std::string mMapName;
-
- //! Specifies texture coordinate offsets/scaling/rotations
- float mOffsetU;
- float mOffsetV;
- float mScaleU;
- float mScaleV;
- float mRotation;
-
- //! Specifies the mapping mode to be used for the texture
- aiTextureMapMode mMapMode;
-
- //! Used internally
- bool bPrivate;
- int iUVSrc;
+ //! Default constructor
+ Texture()
+ : mOffsetU (0.0f)
+ , mOffsetV (0.0f)
+ , mScaleU (1.0f)
+ , mScaleV (1.0f)
+ , mRotation (0.0f)
+ , mMapMode (aiTextureMapMode_Wrap)
+ , bPrivate()
+ , iUVSrc (0)
+ {
+ mTextureBlend = get_qnan();
+ }
+
+ //! Specifies the blend factor for the texture
+ float mTextureBlend;
+
+ //! Specifies the filename of the texture
+ std::string mMapName;
+
+ //! Specifies texture coordinate offsets/scaling/rotations
+ float mOffsetU;
+ float mOffsetV;
+ float mScaleU;
+ float mScaleV;
+ float mRotation;
+
+ //! Specifies the mapping mode to be used for the texture
+ aiTextureMapMode mMapMode;
+
+ //! Used internally
+ bool bPrivate;
+ int iUVSrc;
};
#include "./../include/assimp/Compiler/poppack1.h"
@@ -358,117 +366,117 @@ struct Texture
/** Helper structure representing a 3ds material */
struct Material
{
- //! Default constructor. Builds a default name for the material
- Material()
- :
- mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black
- mSpecularExponent (0.0f),
- mShininessStrength (1.0f),
- mShading(Discreet3DS::Gouraud),
- mTransparency (1.0f),
- mBumpHeight (1.0f),
- mTwoSided (false)
- {
- static int iCnt = 0;
-
- char szTemp[128];
- sprintf(szTemp,"UNNAMED_%i",iCnt++);
- mName = szTemp;
- }
-
- //! Name of the material
- std::string mName;
- //! Diffuse color of the material
- aiColor3D mDiffuse;
- //! Specular exponent
- float mSpecularExponent;
- //! Shininess strength, in percent
- float mShininessStrength;
- //! Specular color of the material
- aiColor3D mSpecular;
- //! Ambient color of the material
- aiColor3D mAmbient;
- //! Shading type to be used
- Discreet3DS::shadetype3ds mShading;
- //! Opacity of the material
- float mTransparency;
- //! Diffuse texture channel
- Texture sTexDiffuse;
- //! Opacity texture channel
- Texture sTexOpacity;
- //! Specular texture channel
- Texture sTexSpecular;
- //! Reflective texture channel
- Texture sTexReflective;
- //! Bump texture channel
- Texture sTexBump;
- //! Emissive texture channel
- Texture sTexEmissive;
- //! Shininess texture channel
- Texture sTexShininess;
- //! Scaling factor for the bump values
- float mBumpHeight;
- //! Emissive color
- aiColor3D mEmissive;
- //! Ambient texture channel
- //! (used by the ASE format)
- Texture sTexAmbient;
- //! True if the material must be rendered from two sides
- bool mTwoSided;
+ //! Default constructor. Builds a default name for the material
+ Material()
+ :
+ mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black
+ mSpecularExponent (0.0f),
+ mShininessStrength (1.0f),
+ mShading(Discreet3DS::Gouraud),
+ mTransparency (1.0f),
+ mBumpHeight (1.0f),
+ mTwoSided (false)
+ {
+ static int iCnt = 0;
+
+ char szTemp[128];
+ ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
+ mName = szTemp;
+ }
+
+ //! Name of the material
+ std::string mName;
+ //! Diffuse color of the material
+ aiColor3D mDiffuse;
+ //! Specular exponent
+ float mSpecularExponent;
+ //! Shininess strength, in percent
+ float mShininessStrength;
+ //! Specular color of the material
+ aiColor3D mSpecular;
+ //! Ambient color of the material
+ aiColor3D mAmbient;
+ //! Shading type to be used
+ Discreet3DS::shadetype3ds mShading;
+ //! Opacity of the material
+ float mTransparency;
+ //! Diffuse texture channel
+ Texture sTexDiffuse;
+ //! Opacity texture channel
+ Texture sTexOpacity;
+ //! Specular texture channel
+ Texture sTexSpecular;
+ //! Reflective texture channel
+ Texture sTexReflective;
+ //! Bump texture channel
+ Texture sTexBump;
+ //! Emissive texture channel
+ Texture sTexEmissive;
+ //! Shininess texture channel
+ Texture sTexShininess;
+ //! Scaling factor for the bump values
+ float mBumpHeight;
+ //! Emissive color
+ aiColor3D mEmissive;
+ //! Ambient texture channel
+ //! (used by the ASE format)
+ Texture sTexAmbient;
+ //! True if the material must be rendered from two sides
+ bool mTwoSided;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file mesh */
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
{
- //! Default constructor
- Mesh()
- {
- static int iCnt = 0;
-
- // Generate a default name for the mesh
- char szTemp[128];
- ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
- mName = szTemp;
- }
-
- //! Name of the mesh
- std::string mName;
-
- //! Texture coordinates
- std::vector<aiVector3D> mTexCoords;
-
- //! Face materials
- std::vector<unsigned int> mFaceMaterials;
-
- //! Local transformation matrix
- aiMatrix4x4 mMat;
+ //! Default constructor
+ Mesh()
+ {
+ static int iCnt = 0;
+
+ // Generate a default name for the mesh
+ char szTemp[128];
+ ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
+ mName = szTemp;
+ }
+
+ //! Name of the mesh
+ std::string mName;
+
+ //! Texture coordinates
+ std::vector<aiVector3D> mTexCoords;
+
+ //! Face materials
+ std::vector<unsigned int> mFaceMaterials;
+
+ //! Local transformation matrix
+ aiMatrix4x4 mMat;
};
// ---------------------------------------------------------------------------
/** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the
C-API, so it would be difficult to make them a template. */
-struct aiFloatKey
+struct aiFloatKey
{
- double mTime; ///< The time of this key
- float mValue; ///< The value of this key
+ double mTime; ///< The time of this key
+ float mValue; ///< The value of this key
#ifdef __cplusplus
- // time is not compared
- bool operator == (const aiFloatKey& o) const
- {return o.mValue == this->mValue;}
+ // time is not compared
+ bool operator == (const aiFloatKey& o) const
+ {return o.mValue == this->mValue;}
- bool operator != (const aiFloatKey& o) const
- {return o.mValue != this->mValue;}
+ bool operator != (const aiFloatKey& o) const
+ {return o.mValue != this->mValue;}
- // Only time is compared. This operator is defined
- // for use with std::sort
- bool operator < (const aiFloatKey& o) const
- {return mTime < o.mTime;}
+ // Only time is compared. This operator is defined
+ // for use with std::sort
+ bool operator < (const aiFloatKey& o) const
+ {return mTime < o.mTime;}
- bool operator > (const aiFloatKey& o) const
- {return mTime < o.mTime;}
+ bool operator > (const aiFloatKey& o) const
+ {return mTime > o.mTime;}
#endif
};
@@ -477,104 +485,104 @@ struct aiFloatKey
/** Helper structure to represent a 3ds file node */
struct Node
{
- Node()
-
- : mHierarchyPos (0)
+ Node():
+ mParent(NULL)
+ , mInstanceNumber(0)
+ , mHierarchyPos (0)
, mHierarchyIndex (0)
, mInstanceCount (1)
+ {
+ static int iCnt = 0;
- {
- static int iCnt = 0;
-
- // Generate a default name for the node
- char szTemp[128];
- ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
- mName = szTemp;
+ // Generate a default name for the node
+ char szTemp[128];
+ ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
+ mName = szTemp;
- aRotationKeys.reserve (20);
- aPositionKeys.reserve (20);
- aScalingKeys.reserve (20);
- }
+ aRotationKeys.reserve (20);
+ aPositionKeys.reserve (20);
+ aScalingKeys.reserve (20);
+ }
- ~Node()
- {
- for (unsigned int i = 0; i < mChildren.size();++i)
- delete mChildren[i];
- }
+ ~Node()
+ {
+ for (unsigned int i = 0; i < mChildren.size();++i)
+ delete mChildren[i];
+ }
- //! Pointer to the parent node
- Node* mParent;
+ //! Pointer to the parent node
+ Node* mParent;
- //! Holds all child nodes
- std::vector<Node*> mChildren;
+ //! Holds all child nodes
+ std::vector<Node*> mChildren;
- //! Name of the node
- std::string mName;
+ //! Name of the node
+ std::string mName;
- //! InstanceNumber of the node
- int32_t mInstanceNumber;
+ //! InstanceNumber of the node
+ int32_t mInstanceNumber;
- //! Dummy nodes: real name to be combined with the $$$DUMMY
- std::string mDummyName;
+ //! Dummy nodes: real name to be combined with the $$$DUMMY
+ std::string mDummyName;
- //! Position of the node in the hierarchy (tree depth)
- int16_t mHierarchyPos;
+ //! Position of the node in the hierarchy (tree depth)
+ int16_t mHierarchyPos;
- //! Index of the node
- int16_t mHierarchyIndex;
+ //! Index of the node
+ int16_t mHierarchyIndex;
- //! Rotation keys loaded from the file
- std::vector<aiQuatKey> aRotationKeys;
+ //! Rotation keys loaded from the file
+ std::vector<aiQuatKey> aRotationKeys;
- //! Position keys loaded from the file
- std::vector<aiVectorKey> aPositionKeys;
+ //! Position keys loaded from the file
+ std::vector<aiVectorKey> aPositionKeys;
- //! Scaling keys loaded from the file
- std::vector<aiVectorKey> aScalingKeys;
+ //! Scaling keys loaded from the file
+ std::vector<aiVectorKey> aScalingKeys;
- // For target lights (spot lights and directional lights):
- // The position of the target
- std::vector< aiVectorKey > aTargetPositionKeys;
+ // For target lights (spot lights and directional lights):
+ // The position of the target
+ std::vector< aiVectorKey > aTargetPositionKeys;
- // For cameras: the camera roll angle
- std::vector< aiFloatKey > aCameraRollKeys;
+ // For cameras: the camera roll angle
+ std::vector< aiFloatKey > aCameraRollKeys;
- //! Pivot position loaded from the file
- aiVector3D vPivot;
+ //! Pivot position loaded from the file
+ aiVector3D vPivot;
- //instance count, will be kept only for the first node
- int32_t mInstanceCount;
+ //instance count, will be kept only for the first node
+ int32_t mInstanceCount;
- //! Add a child node, setup the right parent node for it
- //! \param pc Node to be 'adopted'
- inline Node& push_back(Node* pc)
- {
- mChildren.push_back(pc);
- pc->mParent = this;
- return *this;
- }
+ //! Add a child node, setup the right parent node for it
+ //! \param pc Node to be 'adopted'
+ inline Node& push_back(Node* pc)
+ {
+ mChildren.push_back(pc);
+ pc->mParent = this;
+ return *this;
+ }
};
// ---------------------------------------------------------------------------
/** Helper structure analogue to aiScene */
struct Scene
{
- //! List of all materials loaded
- //! NOTE: 3ds references materials globally
- std::vector<Material> mMaterials;
+ //! List of all materials loaded
+ //! NOTE: 3ds references materials globally
+ std::vector<Material> mMaterials;
- //! List of all meshes loaded
- std::vector<Mesh> mMeshes;
+ //! List of all meshes loaded
+ std::vector<Mesh> mMeshes;
- //! List of all cameras loaded
- std::vector<aiCamera*> mCameras;
+ //! List of all cameras loaded
+ std::vector<aiCamera*> mCameras;
- //! List of all lights loaded
- std::vector<aiLight*> mLights;
+ //! List of all lights loaded
+ std::vector<aiLight*> mLights;
- //! Pointer to the root node of the scene
- // --- moved to main class
- // Node* pcRootNode;
+ //! Pointer to the root node of the scene
+ // --- moved to main class
+ // Node* pcRootNode;
};
diff --git a/src/3rdparty/assimp/code/3DSLoader.cpp b/src/3rdparty/assimp/code/3DSLoader.cpp
index 137cceb1f..a2b73b2cb 100644
--- a/src/3rdparty/assimp/code/3DSLoader.cpp
+++ b/src/3rdparty/assimp/code/3DSLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -45,554 +45,570 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* http://www.the-labs.com/Blender/3DS-details.html
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers
#include "3DSLoader.h"
+#include "Macros.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include "StringComparison.h"
using namespace Assimp;
static const aiImporterDesc desc = {
- "Discreet 3DS Importer",
- "",
- "",
- "Limited animation support",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "3ds prj"
+ "Discreet 3DS Importer",
+ "",
+ "",
+ "Limited animation support",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "3ds prj"
};
-
+
// ------------------------------------------------------------------------------------------------
// Begins a new parsing block
// - Reads the current chunk and validates it
// - computes its length
#define ASSIMP_3DS_BEGIN_CHUNK() \
- while (true) { \
- if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)){ \
- return; \
- } \
- Discreet3DS::Chunk chunk; \
- ReadChunk(&chunk); \
- int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
+ while (true) { \
+ if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)){ \
+ return; \
+ } \
+ Discreet3DS::Chunk chunk; \
+ ReadChunk(&chunk); \
+ int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
if(chunkSize <= 0) \
continue; \
- const int oldReadLimit = stream->GetReadLimit(); \
- stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \
-
+ const unsigned int oldReadLimit = stream->SetReadLimit( \
+ stream->GetCurrentPos() + chunkSize); \
+
// ------------------------------------------------------------------------------------------------
// End a parsing block
// Must follow at the end of each parsing block, reset chunk end marker to previous value
#define ASSIMP_3DS_END_CHUNK() \
- stream->SkipToReadLimit(); \
- stream->SetReadLimit(oldReadLimit); \
- if (stream->GetRemainingSizeToLimit() == 0) \
- return; \
- }
+ stream->SkipToReadLimit(); \
+ stream->SetReadLimit(oldReadLimit); \
+ if (stream->GetRemainingSizeToLimit() == 0) \
+ return; \
+ }
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
Discreet3DSImporter::Discreet3DSImporter()
+ : stream(),
+ mLastNodeIndex(),
+ mCurrentNode(),
+ mRootNode(),
+ mScene(),
+ mMasterScale(),
+ bHasBG(),
+ bIsPrj()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
Discreet3DSImporter::~Discreet3DSImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- std::string extension = GetExtension(pFile);
- if(extension == "3ds" || extension == "prj" ) {
- return true;
- }
- if (!extension.length() || checkSig) {
- uint16_t token[3];
- token[0] = 0x4d4d;
- token[1] = 0x3dc2;
- //token[2] = 0x3daa;
- return CheckMagicToken(pIOHandler,pFile,token,2,0,2);
- }
- return false;
+ std::string extension = GetExtension(pFile);
+ if(extension == "3ds" || extension == "prj" ) {
+ return true;
+ }
+ if (!extension.length() || checkSig) {
+ uint16_t token[3];
+ token[0] = 0x4d4d;
+ token[1] = 0x3dc2;
+ //token[2] = 0x3daa;
+ return CheckMagicToken(pIOHandler,pFile,token,2,0,2);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Loader registry entry
const aiImporterDesc* Discreet3DSImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
{
- // nothing to be done for the moment
+ // nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void Discreet3DSImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void Discreet3DSImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
- this->stream = &stream;
-
- // We should have at least one chunk
- if (stream.GetRemainingSize() < 16) {
- throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile);
- }
-
- // Allocate our temporary 3DS representation
- mScene = new D3DS::Scene();
-
- // Initialize members
- mLastNodeIndex = -1;
- mCurrentNode = new D3DS::Node();
- mRootNode = mCurrentNode;
- mRootNode->mHierarchyPos = -1;
- mRootNode->mHierarchyIndex = -1;
- mRootNode->mParent = NULL;
- mMasterScale = 1.0f;
- mBackgroundImage = "";
- bHasBG = false;
- bIsPrj = false;
-
- // Parse the file
- ParseMainChunk();
-
- // Process all meshes in the file. First check whether all
- // face indices haev valid values. The generate our
- // internal verbose representation. Finally compute normal
- // vectors from the smoothing groups we read from the
- // file.
- for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(),
- end = mScene->mMeshes.end(); i != end;++i) {
- CheckIndices(*i);
- MakeUnique (*i);
- ComputeNormalsWithSmoothingsGroups<D3DS::Face>(*i);
- }
-
- // Replace all occurences of the default material with a
- // valid material. Generate it if no material containing
- // DEFAULT in its name has been found in the file
- ReplaceDefaultMaterial();
-
- // Convert the scene from our internal representation to an
- // aiScene object. This involves copying all meshes, lights
- // and cameras to the scene
- ConvertScene(pScene);
-
- // Generate the node graph for the scene. This is a little bit
- // tricky since we'll need to split some meshes into submeshes
- GenerateNodeGraph(pScene);
-
- // Now apply the master scaling factor to the scene
- ApplyMasterScale(pScene);
-
- // Delete our internal scene representation and the root
- // node, so the whole hierarchy will follow
- delete mRootNode;
- delete mScene;
-
- AI_DEBUG_INVALIDATE_PTR(mRootNode);
- AI_DEBUG_INVALIDATE_PTR(mScene);
- AI_DEBUG_INVALIDATE_PTR(this->stream);
+ StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+ this->stream = &stream;
+
+ // We should have at least one chunk
+ if (stream.GetRemainingSize() < 16) {
+ throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile);
+ }
+
+ // Allocate our temporary 3DS representation
+ mScene = new D3DS::Scene();
+
+ // Initialize members
+ mLastNodeIndex = -1;
+ mCurrentNode = new D3DS::Node();
+ mRootNode = mCurrentNode;
+ mRootNode->mHierarchyPos = -1;
+ mRootNode->mHierarchyIndex = -1;
+ mRootNode->mParent = NULL;
+ mMasterScale = 1.0f;
+ mBackgroundImage = "";
+ bHasBG = false;
+ bIsPrj = false;
+
+ // Parse the file
+ ParseMainChunk();
+
+ // Process all meshes in the file. First check whether all
+ // face indices haev valid values. The generate our
+ // internal verbose representation. Finally compute normal
+ // vectors from the smoothing groups we read from the
+ // file.
+ for (auto &mesh : mScene->mMeshes) {
+ if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) {
+ delete mScene;
+ throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile);
+ }
+ CheckIndices(mesh);
+ MakeUnique (mesh);
+ ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
+ }
+
+ // Replace all occurrences of the default material with a
+ // valid material. Generate it if no material containing
+ // DEFAULT in its name has been found in the file
+ ReplaceDefaultMaterial();
+
+ // Convert the scene from our internal representation to an
+ // aiScene object. This involves copying all meshes, lights
+ // and cameras to the scene
+ ConvertScene(pScene);
+
+ // Generate the node graph for the scene. This is a little bit
+ // tricky since we'll need to split some meshes into submeshes
+ GenerateNodeGraph(pScene);
+
+ // Now apply the master scaling factor to the scene
+ ApplyMasterScale(pScene);
+
+ // Delete our internal scene representation and the root
+ // node, so the whole hierarchy will follow
+ delete mRootNode;
+ delete mScene;
+
+ AI_DEBUG_INVALIDATE_PTR(mRootNode);
+ AI_DEBUG_INVALIDATE_PTR(mScene);
+ AI_DEBUG_INVALIDATE_PTR(this->stream);
}
// ------------------------------------------------------------------------------------------------
// Applies a master-scaling factor to the imported scene
void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene)
{
- // There are some 3DS files with a zero scaling factor
- if (!mMasterScale)mMasterScale = 1.0f;
- else mMasterScale = 1.0f / mMasterScale;
-
- // Construct an uniform scaling matrix and multiply with it
- pScene->mRootNode->mTransformation *= aiMatrix4x4(
- mMasterScale,0.0f, 0.0f, 0.0f,
- 0.0f, mMasterScale,0.0f, 0.0f,
- 0.0f, 0.0f, mMasterScale,0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f);
-
- // Check whether a scaling track is assigned to the root node.
+ // There are some 3DS files with a zero scaling factor
+ if (!mMasterScale)mMasterScale = 1.0f;
+ else mMasterScale = 1.0f / mMasterScale;
+
+ // Construct an uniform scaling matrix and multiply with it
+ pScene->mRootNode->mTransformation *= aiMatrix4x4(
+ mMasterScale,0.0f, 0.0f, 0.0f,
+ 0.0f, mMasterScale,0.0f, 0.0f,
+ 0.0f, 0.0f, mMasterScale,0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+
+ // Check whether a scaling track is assigned to the root node.
}
// ------------------------------------------------------------------------------------------------
// Reads a new chunk from the file
void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut)
{
- ai_assert(pcOut != NULL);
+ ai_assert(pcOut != NULL);
- pcOut->Flag = stream->GetI2();
- pcOut->Size = stream->GetI4();
+ pcOut->Flag = stream->GetI2();
+ pcOut->Size = stream->GetI4();
- if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
- throw DeadlyImportError("Chunk is too large");
-
- if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit())
- DefaultLogger::get()->error("3DS: Chunk overflow");
+ if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
+ throw DeadlyImportError("Chunk is too large");
+
+ if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit())
+ DefaultLogger::get()->error("3DS: Chunk overflow");
}
// ------------------------------------------------------------------------------------------------
// Skip a chunk
void Discreet3DSImporter::SkipChunk()
{
- Discreet3DS::Chunk psChunk;
- ReadChunk(&psChunk);
-
- stream->IncPtr(psChunk.Size-sizeof(Discreet3DS::Chunk));
- return;
+ Discreet3DS::Chunk psChunk;
+ ReadChunk(&psChunk);
+
+ stream->IncPtr(psChunk.Size-sizeof(Discreet3DS::Chunk));
+ return;
}
// ------------------------------------------------------------------------------------------------
// Process the primary chunk of the file
void Discreet3DSImporter::ParseMainChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
-
- case Discreet3DS::CHUNK_PRJ:
- bIsPrj = true;
- case Discreet3DS::CHUNK_MAIN:
- ParseEditorChunk();
- break;
- };
-
- ASSIMP_3DS_END_CHUNK();
- // recursively continue processing this hierarchy level
- return ParseMainChunk();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+
+ case Discreet3DS::CHUNK_PRJ:
+ bIsPrj = true;
+ case Discreet3DS::CHUNK_MAIN:
+ ParseEditorChunk();
+ break;
+ };
+
+ ASSIMP_3DS_END_CHUNK();
+ // recursively continue processing this hierarchy level
+ return ParseMainChunk();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseEditorChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_OBJMESH:
-
- ParseObjectChunk();
- break;
-
- // NOTE: In several documentations in the internet this
- // chunk appears at different locations
- case Discreet3DS::CHUNK_KEYFRAMER:
-
- ParseKeyframeChunk();
- break;
-
- case Discreet3DS::CHUNK_VERSION:
- {
- // print the version number
- char buff[10];
- ASSIMP_itoa10(buff,stream->GetI2());
- DefaultLogger::get()->info(std::string("3DS file format version: ") + buff);
- }
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_OBJMESH:
+
+ ParseObjectChunk();
+ break;
+
+ // NOTE: In several documentations in the internet this
+ // chunk appears at different locations
+ case Discreet3DS::CHUNK_KEYFRAMER:
+
+ ParseKeyframeChunk();
+ break;
+
+ case Discreet3DS::CHUNK_VERSION:
+ {
+ // print the version number
+ char buff[10];
+ ASSIMP_itoa10(buff,stream->GetI2());
+ DefaultLogger::get()->info(std::string("3DS file format version: ") + buff);
+ }
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseObjectChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_OBJBLOCK:
- {
- unsigned int cnt = 0;
- const char* sz = (const char*)stream->GetPtr();
-
- // Get the name of the geometry object
- while (stream->GetI1())++cnt;
- ParseChunk(sz,cnt);
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_MATERIAL:
-
- // Add a new material to the list
- mScene->mMaterials.push_back(D3DS::Material());
- ParseMaterialChunk();
- break;
-
- case Discreet3DS::CHUNK_AMBCOLOR:
-
- // This is the ambient base color of the scene.
- // We add it to the ambient color of all materials
- ParseColorChunk(&mClrAmbient,true);
- if (is_qnan(mClrAmbient.r))
- {
- // We failed to read the ambient base color.
- DefaultLogger::get()->error("3DS: Failed to read ambient base color");
- mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
- }
- break;
-
- case Discreet3DS::CHUNK_BIT_MAP:
- {
- // Specifies the background image. The string should already be
- // properly 0 terminated but we need to be sure
- unsigned int cnt = 0;
- const char* sz = (const char*)stream->GetPtr();
- while (stream->GetI1())++cnt;
- mBackgroundImage = std::string(sz,cnt);
- }
- break;
-
- case Discreet3DS::CHUNK_BIT_MAP_EXISTS:
- bHasBG = true;
- break;
-
- case Discreet3DS::CHUNK_MASTER_SCALE:
- // Scene master scaling factor
- mMasterScale = stream->GetF4();
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_OBJBLOCK:
+ {
+ unsigned int cnt = 0;
+ const char* sz = (const char*)stream->GetPtr();
+
+ // Get the name of the geometry object
+ while (stream->GetI1())++cnt;
+ ParseChunk(sz,cnt);
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MATERIAL:
+
+ // Add a new material to the list
+ mScene->mMaterials.push_back(D3DS::Material());
+ ParseMaterialChunk();
+ break;
+
+ case Discreet3DS::CHUNK_AMBCOLOR:
+
+ // This is the ambient base color of the scene.
+ // We add it to the ambient color of all materials
+ ParseColorChunk(&mClrAmbient,true);
+ if (is_qnan(mClrAmbient.r))
+ {
+ // We failed to read the ambient base color.
+ DefaultLogger::get()->error("3DS: Failed to read ambient base color");
+ mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_BIT_MAP:
+ {
+ // Specifies the background image. The string should already be
+ // properly 0 terminated but we need to be sure
+ unsigned int cnt = 0;
+ const char* sz = (const char*)stream->GetPtr();
+ while (stream->GetI1())++cnt;
+ mBackgroundImage = std::string(sz,cnt);
+ }
+ break;
+
+ case Discreet3DS::CHUNK_BIT_MAP_EXISTS:
+ bHasBG = true;
+ break;
+
+ case Discreet3DS::CHUNK_MASTER_SCALE:
+ // Scene master scaling factor
+ mMasterScale = stream->GetF4();
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // IMPLEMENTATION NOTE;
- // Cameras or lights define their transformation in their parent node and in the
- // corresponding light or camera chunks. However, we read and process the latter
- // to to be able to return valid cameras/lights even if no scenegraph is given.
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_TRIMESH:
- {
- // this starts a new triangle mesh
- mScene->mMeshes.push_back(D3DS::Mesh());
- D3DS::Mesh& m = mScene->mMeshes.back();
-
- // Setup the name of the mesh
- m.mName = std::string(name, num);
-
- // Read mesh chunks
- ParseMeshChunk();
- }
- break;
-
- case Discreet3DS::CHUNK_LIGHT:
- {
- // This starts a new light
- aiLight* light = new aiLight();
- mScene->mLights.push_back(light);
-
- light->mName.Set(std::string(name, num));
-
- // First read the position of the light
- light->mPosition.x = stream->GetF4();
- light->mPosition.y = stream->GetF4();
- light->mPosition.z = stream->GetF4();
-
- light->mColorDiffuse = aiColor3D(1.f,1.f,1.f);
-
- // Now check for further subchunks
- if (!bIsPrj) /* fixme */
- ParseLightChunk();
-
- // The specular light color is identical the the diffuse light color. The ambient light color
- // is equal to the ambient base color of the whole scene.
- light->mColorSpecular = light->mColorDiffuse;
- light->mColorAmbient = mClrAmbient;
-
- if (light->mType == aiLightSource_UNDEFINED)
- {
- // It must be a point light
- light->mType = aiLightSource_POINT;
- }}
- break;
-
- case Discreet3DS::CHUNK_CAMERA:
- {
- // This starts a new camera
- aiCamera* camera = new aiCamera();
- mScene->mCameras.push_back(camera);
- camera->mName.Set(std::string(name, num));
-
- // First read the position of the camera
- camera->mPosition.x = stream->GetF4();
- camera->mPosition.y = stream->GetF4();
- camera->mPosition.z = stream->GetF4();
-
- // Then the camera target
- camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
- camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
- camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
- float len = camera->mLookAt.Length();
- if (len < 1e-5f) {
-
- // There are some files with lookat == position. Don't know why or whether it's ok or not.
- DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
- camera->mLookAt = aiVector3D(0.f,1.f,0.f);
-
- }
- else camera->mLookAt /= len;
-
- // And finally - the camera rotation angle, in counter clockwise direction
- const float angle = AI_DEG_TO_RAD( stream->GetF4() );
- aiQuaternion quat(camera->mLookAt,angle);
- camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f);
-
- // Read the lense angle
- camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
- if (camera->mHorizontalFOV < 0.001f) {
- camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
- }
-
- // Now check for further subchunks
- if (!bIsPrj) /* fixme */ {
- ParseCameraChunk();
- }}
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // IMPLEMENTATION NOTE;
+ // Cameras or lights define their transformation in their parent node and in the
+ // corresponding light or camera chunks. However, we read and process the latter
+ // to to be able to return valid cameras/lights even if no scenegraph is given.
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_TRIMESH:
+ {
+ // this starts a new triangle mesh
+ mScene->mMeshes.push_back(D3DS::Mesh());
+ D3DS::Mesh& m = mScene->mMeshes.back();
+
+ // Setup the name of the mesh
+ m.mName = std::string(name, num);
+
+ // Read mesh chunks
+ ParseMeshChunk();
+ }
+ break;
+
+ case Discreet3DS::CHUNK_LIGHT:
+ {
+ // This starts a new light
+ aiLight* light = new aiLight();
+ mScene->mLights.push_back(light);
+
+ light->mName.Set(std::string(name, num));
+
+ // First read the position of the light
+ light->mPosition.x = stream->GetF4();
+ light->mPosition.y = stream->GetF4();
+ light->mPosition.z = stream->GetF4();
+
+ light->mColorDiffuse = aiColor3D(1.f,1.f,1.f);
+
+ // Now check for further subchunks
+ if (!bIsPrj) /* fixme */
+ ParseLightChunk();
+
+ // The specular light color is identical the the diffuse light color. The ambient light color
+ // is equal to the ambient base color of the whole scene.
+ light->mColorSpecular = light->mColorDiffuse;
+ light->mColorAmbient = mClrAmbient;
+
+ if (light->mType == aiLightSource_UNDEFINED)
+ {
+ // It must be a point light
+ light->mType = aiLightSource_POINT;
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_CAMERA:
+ {
+ // This starts a new camera
+ aiCamera* camera = new aiCamera();
+ mScene->mCameras.push_back(camera);
+ camera->mName.Set(std::string(name, num));
+
+ // First read the position of the camera
+ camera->mPosition.x = stream->GetF4();
+ camera->mPosition.y = stream->GetF4();
+ camera->mPosition.z = stream->GetF4();
+
+ // Then the camera target
+ camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
+ camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
+ camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
+ float len = camera->mLookAt.Length();
+ if (len < 1e-5f) {
+
+ // There are some files with lookat == position. Don't know why or whether it's ok or not.
+ DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
+ camera->mLookAt = aiVector3D(0.f,1.f,0.f);
+
+ }
+ else camera->mLookAt /= len;
+
+ // And finally - the camera rotation angle, in counter clockwise direction
+ const float angle = AI_DEG_TO_RAD( stream->GetF4() );
+ aiQuaternion quat(camera->mLookAt,angle);
+ camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f);
+
+ // Read the lense angle
+ camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
+ if (camera->mHorizontalFOV < 0.001f) {
+ camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
+ }
+
+ // Now check for further subchunks
+ if (!bIsPrj) /* fixme */ {
+ ParseCameraChunk();
+ }}
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseLightChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
- aiLight* light = mScene->mLights.back();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_DL_SPOTLIGHT:
- // Now we can be sure that the light is a spot light
- light->mType = aiLightSource_SPOT;
-
- // We wouldn't need to normalize here, but we do it
- light->mDirection.x = stream->GetF4() - light->mPosition.x;
- light->mDirection.y = stream->GetF4() - light->mPosition.y;
- light->mDirection.z = stream->GetF4() - light->mPosition.z;
- light->mDirection.Normalize();
-
- // Now the hotspot and falloff angles - in degrees
- light->mAngleInnerCone = AI_DEG_TO_RAD( stream->GetF4() );
-
- // FIX: the falloff angle is just an offset
- light->mAngleOuterCone = light->mAngleInnerCone+AI_DEG_TO_RAD( stream->GetF4() );
- break;
-
- // intensity multiplier
- case Discreet3DS::CHUNK_DL_MULTIPLIER:
- light->mColorDiffuse = light->mColorDiffuse * stream->GetF4();
- break;
-
- // light color
- case Discreet3DS::CHUNK_RGBF:
- case Discreet3DS::CHUNK_LINRGBF:
- light->mColorDiffuse.r *= stream->GetF4();
- light->mColorDiffuse.g *= stream->GetF4();
- light->mColorDiffuse.b *= stream->GetF4();
- break;
-
- // light attenuation
- case Discreet3DS::CHUNK_DL_ATTENUATE:
- light->mAttenuationLinear = stream->GetF4();
- break;
- };
-
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+ aiLight* light = mScene->mLights.back();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_DL_SPOTLIGHT:
+ // Now we can be sure that the light is a spot light
+ light->mType = aiLightSource_SPOT;
+
+ // We wouldn't need to normalize here, but we do it
+ light->mDirection.x = stream->GetF4() - light->mPosition.x;
+ light->mDirection.y = stream->GetF4() - light->mPosition.y;
+ light->mDirection.z = stream->GetF4() - light->mPosition.z;
+ light->mDirection.Normalize();
+
+ // Now the hotspot and falloff angles - in degrees
+ light->mAngleInnerCone = AI_DEG_TO_RAD( stream->GetF4() );
+
+ // FIX: the falloff angle is just an offset
+ light->mAngleOuterCone = light->mAngleInnerCone+AI_DEG_TO_RAD( stream->GetF4() );
+ break;
+
+ // intensity multiplier
+ case Discreet3DS::CHUNK_DL_MULTIPLIER:
+ light->mColorDiffuse = light->mColorDiffuse * stream->GetF4();
+ break;
+
+ // light color
+ case Discreet3DS::CHUNK_RGBF:
+ case Discreet3DS::CHUNK_LINRGBF:
+ light->mColorDiffuse.r *= stream->GetF4();
+ light->mColorDiffuse.g *= stream->GetF4();
+ light->mColorDiffuse.b *= stream->GetF4();
+ break;
+
+ // light attenuation
+ case Discreet3DS::CHUNK_DL_ATTENUATE:
+ light->mAttenuationLinear = stream->GetF4();
+ break;
+ };
+
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseCameraChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
- aiCamera* camera = mScene->mCameras.back();
-
- // get chunk type
- switch (chunk.Flag)
- {
- // near and far clip plane
- case Discreet3DS::CHUNK_CAM_RANGES:
- camera->mClipPlaneNear = stream->GetF4();
- camera->mClipPlaneFar = stream->GetF4();
- break;
- }
-
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+ aiCamera* camera = mScene->mCameras.back();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ // near and far clip plane
+ case Discreet3DS::CHUNK_CAM_RANGES:
+ camera->mClipPlaneNear = stream->GetF4();
+ camera->mClipPlaneFar = stream->GetF4();
+ break;
+ }
+
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseKeyframeChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_TRACKCAMTGT:
- case Discreet3DS::CHUNK_TRACKSPOTL:
- case Discreet3DS::CHUNK_TRACKCAMERA:
- case Discreet3DS::CHUNK_TRACKINFO:
- case Discreet3DS::CHUNK_TRACKLIGHT:
- case Discreet3DS::CHUNK_TRACKLIGTGT:
-
- // this starts a new mesh hierarchy chunk
- ParseHierarchyChunk(chunk.Flag);
- break;
- };
-
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_TRACKCAMTGT:
+ case Discreet3DS::CHUNK_TRACKSPOTL:
+ case Discreet3DS::CHUNK_TRACKCAMERA:
+ case Discreet3DS::CHUNK_TRACKINFO:
+ case Discreet3DS::CHUNK_TRACKLIGHT:
+ case Discreet3DS::CHUNK_TRACKLIGTGT:
+
+ // this starts a new mesh hierarchy chunk
+ ParseHierarchyChunk(chunk.Flag);
+ break;
+ };
+
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
// Little helper function for ParseHierarchyChunk
void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent)
{
- if (!pcCurrent) {
- mRootNode->push_back(pcNode);
- return;
- }
-
- if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) {
- if(pcCurrent->mParent) {
- pcCurrent->mParent->push_back(pcNode);
- }
- else pcCurrent->push_back(pcNode);
- return;
- }
- return InverseNodeSearch(pcNode,pcCurrent->mParent);
+ if (!pcCurrent) {
+ mRootNode->push_back(pcNode);
+ return;
+ }
+
+ if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) {
+ if(pcCurrent->mParent) {
+ pcCurrent->mParent->push_back(pcNode);
+ }
+ else pcCurrent->push_back(pcNode);
+ return;
+ }
+ return InverseNodeSearch(pcNode,pcCurrent->mParent);
}
// ------------------------------------------------------------------------------------------------
// Find a node with a specific name in the import hierarchy
D3DS::Node* FindNode(D3DS::Node* root, const std::string& name)
{
- if (root->mName == name)
- return root;
- for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
- D3DS::Node* nd;
- if (( nd = FindNode(*it,name)))
- return nd;
- }
- return NULL;
+ if (root->mName == name)
+ return root;
+ for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) {
+ D3DS::Node* nd;
+ if (( nd = FindNode(*it,name)))
+ return nd;
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
@@ -600,803 +616,806 @@ D3DS::Node* FindNode(D3DS::Node* root, const std::string& name)
template <class T>
bool KeyUniqueCompare(const T& first, const T& second)
{
- return first.mTime == second.mTime;
+ return first.mTime == second.mTime;
}
// ------------------------------------------------------------------------------------------------
// Skip some additional import data.
void Discreet3DSImporter::SkipTCBInfo()
{
- unsigned int flags = stream->GetI2();
-
- if (!flags) {
- // Currently we can't do anything with these values. They occur
- // quite rare, so it wouldn't be worth the effort implementing
- // them. 3DS ist not really suitable for complex animations,
- // so full support is not required.
- DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
- }
-
- if (flags & Discreet3DS::KEY_USE_TENS) {
- stream->IncPtr(4);
- }
- if (flags & Discreet3DS::KEY_USE_BIAS) {
- stream->IncPtr(4);
- }
- if (flags & Discreet3DS::KEY_USE_CONT) {
- stream->IncPtr(4);
- }
- if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
- stream->IncPtr(4);
- }
- if (flags & Discreet3DS::KEY_USE_EASE_TO) {
- stream->IncPtr(4);
- }
+ unsigned int flags = stream->GetI2();
+
+ if (!flags) {
+ // Currently we can't do anything with these values. They occur
+ // quite rare, so it wouldn't be worth the effort implementing
+ // them. 3DS ist not really suitable for complex animations,
+ // so full support is not required.
+ DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
+ }
+
+ if (flags & Discreet3DS::KEY_USE_TENS) {
+ stream->IncPtr(4);
+ }
+ if (flags & Discreet3DS::KEY_USE_BIAS) {
+ stream->IncPtr(4);
+ }
+ if (flags & Discreet3DS::KEY_USE_CONT) {
+ stream->IncPtr(4);
+ }
+ if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
+ stream->IncPtr(4);
+ }
+ if (flags & Discreet3DS::KEY_USE_EASE_TO) {
+ stream->IncPtr(4);
+ }
}
// ------------------------------------------------------------------------------------------------
// Read hierarchy and keyframe info
void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_TRACKOBJNAME:
-
- // This is the name of the object to which the track applies. The chunk also
- // defines the position of this object in the hierarchy.
- {
-
- // First of all: get the name of the object
- unsigned int cnt = 0;
- const char* sz = (const char*)stream->GetPtr();
-
- while (stream->GetI1())++cnt;
- std::string name = std::string(sz,cnt);
-
- // Now find out whether we have this node already (target animation channels
- // are stored with a separate object ID)
- D3DS::Node* pcNode = FindNode(mRootNode,name);
- int instanceNumber = 1;
-
- if ( pcNode)
- {
- // if the source is not a CHUNK_TRACKINFO block it wont be an object instance
- if (parent != Discreet3DS::CHUNK_TRACKINFO)
- {
- mCurrentNode = pcNode;
- break;
- }
- pcNode->mInstanceCount++;
- instanceNumber = pcNode->mInstanceCount;
- }
- pcNode = new D3DS::Node();
- pcNode->mName = name;
- pcNode->mInstanceNumber = instanceNumber;
-
- // There are two unknown values which we can safely ignore
- stream->IncPtr(4);
-
- // Now read the hierarchy position of the object
- uint16_t hierarchy = stream->GetI2() + 1;
- pcNode->mHierarchyPos = hierarchy;
- pcNode->mHierarchyIndex = mLastNodeIndex;
-
- // And find a proper position in the graph for it
- if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) {
-
- // add to the parent of the last touched node
- mCurrentNode->mParent->push_back(pcNode);
- mLastNodeIndex++;
- }
- else if(hierarchy >= mLastNodeIndex) {
-
- // place it at the current position in the hierarchy
- mCurrentNode->push_back(pcNode);
- mLastNodeIndex = hierarchy;
- }
- else {
- // need to go back to the specified position in the hierarchy.
- InverseNodeSearch(pcNode,mCurrentNode);
- mLastNodeIndex++;
- }
- // Make this node the current node
- mCurrentNode = pcNode;
- }
- break;
-
- case Discreet3DS::CHUNK_TRACKDUMMYOBJNAME:
-
- // This is the "real" name of a $$$DUMMY object
- {
- const char* sz = (const char*) stream->GetPtr();
- while (stream->GetI1());
-
- // If object name is DUMMY, take this one instead
- if (mCurrentNode->mName == "$$$DUMMY") {
- //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
- mCurrentNode->mName = std::string(sz);
- break;
- }
- }
- break;
-
- case Discreet3DS::CHUNK_TRACKPIVOT:
-
- if ( Discreet3DS::CHUNK_TRACKINFO != parent)
- {
- DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object");
- break;
- }
-
- // Pivot = origin of rotation and scaling
- mCurrentNode->vPivot.x = stream->GetF4();
- mCurrentNode->vPivot.y = stream->GetF4();
- mCurrentNode->vPivot.z = stream->GetF4();
- break;
-
-
- // ////////////////////////////////////////////////////////////////////
- // POSITION KEYFRAME
- case Discreet3DS::CHUNK_TRACKPOS:
- {
- stream->IncPtr(10);
- const unsigned int numFrames = stream->GetI4();
- bool sortKeys = false;
-
- // This could also be meant as the target position for
- // (targeted) lights and cameras
- std::vector<aiVectorKey>* l;
- if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) {
- l = & mCurrentNode->aTargetPositionKeys;
- }
- else l = & mCurrentNode->aPositionKeys;
-
- l->reserve(numFrames);
- for (unsigned int i = 0; i < numFrames;++i) {
- const unsigned int fidx = stream->GetI4();
-
- // Setup a new position key
- aiVectorKey v;
- v.mTime = (double)fidx;
-
- SkipTCBInfo();
- v.mValue.x = stream->GetF4();
- v.mValue.y = stream->GetF4();
- v.mValue.z = stream->GetF4();
-
- // check whether we'll need to sort the keys
- if (!l->empty() && v.mTime <= l->back().mTime)
- sortKeys = true;
-
- // Add the new keyframe to the list
- l->push_back(v);
- }
-
- // Sort all keys with ascending time values and remove duplicates?
- if (sortKeys) {
- std::stable_sort(l->begin(),l->end());
- l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
- }}
-
- break;
-
- // ////////////////////////////////////////////////////////////////////
- // CAMERA ROLL KEYFRAME
- case Discreet3DS::CHUNK_TRACKROLL:
- {
- // roll keys are accepted for cameras only
- if (parent != Discreet3DS::CHUNK_TRACKCAMERA) {
- DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
- break;
- }
- bool sortKeys = false;
- std::vector<aiFloatKey>* l = &mCurrentNode->aCameraRollKeys;
-
- stream->IncPtr(10);
- const unsigned int numFrames = stream->GetI4();
- l->reserve(numFrames);
- for (unsigned int i = 0; i < numFrames;++i) {
- const unsigned int fidx = stream->GetI4();
-
- // Setup a new position key
- aiFloatKey v;
- v.mTime = (double)fidx;
-
- // This is just a single float
- SkipTCBInfo();
- v.mValue = stream->GetF4();
-
- // Check whether we'll need to sort the keys
- if (!l->empty() && v.mTime <= l->back().mTime)
- sortKeys = true;
-
- // Add the new keyframe to the list
- l->push_back(v);
- }
-
- // Sort all keys with ascending time values and remove duplicates?
- if (sortKeys) {
- std::stable_sort(l->begin(),l->end());
- l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() );
- }}
- break;
-
-
- // ////////////////////////////////////////////////////////////////////
- // CAMERA FOV KEYFRAME
- case Discreet3DS::CHUNK_TRACKFOV:
- {
- DefaultLogger::get()->error("3DS: Skipping FOV animation track. "
- "This is not supported");
- }
- break;
-
-
- // ////////////////////////////////////////////////////////////////////
- // ROTATION KEYFRAME
- case Discreet3DS::CHUNK_TRACKROTATE:
- {
- stream->IncPtr(10);
- const unsigned int numFrames = stream->GetI4();
-
- bool sortKeys = false;
- std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
- l->reserve(numFrames);
-
- for (unsigned int i = 0; i < numFrames;++i) {
- const unsigned int fidx = stream->GetI4();
- SkipTCBInfo();
-
- aiQuatKey v;
- v.mTime = (double)fidx;
-
- // The rotation keyframe is given as an axis-angle pair
- const float rad = stream->GetF4();
- aiVector3D axis;
- axis.x = stream->GetF4();
- axis.y = stream->GetF4();
- axis.z = stream->GetF4();
-
- if (!axis.x && !axis.y && !axis.z)
- axis.y = 1.f;
-
- // Construct a rotation quaternion from the axis-angle pair
- v.mValue = aiQuaternion(axis,rad);
-
- // Check whether we'll need to sort the keys
- if (!l->empty() && v.mTime <= l->back().mTime)
- sortKeys = true;
-
- // add the new keyframe to the list
- l->push_back(v);
- }
- // Sort all keys with ascending time values and remove duplicates?
- if (sortKeys) {
- std::stable_sort(l->begin(),l->end());
- l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() );
- }}
- break;
-
- // ////////////////////////////////////////////////////////////////////
- // SCALING KEYFRAME
- case Discreet3DS::CHUNK_TRACKSCALE:
- {
- stream->IncPtr(10);
- const unsigned int numFrames = stream->GetI2();
- stream->IncPtr(2);
-
- bool sortKeys = false;
- std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys;
- l->reserve(numFrames);
-
- for (unsigned int i = 0; i < numFrames;++i) {
- const unsigned int fidx = stream->GetI4();
- SkipTCBInfo();
-
- // Setup a new key
- aiVectorKey v;
- v.mTime = (double)fidx;
-
- // ... and read its value
- v.mValue.x = stream->GetF4();
- v.mValue.y = stream->GetF4();
- v.mValue.z = stream->GetF4();
-
- // check whether we'll need to sort the keys
- if (!l->empty() && v.mTime <= l->back().mTime)
- sortKeys = true;
-
- // Remove zero-scalings on singular axes - they've been reported to be there erroneously in some strange files
- if (!v.mValue.x) v.mValue.x = 1.f;
- if (!v.mValue.y) v.mValue.y = 1.f;
- if (!v.mValue.z) v.mValue.z = 1.f;
-
- l->push_back(v);
- }
- // Sort all keys with ascending time values and remove duplicates?
- if (sortKeys) {
- std::stable_sort(l->begin(),l->end());
- l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
- }}
- break;
- };
-
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_TRACKOBJNAME:
+
+ // This is the name of the object to which the track applies. The chunk also
+ // defines the position of this object in the hierarchy.
+ {
+
+ // First of all: get the name of the object
+ unsigned int cnt = 0;
+ const char* sz = (const char*)stream->GetPtr();
+
+ while (stream->GetI1())++cnt;
+ std::string name = std::string(sz,cnt);
+
+ // Now find out whether we have this node already (target animation channels
+ // are stored with a separate object ID)
+ D3DS::Node* pcNode = FindNode(mRootNode,name);
+ int instanceNumber = 1;
+
+ if ( pcNode)
+ {
+ // if the source is not a CHUNK_TRACKINFO block it wont be an object instance
+ if (parent != Discreet3DS::CHUNK_TRACKINFO)
+ {
+ mCurrentNode = pcNode;
+ break;
+ }
+ pcNode->mInstanceCount++;
+ instanceNumber = pcNode->mInstanceCount;
+ }
+ pcNode = new D3DS::Node();
+ pcNode->mName = name;
+ pcNode->mInstanceNumber = instanceNumber;
+
+ // There are two unknown values which we can safely ignore
+ stream->IncPtr(4);
+
+ // Now read the hierarchy position of the object
+ uint16_t hierarchy = stream->GetI2() + 1;
+ pcNode->mHierarchyPos = hierarchy;
+ pcNode->mHierarchyIndex = mLastNodeIndex;
+
+ // And find a proper position in the graph for it
+ if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) {
+
+ // add to the parent of the last touched node
+ mCurrentNode->mParent->push_back(pcNode);
+ mLastNodeIndex++;
+ }
+ else if(hierarchy >= mLastNodeIndex) {
+
+ // place it at the current position in the hierarchy
+ mCurrentNode->push_back(pcNode);
+ mLastNodeIndex = hierarchy;
+ }
+ else {
+ // need to go back to the specified position in the hierarchy.
+ InverseNodeSearch(pcNode,mCurrentNode);
+ mLastNodeIndex++;
+ }
+ // Make this node the current node
+ mCurrentNode = pcNode;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_TRACKDUMMYOBJNAME:
+
+ // This is the "real" name of a $$$DUMMY object
+ {
+ const char* sz = (const char*) stream->GetPtr();
+ while (stream->GetI1());
+
+ // If object name is DUMMY, take this one instead
+ if (mCurrentNode->mName == "$$$DUMMY") {
+ //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
+ mCurrentNode->mName = std::string(sz);
+ break;
+ }
+ }
+ break;
+
+ case Discreet3DS::CHUNK_TRACKPIVOT:
+
+ if ( Discreet3DS::CHUNK_TRACKINFO != parent)
+ {
+ DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object");
+ break;
+ }
+
+ // Pivot = origin of rotation and scaling
+ mCurrentNode->vPivot.x = stream->GetF4();
+ mCurrentNode->vPivot.y = stream->GetF4();
+ mCurrentNode->vPivot.z = stream->GetF4();
+ break;
+
+
+ // ////////////////////////////////////////////////////////////////////
+ // POSITION KEYFRAME
+ case Discreet3DS::CHUNK_TRACKPOS:
+ {
+ stream->IncPtr(10);
+ const unsigned int numFrames = stream->GetI4();
+ bool sortKeys = false;
+
+ // This could also be meant as the target position for
+ // (targeted) lights and cameras
+ std::vector<aiVectorKey>* l;
+ if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) {
+ l = & mCurrentNode->aTargetPositionKeys;
+ }
+ else l = & mCurrentNode->aPositionKeys;
+
+ l->reserve(numFrames);
+ for (unsigned int i = 0; i < numFrames;++i) {
+ const unsigned int fidx = stream->GetI4();
+
+ // Setup a new position key
+ aiVectorKey v;
+ v.mTime = (double)fidx;
+
+ SkipTCBInfo();
+ v.mValue.x = stream->GetF4();
+ v.mValue.y = stream->GetF4();
+ v.mValue.z = stream->GetF4();
+
+ // check whether we'll need to sort the keys
+ if (!l->empty() && v.mTime <= l->back().mTime)
+ sortKeys = true;
+
+ // Add the new keyframe to the list
+ l->push_back(v);
+ }
+
+ // Sort all keys with ascending time values and remove duplicates?
+ if (sortKeys) {
+ std::stable_sort(l->begin(),l->end());
+ l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
+ }}
+
+ break;
+
+ // ////////////////////////////////////////////////////////////////////
+ // CAMERA ROLL KEYFRAME
+ case Discreet3DS::CHUNK_TRACKROLL:
+ {
+ // roll keys are accepted for cameras only
+ if (parent != Discreet3DS::CHUNK_TRACKCAMERA) {
+ DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
+ break;
+ }
+ bool sortKeys = false;
+ std::vector<aiFloatKey>* l = &mCurrentNode->aCameraRollKeys;
+
+ stream->IncPtr(10);
+ const unsigned int numFrames = stream->GetI4();
+ l->reserve(numFrames);
+ for (unsigned int i = 0; i < numFrames;++i) {
+ const unsigned int fidx = stream->GetI4();
+
+ // Setup a new position key
+ aiFloatKey v;
+ v.mTime = (double)fidx;
+
+ // This is just a single float
+ SkipTCBInfo();
+ v.mValue = stream->GetF4();
+
+ // Check whether we'll need to sort the keys
+ if (!l->empty() && v.mTime <= l->back().mTime)
+ sortKeys = true;
+
+ // Add the new keyframe to the list
+ l->push_back(v);
+ }
+
+ // Sort all keys with ascending time values and remove duplicates?
+ if (sortKeys) {
+ std::stable_sort(l->begin(),l->end());
+ l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() );
+ }}
+ break;
+
+
+ // ////////////////////////////////////////////////////////////////////
+ // CAMERA FOV KEYFRAME
+ case Discreet3DS::CHUNK_TRACKFOV:
+ {
+ DefaultLogger::get()->error("3DS: Skipping FOV animation track. "
+ "This is not supported");
+ }
+ break;
+
+
+ // ////////////////////////////////////////////////////////////////////
+ // ROTATION KEYFRAME
+ case Discreet3DS::CHUNK_TRACKROTATE:
+ {
+ stream->IncPtr(10);
+ const unsigned int numFrames = stream->GetI4();
+
+ bool sortKeys = false;
+ std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
+ l->reserve(numFrames);
+
+ for (unsigned int i = 0; i < numFrames;++i) {
+ const unsigned int fidx = stream->GetI4();
+ SkipTCBInfo();
+
+ aiQuatKey v;
+ v.mTime = (double)fidx;
+
+ // The rotation keyframe is given as an axis-angle pair
+ const float rad = stream->GetF4();
+ aiVector3D axis;
+ axis.x = stream->GetF4();
+ axis.y = stream->GetF4();
+ axis.z = stream->GetF4();
+
+ if (!axis.x && !axis.y && !axis.z)
+ axis.y = 1.f;
+
+ // Construct a rotation quaternion from the axis-angle pair
+ v.mValue = aiQuaternion(axis,rad);
+
+ // Check whether we'll need to sort the keys
+ if (!l->empty() && v.mTime <= l->back().mTime)
+ sortKeys = true;
+
+ // add the new keyframe to the list
+ l->push_back(v);
+ }
+ // Sort all keys with ascending time values and remove duplicates?
+ if (sortKeys) {
+ std::stable_sort(l->begin(),l->end());
+ l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() );
+ }}
+ break;
+
+ // ////////////////////////////////////////////////////////////////////
+ // SCALING KEYFRAME
+ case Discreet3DS::CHUNK_TRACKSCALE:
+ {
+ stream->IncPtr(10);
+ const unsigned int numFrames = stream->GetI2();
+ stream->IncPtr(2);
+
+ bool sortKeys = false;
+ std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys;
+ l->reserve(numFrames);
+
+ for (unsigned int i = 0; i < numFrames;++i) {
+ const unsigned int fidx = stream->GetI4();
+ SkipTCBInfo();
+
+ // Setup a new key
+ aiVectorKey v;
+ v.mTime = (double)fidx;
+
+ // ... and read its value
+ v.mValue.x = stream->GetF4();
+ v.mValue.y = stream->GetF4();
+ v.mValue.z = stream->GetF4();
+
+ // check whether we'll need to sort the keys
+ if (!l->empty() && v.mTime <= l->back().mTime)
+ sortKeys = true;
+
+ // Remove zero-scalings on singular axes - they've been reported to be there erroneously in some strange files
+ if (!v.mValue.x) v.mValue.x = 1.f;
+ if (!v.mValue.y) v.mValue.y = 1.f;
+ if (!v.mValue.z) v.mValue.z = 1.f;
+
+ l->push_back(v);
+ }
+ // Sort all keys with ascending time values and remove duplicates?
+ if (sortKeys) {
+ std::stable_sort(l->begin(),l->end());
+ l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
+ }}
+ break;
+ };
+
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
// Read a face chunk - it contains smoothing groups and material assignments
void Discreet3DSImporter::ParseFaceChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // Get the mesh we're currently working on
- D3DS::Mesh& mMesh = mScene->mMeshes.back();
-
- // Get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_SMOOLIST:
- {
- // This is the list of smoothing groups - a bitfield for every face.
- // Up to 32 smoothing groups assigned to a single face.
- unsigned int num = chunkSize/4, m = 0;
- for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) {
- // nth bit is set for nth smoothing group
- (*i).iSmoothGroup = stream->GetI4();
- }}
- break;
-
- case Discreet3DS::CHUNK_FACEMAT:
- {
- // at fist an asciiz with the material name
- const char* sz = (const char*)stream->GetPtr();
- while (stream->GetI1());
-
- // find the index of the material
- unsigned int idx = 0xcdcdcdcd, cnt = 0;
- for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin();i != mScene->mMaterials.end();++i,++cnt) {
- // use case independent comparisons. hopefully it will work.
- if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) {
- idx = cnt;
- break;
- }
- }
- if (0xcdcdcdcd == idx) {
- DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
- }
-
- // Now continue and read all material indices
- cnt = (uint16_t)stream->GetI2();
- for (unsigned int i = 0; i < cnt;++i) {
- unsigned int fidx = (uint16_t)stream->GetI2();
-
- // check range
- if (fidx >= mMesh.mFaceMaterials.size()) {
- DefaultLogger::get()->error("3DS: Invalid face index in face material list");
- }
- else mMesh.mFaceMaterials[fidx] = idx;
- }}
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // Get the mesh we're currently working on
+ D3DS::Mesh& mMesh = mScene->mMeshes.back();
+
+ // Get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_SMOOLIST:
+ {
+ // This is the list of smoothing groups - a bitfield for every face.
+ // Up to 32 smoothing groups assigned to a single face.
+ unsigned int num = chunkSize/4, m = 0;
+ if (num > mMesh.mFaces.size()) {
+ throw DeadlyImportError("3DS: More smoothing groups than faces");
+ }
+ for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) {
+ // nth bit is set for nth smoothing group
+ (*i).iSmoothGroup = stream->GetI4();
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_FACEMAT:
+ {
+ // at fist an asciiz with the material name
+ const char* sz = (const char*)stream->GetPtr();
+ while (stream->GetI1());
+
+ // find the index of the material
+ unsigned int idx = 0xcdcdcdcd, cnt = 0;
+ for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin();i != mScene->mMaterials.end();++i,++cnt) {
+ // use case independent comparisons. hopefully it will work.
+ if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) {
+ idx = cnt;
+ break;
+ }
+ }
+ if (0xcdcdcdcd == idx) {
+ DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
+ }
+
+ // Now continue and read all material indices
+ cnt = (uint16_t)stream->GetI2();
+ for (unsigned int i = 0; i < cnt;++i) {
+ unsigned int fidx = (uint16_t)stream->GetI2();
+
+ // check range
+ if (fidx >= mMesh.mFaceMaterials.size()) {
+ DefaultLogger::get()->error("3DS: Invalid face index in face material list");
+ }
+ else mMesh.mFaceMaterials[fidx] = idx;
+ }}
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
// Read a mesh chunk. Here's the actual mesh data
void Discreet3DSImporter::ParseMeshChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // Get the mesh we're currently working on
- D3DS::Mesh& mMesh = mScene->mMeshes.back();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_VERTLIST:
- {
- // This is the list of all vertices in the current mesh
- int num = (int)(uint16_t)stream->GetI2();
- mMesh.mPositions.reserve(num);
- while (num-- > 0) {
- aiVector3D v;
- v.x = stream->GetF4();
- v.y = stream->GetF4();
- v.z = stream->GetF4();
- mMesh.mPositions.push_back(v);
- }}
- break;
- case Discreet3DS::CHUNK_TRMATRIX:
- {
- // This is the RLEATIVE transformation matrix of the current mesh. Vertices are
- // pretransformed by this matrix wonder.
- mMesh.mMat.a1 = stream->GetF4();
- mMesh.mMat.b1 = stream->GetF4();
- mMesh.mMat.c1 = stream->GetF4();
- mMesh.mMat.a2 = stream->GetF4();
- mMesh.mMat.b2 = stream->GetF4();
- mMesh.mMat.c2 = stream->GetF4();
- mMesh.mMat.a3 = stream->GetF4();
- mMesh.mMat.b3 = stream->GetF4();
- mMesh.mMat.c3 = stream->GetF4();
- mMesh.mMat.a4 = stream->GetF4();
- mMesh.mMat.b4 = stream->GetF4();
- mMesh.mMat.c4 = stream->GetF4();
- }
- break;
-
- case Discreet3DS::CHUNK_MAPLIST:
- {
- // This is the list of all UV coords in the current mesh
- int num = (int)(uint16_t)stream->GetI2();
- mMesh.mTexCoords.reserve(num);
- while (num-- > 0) {
- aiVector3D v;
- v.x = stream->GetF4();
- v.y = stream->GetF4();
- mMesh.mTexCoords.push_back(v);
- }}
- break;
-
- case Discreet3DS::CHUNK_FACELIST:
- {
- // This is the list of all faces in the current mesh
- int num = (int)(uint16_t)stream->GetI2();
- mMesh.mFaces.reserve(num);
- while (num-- > 0) {
- // 3DS faces are ALWAYS triangles
- mMesh.mFaces.push_back(D3DS::Face());
- D3DS::Face& sFace = mMesh.mFaces.back();
-
- sFace.mIndices[0] = (uint16_t)stream->GetI2();
- sFace.mIndices[1] = (uint16_t)stream->GetI2();
- sFace.mIndices[2] = (uint16_t)stream->GetI2();
-
- stream->IncPtr(2); // skip edge visibility flag
- }
-
- // Resize the material array (0xcdcdcdcd marks the default material; so if a face is
- // not referenced by a material, $$DEFAULT will be assigned to it)
- mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
-
- // Larger 3DS files could have multiple FACE chunks here
- chunkSize = stream->GetRemainingSizeToLimit();
- if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
- ParseFaceChunk();
- }
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // Get the mesh we're currently working on
+ D3DS::Mesh& mMesh = mScene->mMeshes.back();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_VERTLIST:
+ {
+ // This is the list of all vertices in the current mesh
+ int num = (int)(uint16_t)stream->GetI2();
+ mMesh.mPositions.reserve(num);
+ while (num-- > 0) {
+ aiVector3D v;
+ v.x = stream->GetF4();
+ v.y = stream->GetF4();
+ v.z = stream->GetF4();
+ mMesh.mPositions.push_back(v);
+ }}
+ break;
+ case Discreet3DS::CHUNK_TRMATRIX:
+ {
+ // This is the RLEATIVE transformation matrix of the current mesh. Vertices are
+ // pretransformed by this matrix wonder.
+ mMesh.mMat.a1 = stream->GetF4();
+ mMesh.mMat.b1 = stream->GetF4();
+ mMesh.mMat.c1 = stream->GetF4();
+ mMesh.mMat.a2 = stream->GetF4();
+ mMesh.mMat.b2 = stream->GetF4();
+ mMesh.mMat.c2 = stream->GetF4();
+ mMesh.mMat.a3 = stream->GetF4();
+ mMesh.mMat.b3 = stream->GetF4();
+ mMesh.mMat.c3 = stream->GetF4();
+ mMesh.mMat.a4 = stream->GetF4();
+ mMesh.mMat.b4 = stream->GetF4();
+ mMesh.mMat.c4 = stream->GetF4();
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAPLIST:
+ {
+ // This is the list of all UV coords in the current mesh
+ int num = (int)(uint16_t)stream->GetI2();
+ mMesh.mTexCoords.reserve(num);
+ while (num-- > 0) {
+ aiVector3D v;
+ v.x = stream->GetF4();
+ v.y = stream->GetF4();
+ mMesh.mTexCoords.push_back(v);
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_FACELIST:
+ {
+ // This is the list of all faces in the current mesh
+ int num = (int)(uint16_t)stream->GetI2();
+ mMesh.mFaces.reserve(num);
+ while (num-- > 0) {
+ // 3DS faces are ALWAYS triangles
+ mMesh.mFaces.push_back(D3DS::Face());
+ D3DS::Face& sFace = mMesh.mFaces.back();
+
+ sFace.mIndices[0] = (uint16_t)stream->GetI2();
+ sFace.mIndices[1] = (uint16_t)stream->GetI2();
+ sFace.mIndices[2] = (uint16_t)stream->GetI2();
+
+ stream->IncPtr(2); // skip edge visibility flag
+ }
+
+ // Resize the material array (0xcdcdcdcd marks the default material; so if a face is
+ // not referenced by a material, $$DEFAULT will be assigned to it)
+ mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
+
+ // Larger 3DS files could have multiple FACE chunks here
+ chunkSize = stream->GetRemainingSizeToLimit();
+ if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
+ ParseFaceChunk();
+ }
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
// Read a 3DS material chunk
void Discreet3DSImporter::ParseMaterialChunk()
{
- ASSIMP_3DS_BEGIN_CHUNK();
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_MAT_MATNAME:
-
- {
- // The material name string is already zero-terminated, but we need to be sure ...
- const char* sz = (const char*)stream->GetPtr();
- unsigned int cnt = 0;
- while (stream->GetI1())
- ++cnt;
-
- if (!cnt) {
- // This may not be, we use the default name instead
- DefaultLogger::get()->error("3DS: Empty material name");
- }
- else mScene->mMaterials.back().mName = std::string(sz,cnt);
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_DIFFUSE:
- {
- // This is the diffuse material color
- aiColor3D* pc = &mScene->mMaterials.back().mDiffuse;
- ParseColorChunk(pc);
- if (is_qnan(pc->r)) {
- // color chunk is invalid. Simply ignore it
- DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
- pc->r = pc->g = pc->b = 1.0f;
- }}
- break;
-
- case Discreet3DS::CHUNK_MAT_SPECULAR:
- {
- // This is the specular material color
- aiColor3D* pc = &mScene->mMaterials.back().mSpecular;
- ParseColorChunk(pc);
- if (is_qnan(pc->r)) {
- // color chunk is invalid. Simply ignore it
- DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
- pc->r = pc->g = pc->b = 1.0f;
- }}
- break;
-
- case Discreet3DS::CHUNK_MAT_AMBIENT:
- {
- // This is the ambient material color
- aiColor3D* pc = &mScene->mMaterials.back().mAmbient;
- ParseColorChunk(pc);
- if (is_qnan(pc->r)) {
- // color chunk is invalid. Simply ignore it
- DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
- pc->r = pc->g = pc->b = 0.0f;
- }}
- break;
-
- case Discreet3DS::CHUNK_MAT_SELF_ILLUM:
- {
- // This is the emissive material color
- aiColor3D* pc = &mScene->mMaterials.back().mEmissive;
- ParseColorChunk(pc);
- if (is_qnan(pc->r)) {
- // color chunk is invalid. Simply ignore it
- DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
- pc->r = pc->g = pc->b = 0.0f;
- }}
- break;
-
- case Discreet3DS::CHUNK_MAT_TRANSPARENCY:
- {
- // This is the material's transparency
- float* pcf = &mScene->mMaterials.back().mTransparency;
- *pcf = ParsePercentageChunk();
-
- // NOTE: transparency, not opacity
- if (is_qnan(*pcf))
- *pcf = 1.0f;
- else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f;
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_SHADING:
- // This is the material shading mode
- mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2();
- break;
-
- case Discreet3DS::CHUNK_MAT_TWO_SIDE:
- // This is the two-sided flag
- mScene->mMaterials.back().mTwoSided = true;
- break;
-
- case Discreet3DS::CHUNK_MAT_SHININESS:
- { // This is the shininess of the material
- float* pcf = &mScene->mMaterials.back().mSpecularExponent;
- *pcf = ParsePercentageChunk();
- if (is_qnan(*pcf))
- *pcf = 0.0f;
- else *pcf *= (float)0xFFFF;
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT:
- { // This is the shininess strength of the material
- float* pcf = &mScene->mMaterials.back().mShininessStrength;
- *pcf = ParsePercentageChunk();
- if (is_qnan(*pcf))
- *pcf = 0.0f;
- else *pcf *= (float)0xffff / 100.0f;
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_SELF_ILPCT:
- { // This is the self illumination strength of the material
- float f = ParsePercentageChunk();
- if (is_qnan(f))
- f = 0.0f;
- else f *= (float)0xFFFF / 100.0f;
- mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
- }
- break;
-
- // Parse texture chunks
- case Discreet3DS::CHUNK_MAT_TEXTURE:
- // Diffuse texture
- ParseTextureChunk(&mScene->mMaterials.back().sTexDiffuse);
- break;
- case Discreet3DS::CHUNK_MAT_BUMPMAP:
- // Height map
- ParseTextureChunk(&mScene->mMaterials.back().sTexBump);
- break;
- case Discreet3DS::CHUNK_MAT_OPACMAP:
- // Opacity texture
- ParseTextureChunk(&mScene->mMaterials.back().sTexOpacity);
- break;
- case Discreet3DS::CHUNK_MAT_MAT_SHINMAP:
- // Shininess map
- ParseTextureChunk(&mScene->mMaterials.back().sTexShininess);
- break;
- case Discreet3DS::CHUNK_MAT_SPECMAP:
- // Specular map
- ParseTextureChunk(&mScene->mMaterials.back().sTexSpecular);
- break;
- case Discreet3DS::CHUNK_MAT_SELFIMAP:
- // Self-illumination (emissive) map
- ParseTextureChunk(&mScene->mMaterials.back().sTexEmissive);
- break;
- case Discreet3DS::CHUNK_MAT_REFLMAP:
- // Reflection map
- ParseTextureChunk(&mScene->mMaterials.back().sTexReflective);
- break;
- };
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_MAT_MATNAME:
+
+ {
+ // The material name string is already zero-terminated, but we need to be sure ...
+ const char* sz = (const char*)stream->GetPtr();
+ unsigned int cnt = 0;
+ while (stream->GetI1())
+ ++cnt;
+
+ if (!cnt) {
+ // This may not be, we use the default name instead
+ DefaultLogger::get()->error("3DS: Empty material name");
+ }
+ else mScene->mMaterials.back().mName = std::string(sz,cnt);
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_DIFFUSE:
+ {
+ // This is the diffuse material color
+ aiColor3D* pc = &mScene->mMaterials.back().mDiffuse;
+ ParseColorChunk(pc);
+ if (is_qnan(pc->r)) {
+ // color chunk is invalid. Simply ignore it
+ DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
+ pc->r = pc->g = pc->b = 1.0f;
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SPECULAR:
+ {
+ // This is the specular material color
+ aiColor3D* pc = &mScene->mMaterials.back().mSpecular;
+ ParseColorChunk(pc);
+ if (is_qnan(pc->r)) {
+ // color chunk is invalid. Simply ignore it
+ DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
+ pc->r = pc->g = pc->b = 1.0f;
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_MAT_AMBIENT:
+ {
+ // This is the ambient material color
+ aiColor3D* pc = &mScene->mMaterials.back().mAmbient;
+ ParseColorChunk(pc);
+ if (is_qnan(pc->r)) {
+ // color chunk is invalid. Simply ignore it
+ DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
+ pc->r = pc->g = pc->b = 0.0f;
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SELF_ILLUM:
+ {
+ // This is the emissive material color
+ aiColor3D* pc = &mScene->mMaterials.back().mEmissive;
+ ParseColorChunk(pc);
+ if (is_qnan(pc->r)) {
+ // color chunk is invalid. Simply ignore it
+ DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
+ pc->r = pc->g = pc->b = 0.0f;
+ }}
+ break;
+
+ case Discreet3DS::CHUNK_MAT_TRANSPARENCY:
+ {
+ // This is the material's transparency
+ float* pcf = &mScene->mMaterials.back().mTransparency;
+ *pcf = ParsePercentageChunk();
+
+ // NOTE: transparency, not opacity
+ if (is_qnan(*pcf))
+ *pcf = 1.0f;
+ else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SHADING:
+ // This is the material shading mode
+ mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2();
+ break;
+
+ case Discreet3DS::CHUNK_MAT_TWO_SIDE:
+ // This is the two-sided flag
+ mScene->mMaterials.back().mTwoSided = true;
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SHININESS:
+ { // This is the shininess of the material
+ float* pcf = &mScene->mMaterials.back().mSpecularExponent;
+ *pcf = ParsePercentageChunk();
+ if (is_qnan(*pcf))
+ *pcf = 0.0f;
+ else *pcf *= (float)0xFFFF;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT:
+ { // This is the shininess strength of the material
+ float* pcf = &mScene->mMaterials.back().mShininessStrength;
+ *pcf = ParsePercentageChunk();
+ if (is_qnan(*pcf))
+ *pcf = 0.0f;
+ else *pcf *= (float)0xffff / 100.0f;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_SELF_ILPCT:
+ { // This is the self illumination strength of the material
+ float f = ParsePercentageChunk();
+ if (is_qnan(f))
+ f = 0.0f;
+ else f *= (float)0xFFFF / 100.0f;
+ mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
+ }
+ break;
+
+ // Parse texture chunks
+ case Discreet3DS::CHUNK_MAT_TEXTURE:
+ // Diffuse texture
+ ParseTextureChunk(&mScene->mMaterials.back().sTexDiffuse);
+ break;
+ case Discreet3DS::CHUNK_MAT_BUMPMAP:
+ // Height map
+ ParseTextureChunk(&mScene->mMaterials.back().sTexBump);
+ break;
+ case Discreet3DS::CHUNK_MAT_OPACMAP:
+ // Opacity texture
+ ParseTextureChunk(&mScene->mMaterials.back().sTexOpacity);
+ break;
+ case Discreet3DS::CHUNK_MAT_MAT_SHINMAP:
+ // Shininess map
+ ParseTextureChunk(&mScene->mMaterials.back().sTexShininess);
+ break;
+ case Discreet3DS::CHUNK_MAT_SPECMAP:
+ // Specular map
+ ParseTextureChunk(&mScene->mMaterials.back().sTexSpecular);
+ break;
+ case Discreet3DS::CHUNK_MAT_SELFIMAP:
+ // Self-illumination (emissive) map
+ ParseTextureChunk(&mScene->mMaterials.back().sTexEmissive);
+ break;
+ case Discreet3DS::CHUNK_MAT_REFLMAP:
+ // Reflection map
+ ParseTextureChunk(&mScene->mMaterials.back().sTexReflective);
+ break;
+ };
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
{
- ASSIMP_3DS_BEGIN_CHUNK();
-
- // get chunk type
- switch (chunk.Flag)
- {
- case Discreet3DS::CHUNK_MAPFILE:
- {
- // The material name string is already zero-terminated, but we need to be sure ...
- const char* sz = (const char*)stream->GetPtr();
- unsigned int cnt = 0;
- while (stream->GetI1())
- ++cnt;
- pcOut->mMapName = std::string(sz,cnt);
- }
- break;
-
-
- case Discreet3DS::CHUNK_PERCENTF:
- // Manually parse the blend factor
- pcOut->mTextureBlend = stream->GetF4();
- break;
-
- case Discreet3DS::CHUNK_PERCENTW:
- // Manually parse the blend factor
- pcOut->mTextureBlend = (float)((uint16_t)stream->GetI2()) / 100.0f;
- break;
-
- case Discreet3DS::CHUNK_MAT_MAP_USCALE:
- // Texture coordinate scaling in the U direction
- pcOut->mScaleU = stream->GetF4();
- if (0.0f == pcOut->mScaleU)
- {
- DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
- pcOut->mScaleU = 1.0f;
- }
- break;
- case Discreet3DS::CHUNK_MAT_MAP_VSCALE:
- // Texture coordinate scaling in the V direction
- pcOut->mScaleV = stream->GetF4();
- if (0.0f == pcOut->mScaleV)
- {
- DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
- pcOut->mScaleV = 1.0f;
- }
- break;
-
- case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
- // Texture coordinate offset in the U direction
- pcOut->mOffsetU = -stream->GetF4();
- break;
-
- case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
- // Texture coordinate offset in the V direction
- pcOut->mOffsetV = stream->GetF4();
- break;
-
- case Discreet3DS::CHUNK_MAT_MAP_ANG:
- // Texture coordinate rotation, CCW in DEGREES
- pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() );
- break;
-
- case Discreet3DS::CHUNK_MAT_MAP_TILING:
- {
- const uint16_t iFlags = stream->GetI2();
-
- // Get the mapping mode (for both axes)
- if (iFlags & 0x2u)
- pcOut->mMapMode = aiTextureMapMode_Mirror;
-
- else if (iFlags & 0x10u)
- pcOut->mMapMode = aiTextureMapMode_Decal;
-
- // wrapping in all remaining cases
- else pcOut->mMapMode = aiTextureMapMode_Wrap;
- }
- break;
- };
-
- ASSIMP_3DS_END_CHUNK();
+ ASSIMP_3DS_BEGIN_CHUNK();
+
+ // get chunk type
+ switch (chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_MAPFILE:
+ {
+ // The material name string is already zero-terminated, but we need to be sure ...
+ const char* sz = (const char*)stream->GetPtr();
+ unsigned int cnt = 0;
+ while (stream->GetI1())
+ ++cnt;
+ pcOut->mMapName = std::string(sz,cnt);
+ }
+ break;
+
+
+ case Discreet3DS::CHUNK_PERCENTF:
+ // Manually parse the blend factor
+ pcOut->mTextureBlend = stream->GetF4();
+ break;
+
+ case Discreet3DS::CHUNK_PERCENTW:
+ // Manually parse the blend factor
+ pcOut->mTextureBlend = (float)((uint16_t)stream->GetI2()) / 100.0f;
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MAP_USCALE:
+ // Texture coordinate scaling in the U direction
+ pcOut->mScaleU = stream->GetF4();
+ if (0.0f == pcOut->mScaleU)
+ {
+ DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
+ pcOut->mScaleU = 1.0f;
+ }
+ break;
+ case Discreet3DS::CHUNK_MAT_MAP_VSCALE:
+ // Texture coordinate scaling in the V direction
+ pcOut->mScaleV = stream->GetF4();
+ if (0.0f == pcOut->mScaleV)
+ {
+ DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
+ pcOut->mScaleV = 1.0f;
+ }
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MAP_UOFFSET:
+ // Texture coordinate offset in the U direction
+ pcOut->mOffsetU = -stream->GetF4();
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MAP_VOFFSET:
+ // Texture coordinate offset in the V direction
+ pcOut->mOffsetV = stream->GetF4();
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MAP_ANG:
+ // Texture coordinate rotation, CCW in DEGREES
+ pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() );
+ break;
+
+ case Discreet3DS::CHUNK_MAT_MAP_TILING:
+ {
+ const uint16_t iFlags = stream->GetI2();
+
+ // Get the mapping mode (for both axes)
+ if (iFlags & 0x2u)
+ pcOut->mMapMode = aiTextureMapMode_Mirror;
+
+ else if (iFlags & 0x10u)
+ pcOut->mMapMode = aiTextureMapMode_Decal;
+
+ // wrapping in all remaining cases
+ else pcOut->mMapMode = aiTextureMapMode_Wrap;
+ }
+ break;
+ };
+
+ ASSIMP_3DS_END_CHUNK();
}
// ------------------------------------------------------------------------------------------------
// Read a percentage chunk
float Discreet3DSImporter::ParsePercentageChunk()
{
- Discreet3DS::Chunk chunk;
- ReadChunk(&chunk);
-
- if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag)
- return stream->GetF4();
- else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag)
- return (float)((uint16_t)stream->GetI2()) / (float)0xFFFF;
- return get_qnan();
+ Discreet3DS::Chunk chunk;
+ ReadChunk(&chunk);
+
+ if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag)
+ return stream->GetF4();
+ else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag)
+ return (float)((uint16_t)stream->GetI2()) / (float)0xFFFF;
+ return get_qnan();
}
// ------------------------------------------------------------------------------------------------
// Read a color chunk. If a percentage chunk is found instead it is read as a grayscale color
void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
- bool acceptPercent)
+ bool acceptPercent)
{
- ai_assert(out != NULL);
-
- // error return value
- const float qnan = get_qnan();
- static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan);
-
- Discreet3DS::Chunk chunk;
- ReadChunk(&chunk);
- const unsigned int diff = chunk.Size - sizeof(Discreet3DS::Chunk);
-
- bool bGamma = false;
-
- // Get the type of the chunk
- switch(chunk.Flag)
- {
- case Discreet3DS::CHUNK_LINRGBF:
- bGamma = true;
-
- case Discreet3DS::CHUNK_RGBF:
- if (sizeof(float) * 3 > diff) {
- *out = clrError;
- return;
- }
- out->r = stream->GetF4();
- out->g = stream->GetF4();
- out->b = stream->GetF4();
- break;
-
- case Discreet3DS::CHUNK_LINRGBB:
- bGamma = true;
- case Discreet3DS::CHUNK_RGBB:
- if (sizeof(char) * 3 > diff) {
- *out = clrError;
- return;
- }
- out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
- out->g = (float)(uint8_t)stream->GetI1() / 255.0f;
- out->b = (float)(uint8_t)stream->GetI1() / 255.0f;
- break;
-
- // Percentage chunks are accepted, too.
- case Discreet3DS::CHUNK_PERCENTF:
- if (acceptPercent && 4 <= diff) {
- out->g = out->b = out->r = stream->GetF4();
- break;
- }
- *out = clrError;
- return;
-
- case Discreet3DS::CHUNK_PERCENTW:
- if (acceptPercent && 1 <= diff) {
- out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
- break;
- }
- *out = clrError;
- return;
-
- default:
- stream->IncPtr(diff);
- // Skip unknown chunks, hope this won't cause any problems.
- return ParseColorChunk(out,acceptPercent);
- };
- (void)bGamma;
+ ai_assert(out != NULL);
+
+ // error return value
+ const float qnan = get_qnan();
+ static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan);
+
+ Discreet3DS::Chunk chunk;
+ ReadChunk(&chunk);
+ const unsigned int diff = chunk.Size - sizeof(Discreet3DS::Chunk);
+
+ bool bGamma = false;
+
+ // Get the type of the chunk
+ switch(chunk.Flag)
+ {
+ case Discreet3DS::CHUNK_LINRGBF:
+ bGamma = true;
+
+ case Discreet3DS::CHUNK_RGBF:
+ if (sizeof(float) * 3 > diff) {
+ *out = clrError;
+ return;
+ }
+ out->r = stream->GetF4();
+ out->g = stream->GetF4();
+ out->b = stream->GetF4();
+ break;
+
+ case Discreet3DS::CHUNK_LINRGBB:
+ bGamma = true;
+ case Discreet3DS::CHUNK_RGBB:
+ if (sizeof(char) * 3 > diff) {
+ *out = clrError;
+ return;
+ }
+ out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
+ out->g = (float)(uint8_t)stream->GetI1() / 255.0f;
+ out->b = (float)(uint8_t)stream->GetI1() / 255.0f;
+ break;
+
+ // Percentage chunks are accepted, too.
+ case Discreet3DS::CHUNK_PERCENTF:
+ if (acceptPercent && 4 <= diff) {
+ out->g = out->b = out->r = stream->GetF4();
+ break;
+ }
+ *out = clrError;
+ return;
+
+ case Discreet3DS::CHUNK_PERCENTW:
+ if (acceptPercent && 1 <= diff) {
+ out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
+ break;
+ }
+ *out = clrError;
+ return;
+
+ default:
+ stream->IncPtr(diff);
+ // Skip unknown chunks, hope this won't cause any problems.
+ return ParseColorChunk(out,acceptPercent);
+ };
+ (void)bGamma;
}
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
diff --git a/src/3rdparty/assimp/code/3DSLoader.h b/src/3rdparty/assimp/code/3DSLoader.h
index bee129cc1..437ec94b4 100644
--- a/src/3rdparty/assimp/code/3DSLoader.h
+++ b/src/3rdparty/assimp/code/3DSLoader.h
@@ -3,11 +3,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -24,16 +24,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,14 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_3DSIMPORTER_H_INC
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
-struct aiNode;
#include "3DSHelper.h"
+#include "StreamReader.h"
+
+struct aiNode;
-namespace Assimp {
+namespace Assimp {
using namespace D3DS;
@@ -65,216 +67,216 @@ class Discreet3DSImporter : public BaseImporter
{
public:
- Discreet3DSImporter();
- ~Discreet3DSImporter();
+ Discreet3DSImporter();
+ ~Discreet3DSImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
-
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
-
- // -------------------------------------------------------------------
- /** Converts a temporary material to the outer representation
- */
- void ConvertMaterial(D3DS::Material& p_cMat,
- aiMaterial& p_pcOut);
-
- // -------------------------------------------------------------------
- /** Read a chunk
- *
- * @param pcOut Receives the current chunk
- */
- void ReadChunk(Discreet3DS::Chunk* pcOut);
-
- // -------------------------------------------------------------------
- /** Parse a percentage chunk. mCurrent will point to the next
- * chunk behind afterwards. If no percentage chunk is found
- * QNAN is returned.
- */
- float ParsePercentageChunk();
-
- // -------------------------------------------------------------------
- /** Parse a color chunk. mCurrent will point to the next
- * chunk behind afterwards. If no color chunk is found
- * QNAN is returned in all members.
- */
- void ParseColorChunk(aiColor3D* p_pcOut,
- bool p_bAcceptPercent = true);
-
-
- // -------------------------------------------------------------------
- /** Skip a chunk in the file
- */
- void SkipChunk();
-
- // -------------------------------------------------------------------
- /** Generate the nodegraph
- */
- void GenerateNodeGraph(aiScene* pcOut);
-
- // -------------------------------------------------------------------
- /** Parse a main top-level chunk in the file
- */
- void ParseMainChunk();
-
- // -------------------------------------------------------------------
- /** Parse a top-level chunk in the file
- */
- void ParseChunk(const char* name, unsigned int num);
-
- // -------------------------------------------------------------------
- /** Parse a top-level editor chunk in the file
- */
- void ParseEditorChunk();
-
- // -------------------------------------------------------------------
- /** Parse a top-level object chunk in the file
- */
- void ParseObjectChunk();
-
- // -------------------------------------------------------------------
- /** Parse a material chunk in the file
- */
- void ParseMaterialChunk();
-
- // -------------------------------------------------------------------
- /** Parse a mesh chunk in the file
- */
- void ParseMeshChunk();
-
- // -------------------------------------------------------------------
- /** Parse a light chunk in the file
- */
- void ParseLightChunk();
-
- // -------------------------------------------------------------------
- /** Parse a camera chunk in the file
- */
- void ParseCameraChunk();
-
- // -------------------------------------------------------------------
- /** Parse a face list chunk in the file
- */
- void ParseFaceChunk();
-
- // -------------------------------------------------------------------
- /** Parse a keyframe chunk in the file
- */
- void ParseKeyframeChunk();
-
- // -------------------------------------------------------------------
- /** Parse a hierarchy chunk in the file
- */
- void ParseHierarchyChunk(uint16_t parent);
-
- // -------------------------------------------------------------------
- /** Parse a texture chunk in the file
- */
- void ParseTextureChunk(D3DS::Texture* pcOut);
-
- // -------------------------------------------------------------------
- /** Convert the meshes in the file
- */
- void ConvertMeshes(aiScene* pcOut);
-
- // -------------------------------------------------------------------
- /** Replace the default material in the scene
- */
- void ReplaceDefaultMaterial();
-
- // -------------------------------------------------------------------
- /** Convert the whole scene
- */
- void ConvertScene(aiScene* pcOut);
-
- // -------------------------------------------------------------------
- /** generate unique vertices for a mesh
- */
- void MakeUnique(D3DS::Mesh& sMesh);
-
- // -------------------------------------------------------------------
- /** Add a node to the node graph
- */
- void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
- aiMatrix4x4& absTrafo);
-
- // -------------------------------------------------------------------
- /** Search for a node in the graph.
- * Called recursively
- */
- void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
-
- // -------------------------------------------------------------------
- /** Apply the master scaling factor to the mesh
- */
- void ApplyMasterScale(aiScene* pScene);
-
- // -------------------------------------------------------------------
- /** Clamp all indices in the file to a valid range
- */
- void CheckIndices(D3DS::Mesh& sMesh);
-
- // -------------------------------------------------------------------
- /** Skip the TCB info in a track key
- */
- void SkipTCBInfo();
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Converts a temporary material to the outer representation
+ */
+ void ConvertMaterial(D3DS::Material& p_cMat,
+ aiMaterial& p_pcOut);
+
+ // -------------------------------------------------------------------
+ /** Read a chunk
+ *
+ * @param pcOut Receives the current chunk
+ */
+ void ReadChunk(Discreet3DS::Chunk* pcOut);
+
+ // -------------------------------------------------------------------
+ /** Parse a percentage chunk. mCurrent will point to the next
+ * chunk behind afterwards. If no percentage chunk is found
+ * QNAN is returned.
+ */
+ float ParsePercentageChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a color chunk. mCurrent will point to the next
+ * chunk behind afterwards. If no color chunk is found
+ * QNAN is returned in all members.
+ */
+ void ParseColorChunk(aiColor3D* p_pcOut,
+ bool p_bAcceptPercent = true);
+
+
+ // -------------------------------------------------------------------
+ /** Skip a chunk in the file
+ */
+ void SkipChunk();
+
+ // -------------------------------------------------------------------
+ /** Generate the nodegraph
+ */
+ void GenerateNodeGraph(aiScene* pcOut);
+
+ // -------------------------------------------------------------------
+ /** Parse a main top-level chunk in the file
+ */
+ void ParseMainChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a top-level chunk in the file
+ */
+ void ParseChunk(const char* name, unsigned int num);
+
+ // -------------------------------------------------------------------
+ /** Parse a top-level editor chunk in the file
+ */
+ void ParseEditorChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a top-level object chunk in the file
+ */
+ void ParseObjectChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a material chunk in the file
+ */
+ void ParseMaterialChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a mesh chunk in the file
+ */
+ void ParseMeshChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a light chunk in the file
+ */
+ void ParseLightChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a camera chunk in the file
+ */
+ void ParseCameraChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a face list chunk in the file
+ */
+ void ParseFaceChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a keyframe chunk in the file
+ */
+ void ParseKeyframeChunk();
+
+ // -------------------------------------------------------------------
+ /** Parse a hierarchy chunk in the file
+ */
+ void ParseHierarchyChunk(uint16_t parent);
+
+ // -------------------------------------------------------------------
+ /** Parse a texture chunk in the file
+ */
+ void ParseTextureChunk(D3DS::Texture* pcOut);
+
+ // -------------------------------------------------------------------
+ /** Convert the meshes in the file
+ */
+ void ConvertMeshes(aiScene* pcOut);
+
+ // -------------------------------------------------------------------
+ /** Replace the default material in the scene
+ */
+ void ReplaceDefaultMaterial();
+
+ // -------------------------------------------------------------------
+ /** Convert the whole scene
+ */
+ void ConvertScene(aiScene* pcOut);
+
+ // -------------------------------------------------------------------
+ /** generate unique vertices for a mesh
+ */
+ void MakeUnique(D3DS::Mesh& sMesh);
+
+ // -------------------------------------------------------------------
+ /** Add a node to the node graph
+ */
+ void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
+ aiMatrix4x4& absTrafo);
+
+ // -------------------------------------------------------------------
+ /** Search for a node in the graph.
+ * Called recursively
+ */
+ void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
+
+ // -------------------------------------------------------------------
+ /** Apply the master scaling factor to the mesh
+ */
+ void ApplyMasterScale(aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ /** Clamp all indices in the file to a valid range
+ */
+ void CheckIndices(D3DS::Mesh& sMesh);
+
+ // -------------------------------------------------------------------
+ /** Skip the TCB info in a track key
+ */
+ void SkipTCBInfo();
protected:
- /** Stream to read from */
- StreamReaderLE* stream;
+ /** Stream to read from */
+ StreamReaderLE* stream;
- /** Last touched node index */
- short mLastNodeIndex;
+ /** Last touched node index */
+ short mLastNodeIndex;
- /** Current node, root node */
- D3DS::Node* mCurrentNode, *mRootNode;
+ /** Current node, root node */
+ D3DS::Node* mCurrentNode, *mRootNode;
- /** Scene under construction */
- D3DS::Scene* mScene;
+ /** Scene under construction */
+ D3DS::Scene* mScene;
- /** Ambient base color of the scene */
- aiColor3D mClrAmbient;
+ /** Ambient base color of the scene */
+ aiColor3D mClrAmbient;
- /** Master scaling factor of the scene */
- float mMasterScale;
+ /** Master scaling factor of the scene */
+ float mMasterScale;
- /** Path to the background image of the scene */
- std::string mBackgroundImage;
- bool bHasBG;
+ /** Path to the background image of the scene */
+ std::string mBackgroundImage;
+ bool bHasBG;
- /** true if PRJ file */
- bool bIsPrj;
+ /** true if PRJ file */
+ bool bIsPrj;
};
-#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
-
} // end of namespace Assimp
+#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
+
#endif // AI_3DSIMPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/ACLoader.cpp b/src/3rdparty/assimp/code/ACLoader.cpp
index 687e9acc4..c040d6bbd 100644
--- a/src/3rdparty/assimp/code/ACLoader.cpp
+++ b/src/3rdparty/assimp/code/ACLoader.cpp
@@ -4,12 +4,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -26,23 +26,23 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the AC3D importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
@@ -51,816 +51,857 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
#include "fast_atof.h"
#include "Subdivision.h"
+#include "Importer.h"
+#include "BaseImporter.h"
+#include <assimp/Importer.hpp>
+#include <assimp/light.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <assimp/config.h>
+#include <assimp/IOSystem.hpp>
+#include <memory>
using namespace Assimp;
static const aiImporterDesc desc = {
- "AC3D Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "ac acc ac3d"
+ "AC3D Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ac acc ac3d"
};
// ------------------------------------------------------------------------------------------------
// skip to the next token
#define AI_AC_SKIP_TO_NEXT_TOKEN() \
- if (!SkipSpaces(&buffer)) \
- { \
- DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
- continue; \
- }
+ if (!SkipSpaces(&buffer)) \
+ { \
+ DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
+ continue; \
+ }
// ------------------------------------------------------------------------------------------------
// read a string (may be enclosed in double quotation marks). buffer must point to "
#define AI_AC_GET_STRING(out) \
- ++buffer; \
- const char* sz = buffer; \
- while ('\"' != *buffer) \
- { \
- if (IsLineEnd( *buffer )) \
- { \
- DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
- out = "ERROR"; \
- break; \
- } \
- ++buffer; \
- } \
- if (IsLineEnd( *buffer ))continue; \
- out = std::string(sz,(unsigned int)(buffer-sz)); \
- ++buffer;
+ if (*buffer == '\0') { \
+ throw DeadlyImportError("AC3D: Unexpected EOF in string"); \
+ } \
+ ++buffer; \
+ const char* sz = buffer; \
+ while ('\"' != *buffer) \
+ { \
+ if (IsLineEnd( *buffer )) \
+ { \
+ DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
+ out = "ERROR"; \
+ break; \
+ } \
+ ++buffer; \
+ } \
+ if (IsLineEnd( *buffer ))continue; \
+ out = std::string(sz,(unsigned int)(buffer-sz)); \
+ ++buffer;
// ------------------------------------------------------------------------------------------------
-// read 1 to n floats prefixed with an optional predefined identifier
+// read 1 to n floats prefixed with an optional predefined identifier
#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name,name_length,num,out) \
- AI_AC_SKIP_TO_NEXT_TOKEN(); \
- if (name_length) \
- { \
- if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
- { \
- DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
- continue; \
- } \
- buffer += name_length+1; \
- } \
- for (unsigned int i = 0; i < num;++i) \
- { \
- AI_AC_SKIP_TO_NEXT_TOKEN(); \
- buffer = fast_atoreal_move<float>(buffer,((float*)out)[i]); \
- }
+ AI_AC_SKIP_TO_NEXT_TOKEN(); \
+ if (name_length) \
+ { \
+ if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
+ { \
+ DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
+ continue; \
+ } \
+ buffer += name_length+1; \
+ } \
+ for (unsigned int i = 0; i < num;++i) \
+ { \
+ AI_AC_SKIP_TO_NEXT_TOKEN(); \
+ buffer = fast_atoreal_move<float>(buffer,((float*)out)[i]); \
+ }
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
AC3DImporter::AC3DImporter()
+ : buffer(),
+ configSplitBFCull(),
+ configEvalSubdivision(),
+ mNumMeshes(),
+ mLights(),
+ lights(),
+ groups(),
+ polys(),
+ worlds()
{
- // nothing to be done here
+ // nothing to be done here
}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
AC3DImporter::~AC3DImporter()
{
- // nothing to be done here
+ // nothing to be done here
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- std::string extension = GetExtension(pFile);
-
- // fixme: are acc and ac3d *really* used? Some sources say they are
- if(extension == "ac" || extension == "ac3d" || extension == "acc") {
- return true;
- }
- if (!extension.length() || checkSig) {
- uint32_t token = AI_MAKE_MAGIC("AC3D");
- return CheckMagicToken(pIOHandler,pFile,&token,1,0);
- }
- return false;
+ std::string extension = GetExtension(pFile);
+
+ // fixme: are acc and ac3d *really* used? Some sources say they are
+ if(extension == "ac" || extension == "ac3d" || extension == "acc") {
+ return true;
+ }
+ if (!extension.length() || checkSig) {
+ uint32_t token = AI_MAKE_MAGIC("AC3D");
+ return CheckMagicToken(pIOHandler,pFile,&token,1,0);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* AC3DImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Get a pointer to the next line from the file
bool AC3DImporter::GetNextLine( )
{
- SkipLine(&buffer);
- return SkipSpaces(&buffer);
+ SkipLine(&buffer);
+ return SkipSpaces(&buffer);
}
// ------------------------------------------------------------------------------------------------
// Parse an object section in an AC file
void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
{
- if (!TokenMatch(buffer,"OBJECT",6))
- return;
-
- SkipSpaces(&buffer);
-
- ++mNumMeshes;
-
- objects.push_back(Object());
- Object& obj = objects.back();
-
- aiLight* light = NULL;
- if (!ASSIMP_strincmp(buffer,"light",5))
- {
- // This is a light source. Add it to the list
- mLights->push_back(light = new aiLight());
-
- // Return a point light with no attenuation
- light->mType = aiLightSource_POINT;
- light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
- light->mAttenuationConstant = 1.f;
-
- // Generate a default name for both the light source and the node
- // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
- light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
- obj.name = std::string( light->mName.data );
-
- DefaultLogger::get()->debug("AC3D: Light source encountered");
- obj.type = Object::Light;
- }
- else if (!ASSIMP_strincmp(buffer,"group",5))
- {
- obj.type = Object::Group;
- }
- else if (!ASSIMP_strincmp(buffer,"world",5))
- {
- obj.type = Object::World;
- }
- else obj.type = Object::Poly;
- while (GetNextLine())
- {
- if (TokenMatch(buffer,"kids",4))
- {
- SkipSpaces(&buffer);
- unsigned int num = strtoul10(buffer,&buffer);
- GetNextLine();
- if (num)
- {
- // load the children of this object recursively
- obj.children.reserve(num);
- for (unsigned int i = 0; i < num; ++i)
- LoadObjectSection(obj.children);
- }
- return;
- }
- else if (TokenMatch(buffer,"name",4))
- {
- SkipSpaces(&buffer);
- AI_AC_GET_STRING(obj.name);
-
- // If this is a light source, we'll also need to store
- // the name of the node in it.
- if (light)
- {
- light->mName.Set(obj.name);
- }
- }
- else if (TokenMatch(buffer,"texture",7))
- {
- SkipSpaces(&buffer);
- AI_AC_GET_STRING(obj.texture);
- }
- else if (TokenMatch(buffer,"texrep",6))
- {
- SkipSpaces(&buffer);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat);
- if (!obj.texRepeat.x || !obj.texRepeat.y)
- obj.texRepeat = aiVector2D (1.f,1.f);
- }
- else if (TokenMatch(buffer,"texoff",6))
- {
- SkipSpaces(&buffer);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset);
- }
- else if (TokenMatch(buffer,"rot",3))
- {
- SkipSpaces(&buffer);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation);
- }
- else if (TokenMatch(buffer,"loc",3))
- {
- SkipSpaces(&buffer);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation);
- }
- else if (TokenMatch(buffer,"subdiv",6))
- {
- SkipSpaces(&buffer);
- obj.subDiv = strtoul10(buffer,&buffer);
- }
- else if (TokenMatch(buffer,"crease",6))
- {
- SkipSpaces(&buffer);
- obj.crease = fast_atof(buffer);
- }
- else if (TokenMatch(buffer,"numvert",7))
- {
- SkipSpaces(&buffer);
-
- unsigned int t = strtoul10(buffer,&buffer);
- obj.vertices.reserve(t);
- for (unsigned int i = 0; i < t;++i)
- {
- if (!GetNextLine())
- {
- DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
- break;
- }
- else if (!IsNumeric(*buffer))
- {
- DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
- --buffer; // make sure the line is processed a second time
- break;
- }
- obj.vertices.push_back(aiVector3D());
- aiVector3D& v = obj.vertices.back();
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
- }
- }
- else if (TokenMatch(buffer,"numsurf",7))
- {
- SkipSpaces(&buffer);
-
- bool Q3DWorkAround = false;
-
- const unsigned int t = strtoul10(buffer,&buffer);
- obj.surfaces.reserve(t);
- for (unsigned int i = 0; i < t;++i)
- {
- GetNextLine();
- if (!TokenMatch(buffer,"SURF",4))
- {
- // FIX: this can occur for some files - Quick 3D for
- // example writes no surf chunks
- if (!Q3DWorkAround)
- {
- DefaultLogger::get()->warn("AC3D: SURF token was expected");
- DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
- }
- --buffer; // make sure the line is processed a second time
- // break; --- see fix notes above
-
- Q3DWorkAround = true;
- }
- SkipSpaces(&buffer);
- obj.surfaces.push_back(Surface());
- Surface& surf = obj.surfaces.back();
- surf.flags = strtoul_cppstyle(buffer);
-
- while (1)
- {
- if(!GetNextLine())
- {
- DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete");
- break;
- }
- if (TokenMatch(buffer,"mat",3))
- {
- SkipSpaces(&buffer);
- surf.mat = strtoul10(buffer);
- }
- else if (TokenMatch(buffer,"refs",4))
- {
- // --- see fix notes above
- if (Q3DWorkAround)
- {
- if (!surf.entries.empty())
- {
- buffer -= 6;
- break;
- }
- }
-
- SkipSpaces(&buffer);
- const unsigned int m = strtoul10(buffer);
- surf.entries.reserve(m);
-
- obj.numRefs += m;
-
- for (unsigned int k = 0; k < m; ++k)
- {
- if(!GetNextLine())
- {
- DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
- break;
- }
- surf.entries.push_back(Surface::SurfaceEntry());
- Surface::SurfaceEntry& entry = surf.entries.back();
-
- entry.first = strtoul10(buffer,&buffer);
- SkipSpaces(&buffer);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second);
- }
- }
- else
- {
-
- --buffer; // make sure the line is processed a second time
- break;
- }
- }
- }
- }
- }
- DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
+ if (!TokenMatch(buffer,"OBJECT",6))
+ return;
+
+ SkipSpaces(&buffer);
+
+ ++mNumMeshes;
+
+ objects.push_back(Object());
+ Object& obj = objects.back();
+
+ aiLight* light = NULL;
+ if (!ASSIMP_strincmp(buffer,"light",5))
+ {
+ // This is a light source. Add it to the list
+ mLights->push_back(light = new aiLight());
+
+ // Return a point light with no attenuation
+ light->mType = aiLightSource_POINT;
+ light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
+ light->mAttenuationConstant = 1.f;
+
+ // Generate a default name for both the light source and the node
+ // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
+ light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
+ obj.name = std::string( light->mName.data );
+
+ DefaultLogger::get()->debug("AC3D: Light source encountered");
+ obj.type = Object::Light;
+ }
+ else if (!ASSIMP_strincmp(buffer,"group",5))
+ {
+ obj.type = Object::Group;
+ }
+ else if (!ASSIMP_strincmp(buffer,"world",5))
+ {
+ obj.type = Object::World;
+ }
+ else obj.type = Object::Poly;
+ while (GetNextLine())
+ {
+ if (TokenMatch(buffer,"kids",4))
+ {
+ SkipSpaces(&buffer);
+ unsigned int num = strtoul10(buffer,&buffer);
+ GetNextLine();
+ if (num)
+ {
+ // load the children of this object recursively
+ obj.children.reserve(num);
+ for (unsigned int i = 0; i < num; ++i)
+ LoadObjectSection(obj.children);
+ }
+ return;
+ }
+ else if (TokenMatch(buffer,"name",4))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_GET_STRING(obj.name);
+
+ // If this is a light source, we'll also need to store
+ // the name of the node in it.
+ if (light)
+ {
+ light->mName.Set(obj.name);
+ }
+ }
+ else if (TokenMatch(buffer,"texture",7))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_GET_STRING(obj.texture);
+ }
+ else if (TokenMatch(buffer,"texrep",6))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat);
+ if (!obj.texRepeat.x || !obj.texRepeat.y)
+ obj.texRepeat = aiVector2D (1.f,1.f);
+ }
+ else if (TokenMatch(buffer,"texoff",6))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset);
+ }
+ else if (TokenMatch(buffer,"rot",3))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation);
+ }
+ else if (TokenMatch(buffer,"loc",3))
+ {
+ SkipSpaces(&buffer);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation);
+ }
+ else if (TokenMatch(buffer,"subdiv",6))
+ {
+ SkipSpaces(&buffer);
+ obj.subDiv = strtoul10(buffer,&buffer);
+ }
+ else if (TokenMatch(buffer,"crease",6))
+ {
+ SkipSpaces(&buffer);
+ obj.crease = fast_atof(buffer);
+ }
+ else if (TokenMatch(buffer,"numvert",7))
+ {
+ SkipSpaces(&buffer);
+
+ unsigned int t = strtoul10(buffer,&buffer);
+ if (t >= AI_MAX_ALLOC(aiVector3D)) {
+ throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
+ }
+ obj.vertices.reserve(t);
+ for (unsigned int i = 0; i < t;++i)
+ {
+ if (!GetNextLine())
+ {
+ DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
+ break;
+ }
+ else if (!IsNumeric(*buffer))
+ {
+ DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
+ --buffer; // make sure the line is processed a second time
+ break;
+ }
+ obj.vertices.push_back(aiVector3D());
+ aiVector3D& v = obj.vertices.back();
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
+ }
+ }
+ else if (TokenMatch(buffer,"numsurf",7))
+ {
+ SkipSpaces(&buffer);
+
+ bool Q3DWorkAround = false;
+
+ const unsigned int t = strtoul10(buffer,&buffer);
+ obj.surfaces.reserve(t);
+ for (unsigned int i = 0; i < t;++i)
+ {
+ GetNextLine();
+ if (!TokenMatch(buffer,"SURF",4))
+ {
+ // FIX: this can occur for some files - Quick 3D for
+ // example writes no surf chunks
+ if (!Q3DWorkAround)
+ {
+ DefaultLogger::get()->warn("AC3D: SURF token was expected");
+ DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
+ }
+ --buffer; // make sure the line is processed a second time
+ // break; --- see fix notes above
+
+ Q3DWorkAround = true;
+ }
+ SkipSpaces(&buffer);
+ obj.surfaces.push_back(Surface());
+ Surface& surf = obj.surfaces.back();
+ surf.flags = strtoul_cppstyle(buffer);
+
+ while (1)
+ {
+ if(!GetNextLine())
+ {
+ throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
+ }
+ if (TokenMatch(buffer,"mat",3))
+ {
+ SkipSpaces(&buffer);
+ surf.mat = strtoul10(buffer);
+ }
+ else if (TokenMatch(buffer,"refs",4))
+ {
+ // --- see fix notes above
+ if (Q3DWorkAround)
+ {
+ if (!surf.entries.empty())
+ {
+ buffer -= 6;
+ break;
+ }
+ }
+
+ SkipSpaces(&buffer);
+ const unsigned int m = strtoul10(buffer);
+ surf.entries.reserve(m);
+
+ obj.numRefs += m;
+
+ for (unsigned int k = 0; k < m; ++k)
+ {
+ if(!GetNextLine())
+ {
+ DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
+ break;
+ }
+ surf.entries.push_back(Surface::SurfaceEntry());
+ Surface::SurfaceEntry& entry = surf.entries.back();
+
+ entry.first = strtoul10(buffer,&buffer);
+ SkipSpaces(&buffer);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second);
+ }
+ }
+ else
+ {
+
+ --buffer; // make sure the line is processed a second time
+ break;
+ }
+ }
+ }
+ }
+ }
+ DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
}
// ------------------------------------------------------------------------------------------------
// Convert a material from AC3DImporter::Material to aiMaterial
void AC3DImporter::ConvertMaterial(const Object& object,
- const Material& matSrc,
- aiMaterial& matDest)
+ const Material& matSrc,
+ aiMaterial& matDest)
{
- aiString s;
-
- if (matSrc.name.length())
- {
- s.Set(matSrc.name);
- matDest.AddProperty(&s,AI_MATKEY_NAME);
- }
- if (object.texture.length())
- {
- s.Set(object.texture);
- matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
- // UV transformation
- if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y ||
- object.texOffset.x || object.texOffset.y)
- {
- aiUVTransform transform;
- transform.mScaling = object.texRepeat;
- transform.mTranslation = object.texOffset;
- matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
- }
- }
-
- matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE);
- matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT);
- matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
- matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
-
- int n;
- if (matSrc.shin)
- {
- n = aiShadingMode_Phong;
- matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
- }
- else n = aiShadingMode_Gouraud;
- matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
-
- float f = 1.f - matSrc.trans;
- matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
+ aiString s;
+
+ if (matSrc.name.length())
+ {
+ s.Set(matSrc.name);
+ matDest.AddProperty(&s,AI_MATKEY_NAME);
+ }
+ if (object.texture.length())
+ {
+ s.Set(object.texture);
+ matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+ // UV transformation
+ if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y ||
+ object.texOffset.x || object.texOffset.y)
+ {
+ aiUVTransform transform;
+ transform.mScaling = object.texRepeat;
+ transform.mTranslation = object.texOffset;
+ matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
+ }
+ }
+
+ matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE);
+ matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT);
+ matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
+ matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
+
+ int n;
+ if (matSrc.shin)
+ {
+ n = aiShadingMode_Phong;
+ matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
+ }
+ else n = aiShadingMode_Gouraud;
+ matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
+
+ float f = 1.f - matSrc.trans;
+ matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
}
// ------------------------------------------------------------------------------------------------
// Converts the loaded data to the internal verbose representation
aiNode* AC3DImporter::ConvertObjectSection(Object& object,
- std::vector<aiMesh*>& meshes,
- std::vector<aiMaterial*>& outMaterials,
- const std::vector<Material>& materials,
- aiNode* parent)
+ std::vector<aiMesh*>& meshes,
+ std::vector<aiMaterial*>& outMaterials,
+ const std::vector<Material>& materials,
+ aiNode* parent)
{
- aiNode* node = new aiNode();
- node->mParent = parent;
- if (object.vertices.size())
- {
- if (!object.surfaces.size() || !object.numRefs)
- {
- /* " An object with 7 vertices (no surfaces, no materials defined).
- This is a good way of getting point data into AC3D.
- The Vertex->create convex-surface/object can be used on these
- vertices to 'wrap' a 3d shape around them "
- (http://www.opencity.info/html/ac3dfileformat.html)
-
- therefore: if no surfaces are defined return point data only
- */
-
- DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
- "a point list is returned");
-
- meshes.push_back(new aiMesh());
- aiMesh* mesh = meshes.back();
-
- mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size();
- aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
- aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-
- for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts)
- {
- *verts = object.vertices[i];
- faces->mNumIndices = 1;
- faces->mIndices = new unsigned int[1];
- faces->mIndices[0] = i;
- }
-
- // use the primary material in this case. this should be the
- // default material if all objects of the file contain points
- // and no faces.
- mesh->mMaterialIndex = 0;
- outMaterials.push_back(new aiMaterial());
- ConvertMaterial(object, materials[0], *outMaterials.back());
- }
- else
- {
- // need to generate one or more meshes for this object.
- // find out how many different materials we have
- typedef std::pair< unsigned int, unsigned int > IntPair;
- typedef std::vector< IntPair > MatTable;
- MatTable needMat(materials.size(),IntPair(0,0));
-
- std::vector<Surface>::iterator it,end = object.surfaces.end();
- std::vector<Surface::SurfaceEntry>::iterator it2,end2;
-
- for (it = object.surfaces.begin(); it != end; ++it)
- {
- unsigned int idx = (*it).mat;
- if (idx >= needMat.size())
- {
- DefaultLogger::get()->error("AC3D: material index is out of range");
- idx = 0;
- }
- if ((*it).entries.empty())
- {
- DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
- }
-
- // validate all vertex indices to make sure we won't crash here
- for (it2 = (*it).entries.begin(),
- end2 = (*it).entries.end(); it2 != end2; ++it2)
- {
- if ((*it2).first >= object.vertices.size())
- {
- DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
- (*it2).first = 0;
- }
- }
-
- if (!needMat[idx].first)++node->mNumMeshes;
-
- switch ((*it).flags & 0xf)
- {
- // closed line
- case 0x1:
-
- needMat[idx].first += (unsigned int)(*it).entries.size();
- needMat[idx].second += (unsigned int)(*it).entries.size()<<1u;
- break;
-
- // unclosed line
- case 0x2:
-
- needMat[idx].first += (unsigned int)(*it).entries.size()-1;
- needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u;
- break;
-
- // 0 == polygon, else unknown
- default:
-
- if ((*it).flags & 0xf)
- {
- DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
- (*it).flags &= ~(0xf);
- }
-
- // the number of faces increments by one, the number
- // of vertices by surface.numref.
- needMat[idx].first++;
- needMat[idx].second += (unsigned int)(*it).entries.size();
- };
- }
- unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes];
- unsigned int mat = 0;
- const size_t oldm = meshes.size();
- for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
- cit != cend; ++cit, ++mat)
- {
- if (!(*cit).first)continue;
-
- // allocate a new aiMesh object
- *pip++ = (unsigned int)meshes.size();
- aiMesh* mesh = new aiMesh();
- meshes.push_back(mesh);
-
- mesh->mMaterialIndex = (unsigned int)outMaterials.size();
- outMaterials.push_back(new aiMaterial());
- ConvertMaterial(object, materials[mat], *outMaterials.back());
-
- // allocate storage for vertices and normals
- mesh->mNumFaces = (*cit).first;
- aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
-
- mesh->mNumVertices = (*cit).second;
- aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- unsigned int cur = 0;
-
- // allocate UV coordinates, but only if the texture name for the
- // surface is not empty
- aiVector3D* uv = NULL;
- if(object.texture.length())
- {
- uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
- mesh->mNumUVComponents[0] = 2;
- }
-
- for (it = object.surfaces.begin(); it != end; ++it)
- {
- if (mat == (*it).mat)
- {
- const Surface& src = *it;
-
- // closed polygon
- unsigned int type = (*it).flags & 0xf;
- if (!type)
- {
- aiFace& face = *faces++;
- if((face.mNumIndices = (unsigned int)src.entries.size()))
- {
- face.mIndices = new unsigned int[face.mNumIndices];
- for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices)
- {
- const Surface::SurfaceEntry& entry = src.entries[i];
- face.mIndices[i] = cur++;
-
- // copy vertex positions
- *vertices = object.vertices[entry.first] + object.translation;
-
-
- // copy texture coordinates
- if (uv)
- {
- uv->x = entry.second.x;
- uv->y = entry.second.y;
- ++uv;
- }
- }
- }
- }
- else
- {
-
- it2 = (*it).entries.begin();
-
- // either a closed or an unclosed line
- unsigned int tmp = (unsigned int)(*it).entries.size();
- if (0x2 == type)--tmp;
- for (unsigned int m = 0; m < tmp;++m)
- {
- aiFace& face = *faces++;
-
- face.mNumIndices = 2;
- face.mIndices = new unsigned int[2];
- face.mIndices[0] = cur++;
- face.mIndices[1] = cur++;
-
- // copy vertex positions
- *vertices++ = object.vertices[(*it2).first];
-
- // copy texture coordinates
- if (uv)
- {
- uv->x = (*it2).second.x;
- uv->y = (*it2).second.y;
- ++uv;
- }
-
-
- if (0x1 == type && tmp-1 == m)
- {
- // if this is a closed line repeat its beginning now
- it2 = (*it).entries.begin();
- }
- else ++it2;
-
- // second point
- *vertices++ = object.vertices[(*it2).first];
-
- if (uv)
- {
- uv->x = (*it2).second.x;
- uv->y = (*it2).second.y;
- ++uv;
- }
- }
- }
- }
- }
- }
-
- // Now apply catmull clark subdivision if necessary. We split meshes into
- // materials which is not done by AC3D during smoothing, so we need to
- // collect all meshes using the same material group.
- if (object.subDiv) {
- if (configEvalSubdivision) {
- boost::scoped_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
- DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
-
- std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
- div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
- std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm);
-
- // previous meshes are deleted vy Subdivide().
- }
- else {
- DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
- +object.name);
- }
- }
- }
- }
-
- if (object.name.length())
- node->mName.Set(object.name);
- else
- {
- // generate a name depending on the type of the node
- switch (object.type)
- {
- case Object::Group:
- node->mName.length = ::sprintf(node->mName.data,"ACGroup_%i",groups++);
- break;
- case Object::Poly:
- node->mName.length = ::sprintf(node->mName.data,"ACPoly_%i",polys++);
- break;
- case Object::Light:
- node->mName.length = ::sprintf(node->mName.data,"ACLight_%i",lights++);
- break;
-
- // there shouldn't be more than one world, but we don't care
- case Object::World:
- node->mName.length = ::sprintf(node->mName.data,"ACWorld_%i",worlds++);
- break;
- }
- }
-
-
- // setup the local transformation matrix of the object
- // compute the transformation offset to the parent node
- node->mTransformation = aiMatrix4x4 ( object.rotation );
-
- if (object.type == Object::Group || !object.numRefs)
- {
- node->mTransformation.a4 = object.translation.x;
- node->mTransformation.b4 = object.translation.y;
- node->mTransformation.c4 = object.translation.z;
- }
-
- // add children to the object
- if (object.children.size())
- {
- node->mNumChildren = (unsigned int)object.children.size();
- node->mChildren = new aiNode*[node->mNumChildren];
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- {
- node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node);
- }
- }
-
- return node;
+ aiNode* node = new aiNode();
+ node->mParent = parent;
+ if (object.vertices.size())
+ {
+ if (!object.surfaces.size() || !object.numRefs)
+ {
+ /* " An object with 7 vertices (no surfaces, no materials defined).
+ This is a good way of getting point data into AC3D.
+ The Vertex->create convex-surface/object can be used on these
+ vertices to 'wrap' a 3d shape around them "
+ (http://www.opencity.info/html/ac3dfileformat.html)
+
+ therefore: if no surfaces are defined return point data only
+ */
+
+ DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
+ "a point list is returned");
+
+ meshes.push_back(new aiMesh());
+ aiMesh* mesh = meshes.back();
+
+ mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size();
+ aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+ aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+
+ for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts)
+ {
+ *verts = object.vertices[i];
+ faces->mNumIndices = 1;
+ faces->mIndices = new unsigned int[1];
+ faces->mIndices[0] = i;
+ }
+
+ // use the primary material in this case. this should be the
+ // default material if all objects of the file contain points
+ // and no faces.
+ mesh->mMaterialIndex = 0;
+ outMaterials.push_back(new aiMaterial());
+ ConvertMaterial(object, materials[0], *outMaterials.back());
+ }
+ else
+ {
+ // need to generate one or more meshes for this object.
+ // find out how many different materials we have
+ typedef std::pair< unsigned int, unsigned int > IntPair;
+ typedef std::vector< IntPair > MatTable;
+ MatTable needMat(materials.size(),IntPair(0,0));
+
+ std::vector<Surface>::iterator it,end = object.surfaces.end();
+ std::vector<Surface::SurfaceEntry>::iterator it2,end2;
+
+ for (it = object.surfaces.begin(); it != end; ++it)
+ {
+ unsigned int idx = (*it).mat;
+ if (idx >= needMat.size())
+ {
+ DefaultLogger::get()->error("AC3D: material index is out of range");
+ idx = 0;
+ }
+ if ((*it).entries.empty())
+ {
+ DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
+ }
+
+ // validate all vertex indices to make sure we won't crash here
+ for (it2 = (*it).entries.begin(),
+ end2 = (*it).entries.end(); it2 != end2; ++it2)
+ {
+ if ((*it2).first >= object.vertices.size())
+ {
+ DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
+ (*it2).first = 0;
+ }
+ }
+
+ if (!needMat[idx].first)++node->mNumMeshes;
+
+ switch ((*it).flags & 0xf)
+ {
+ // closed line
+ case 0x1:
+
+ needMat[idx].first += (unsigned int)(*it).entries.size();
+ needMat[idx].second += (unsigned int)(*it).entries.size()<<1u;
+ break;
+
+ // unclosed line
+ case 0x2:
+
+ needMat[idx].first += (unsigned int)(*it).entries.size()-1;
+ needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u;
+ break;
+
+ // 0 == polygon, else unknown
+ default:
+
+ if ((*it).flags & 0xf)
+ {
+ DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
+ (*it).flags &= ~(0xf);
+ }
+
+ // the number of faces increments by one, the number
+ // of vertices by surface.numref.
+ needMat[idx].first++;
+ needMat[idx].second += (unsigned int)(*it).entries.size();
+ };
+ }
+ unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes];
+ unsigned int mat = 0;
+ const size_t oldm = meshes.size();
+ for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
+ cit != cend; ++cit, ++mat)
+ {
+ if (!(*cit).first)continue;
+
+ // allocate a new aiMesh object
+ *pip++ = (unsigned int)meshes.size();
+ aiMesh* mesh = new aiMesh();
+ meshes.push_back(mesh);
+
+ mesh->mMaterialIndex = (unsigned int)outMaterials.size();
+ outMaterials.push_back(new aiMaterial());
+ ConvertMaterial(object, materials[mat], *outMaterials.back());
+
+ // allocate storage for vertices and normals
+ mesh->mNumFaces = (*cit).first;
+ if (mesh->mNumFaces == 0) {
+ throw DeadlyImportError("AC3D: No faces");
+ } else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) {
+ throw DeadlyImportError("AC3D: Too many faces, would run out of memory");
+ }
+ aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+
+ mesh->mNumVertices = (*cit).second;
+ if (mesh->mNumVertices == 0) {
+ throw DeadlyImportError("AC3D: No vertices");
+ } else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
+ throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
+ }
+ aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ unsigned int cur = 0;
+
+ // allocate UV coordinates, but only if the texture name for the
+ // surface is not empty
+ aiVector3D* uv = NULL;
+ if(object.texture.length())
+ {
+ uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+ mesh->mNumUVComponents[0] = 2;
+ }
+
+ for (it = object.surfaces.begin(); it != end; ++it)
+ {
+ if (mat == (*it).mat)
+ {
+ const Surface& src = *it;
+
+ // closed polygon
+ unsigned int type = (*it).flags & 0xf;
+ if (!type)
+ {
+ aiFace& face = *faces++;
+ if((face.mNumIndices = (unsigned int)src.entries.size()))
+ {
+ face.mIndices = new unsigned int[face.mNumIndices];
+ for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices)
+ {
+ const Surface::SurfaceEntry& entry = src.entries[i];
+ face.mIndices[i] = cur++;
+
+ // copy vertex positions
+ if (static_cast<unsigned>(vertices - mesh->mVertices) >= mesh->mNumVertices) {
+ throw DeadlyImportError("AC3D: Invalid number of vertices");
+ }
+ *vertices = object.vertices[entry.first] + object.translation;
+
+
+ // copy texture coordinates
+ if (uv)
+ {
+ uv->x = entry.second.x;
+ uv->y = entry.second.y;
+ ++uv;
+ }
+ }
+ }
+ }
+ else
+ {
+
+ it2 = (*it).entries.begin();
+
+ // either a closed or an unclosed line
+ unsigned int tmp = (unsigned int)(*it).entries.size();
+ if (0x2 == type)--tmp;
+ for (unsigned int m = 0; m < tmp;++m)
+ {
+ aiFace& face = *faces++;
+
+ face.mNumIndices = 2;
+ face.mIndices = new unsigned int[2];
+ face.mIndices[0] = cur++;
+ face.mIndices[1] = cur++;
+
+ // copy vertex positions
+ if (it2 == (*it).entries.end() ) {
+ throw DeadlyImportError("AC3D: Bad line");
+ }
+ ai_assert((*it2).first < object.vertices.size());
+ *vertices++ = object.vertices[(*it2).first];
+
+ // copy texture coordinates
+ if (uv)
+ {
+ uv->x = (*it2).second.x;
+ uv->y = (*it2).second.y;
+ ++uv;
+ }
+
+
+ if (0x1 == type && tmp-1 == m)
+ {
+ // if this is a closed line repeat its beginning now
+ it2 = (*it).entries.begin();
+ }
+ else ++it2;
+
+ // second point
+ *vertices++ = object.vertices[(*it2).first];
+
+ if (uv)
+ {
+ uv->x = (*it2).second.x;
+ uv->y = (*it2).second.y;
+ ++uv;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Now apply catmull clark subdivision if necessary. We split meshes into
+ // materials which is not done by AC3D during smoothing, so we need to
+ // collect all meshes using the same material group.
+ if (object.subDiv) {
+ if (configEvalSubdivision) {
+ std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
+ DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
+
+ std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
+ div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
+ std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm);
+
+ // previous meshes are deleted vy Subdivide().
+ }
+ else {
+ DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
+ +object.name);
+ }
+ }
+ }
+ }
+
+ if (object.name.length())
+ node->mName.Set(object.name);
+ else
+ {
+ // generate a name depending on the type of the node
+ switch (object.type)
+ {
+ case Object::Group:
+ node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i",groups++);
+ break;
+ case Object::Poly:
+ node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i",polys++);
+ break;
+ case Object::Light:
+ node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i",lights++);
+ break;
+
+ // there shouldn't be more than one world, but we don't care
+ case Object::World:
+ node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i",worlds++);
+ break;
+ }
+ }
+
+
+ // setup the local transformation matrix of the object
+ // compute the transformation offset to the parent node
+ node->mTransformation = aiMatrix4x4 ( object.rotation );
+
+ if (object.type == Object::Group || !object.numRefs)
+ {
+ node->mTransformation.a4 = object.translation.x;
+ node->mTransformation.b4 = object.translation.y;
+ node->mTransformation.c4 = object.translation.z;
+ }
+
+ // add children to the object
+ if (object.children.size())
+ {
+ node->mNumChildren = (unsigned int)object.children.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ {
+ node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node);
+ }
+ }
+
+ return node;
}
// ------------------------------------------------------------------------------------------------
void AC3DImporter::SetupProperties(const Importer* pImp)
{
- configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false;
- configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false;
+ configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false;
+ configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void AC3DImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void AC3DImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open AC3D file " + pFile + ".");
-
- // allocate storage and copy the contents of the file to a memory buffer
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
-
- buffer = &mBuffer2[0];
- mNumMeshes = 0;
-
- lights = polys = worlds = groups = 0;
-
- if (::strncmp(buffer,"AC3D",4)) {
- throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found");
- }
-
- // print the file format version to the console
- unsigned int version = HexDigitToDecimal( buffer[4] );
- char msg[3];
- ASSIMP_itoa10(msg,3,version);
- DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
-
- std::vector<Material> materials;
- materials.reserve(5);
-
- std::vector<Object> rootObjects;
- rootObjects.reserve(5);
-
- std::vector<aiLight*> lights;
- mLights = & lights;
-
- while (GetNextLine())
- {
- if (TokenMatch(buffer,"MATERIAL",8))
- {
- materials.push_back(Material());
- Material& mat = materials.back();
-
- // manually parse the material ... sscanf would use the buldin atof ...
- // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f
-
- AI_AC_SKIP_TO_NEXT_TOKEN();
- if ('\"' == *buffer)
- {
- AI_AC_GET_STRING(mat.name);
- AI_AC_SKIP_TO_NEXT_TOKEN();
- }
-
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
- AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
- }
- LoadObjectSection(rootObjects);
- }
-
- if (rootObjects.empty() || !mNumMeshes)
- {
- throw DeadlyImportError("AC3D: No meshes have been loaded");
- }
- if (materials.empty())
- {
- DefaultLogger::get()->warn("AC3D: No material has been found");
- materials.push_back(Material());
- }
-
- mNumMeshes += (mNumMeshes>>2u) + 1;
- std::vector<aiMesh*> meshes;
- meshes.reserve(mNumMeshes);
-
- std::vector<aiMaterial*> omaterials;
- materials.reserve(mNumMeshes);
-
- // generate a dummy root if there are multiple objects on the top layer
- Object* root;
- if (1 == rootObjects.size())
- root = &rootObjects[0];
- else
- {
- root = new Object();
- }
-
- // now convert the imported stuff to our output data structure
- pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
- if (1 != rootObjects.size())delete root;
-
- if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
- pScene->mRootNode->mName.Set("<AC3DWorld>");
-
- // copy meshes
- if (meshes.empty())
- {
- throw DeadlyImportError("An unknown error occured during converting");
- }
- pScene->mNumMeshes = (unsigned int)meshes.size();
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
-
- // copy materials
- pScene->mNumMaterials = (unsigned int)omaterials.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
-
- // copy lights
- pScene->mNumLights = (unsigned int)lights.size();
- if (lights.size())
- {
- pScene->mLights = new aiLight*[lights.size()];
- ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open AC3D file " + pFile + ".");
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+
+ buffer = &mBuffer2[0];
+ mNumMeshes = 0;
+
+ lights = polys = worlds = groups = 0;
+
+ if (::strncmp(buffer,"AC3D",4)) {
+ throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found");
+ }
+
+ // print the file format version to the console
+ unsigned int version = HexDigitToDecimal( buffer[4] );
+ char msg[3];
+ ASSIMP_itoa10(msg,3,version);
+ DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
+
+ std::vector<Material> materials;
+ materials.reserve(5);
+
+ std::vector<Object> rootObjects;
+ rootObjects.reserve(5);
+
+ std::vector<aiLight*> lights;
+ mLights = & lights;
+
+ while (GetNextLine())
+ {
+ if (TokenMatch(buffer,"MATERIAL",8))
+ {
+ materials.push_back(Material());
+ Material& mat = materials.back();
+
+ // manually parse the material ... sscanf would use the buldin atof ...
+ // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f
+
+ AI_AC_SKIP_TO_NEXT_TOKEN();
+ if ('\"' == *buffer)
+ {
+ AI_AC_GET_STRING(mat.name);
+ AI_AC_SKIP_TO_NEXT_TOKEN();
+ }
+
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
+ AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
+ }
+ LoadObjectSection(rootObjects);
+ }
+
+ if (rootObjects.empty() || !mNumMeshes)
+ {
+ throw DeadlyImportError("AC3D: No meshes have been loaded");
+ }
+ if (materials.empty())
+ {
+ DefaultLogger::get()->warn("AC3D: No material has been found");
+ materials.push_back(Material());
+ }
+
+ mNumMeshes += (mNumMeshes>>2u) + 1;
+ std::vector<aiMesh*> meshes;
+ meshes.reserve(mNumMeshes);
+
+ std::vector<aiMaterial*> omaterials;
+ materials.reserve(mNumMeshes);
+
+ // generate a dummy root if there are multiple objects on the top layer
+ Object* root;
+ if (1 == rootObjects.size())
+ root = &rootObjects[0];
+ else
+ {
+ root = new Object();
+ }
+
+ // now convert the imported stuff to our output data structure
+ pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
+ if (1 != rootObjects.size())delete root;
+
+ if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
+ pScene->mRootNode->mName.Set("<AC3DWorld>");
+
+ // copy meshes
+ if (meshes.empty())
+ {
+ throw DeadlyImportError("An unknown error occurred during converting");
+ }
+ pScene->mNumMeshes = (unsigned int)meshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
+
+ // copy materials
+ pScene->mNumMaterials = (unsigned int)omaterials.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
+
+ // copy lights
+ pScene->mNumLights = (unsigned int)lights.size();
+ if (lights.size())
+ {
+ pScene->mLights = new aiLight*[lights.size()];
+ ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
+ }
}
#endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER
diff --git a/src/3rdparty/assimp/code/ACLoader.h b/src/3rdparty/assimp/code/ACLoader.h
index 3f5089258..52563adad 100644
--- a/src/3rdparty/assimp/code/ACLoader.h
+++ b/src/3rdparty/assimp/code/ACLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,9 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
-namespace Assimp {
+struct aiNode;
+struct aiMesh;
+struct aiMaterial;
+struct aiLight;
+
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** AC3D (*.ac) importer class
@@ -57,209 +63,210 @@ namespace Assimp {
class AC3DImporter : public BaseImporter
{
public:
- AC3DImporter();
- ~AC3DImporter();
-
-
-
- // Represents an AC3D material
- struct Material
- {
- Material()
- : rgb (0.6f,0.6f,0.6f)
- , spec (1.f,1.f,1.f)
- , shin (0.f)
- , trans (0.f)
- {}
+ AC3DImporter();
+ ~AC3DImporter();
+
+
+
+ // Represents an AC3D material
+ struct Material
+ {
+ Material()
+ : rgb (0.6f,0.6f,0.6f)
+ , spec (1.f,1.f,1.f)
+ , shin (0.f)
+ , trans (0.f)
+ {}
- // base color of the material
- aiColor3D rgb;
+ // base color of the material
+ aiColor3D rgb;
- // ambient color of the material
- aiColor3D amb;
+ // ambient color of the material
+ aiColor3D amb;
- // emissive color of the material
- aiColor3D emis;
+ // emissive color of the material
+ aiColor3D emis;
- // specular color of the material
- aiColor3D spec;
+ // specular color of the material
+ aiColor3D spec;
- // shininess exponent
- float shin;
+ // shininess exponent
+ float shin;
- // transparency. 0 == opaque
- float trans;
+ // transparency. 0 == opaque
+ float trans;
- // name of the material. optional.
- std::string name;
- };
+ // name of the material. optional.
+ std::string name;
+ };
- // Represents an AC3D surface
- struct Surface
- {
- Surface()
- : mat (0)
- , flags (0)
- {}
+ // Represents an AC3D surface
+ struct Surface
+ {
+ Surface()
+ : mat (0)
+ , flags (0)
+ {}
- unsigned int mat,flags;
+ unsigned int mat,flags;
- typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
- std::vector< SurfaceEntry > entries;
- };
+ typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
+ std::vector< SurfaceEntry > entries;
+ };
- // Represents an AC3D object
- struct Object
- {
- Object()
- : type (World)
- , name( "" )
- , children()
- , texture( "" )
- , texRepeat( 1.f, 1.f )
- , texOffset( 0.0f, 0.0f )
- , rotation()
- , translation()
- , vertices()
- , surfaces()
- , numRefs (0)
- , subDiv (0)
- {}
+ // Represents an AC3D object
+ struct Object
+ {
+ Object()
+ : type (World)
+ , name( "" )
+ , children()
+ , texture( "" )
+ , texRepeat( 1.f, 1.f )
+ , texOffset( 0.0f, 0.0f )
+ , rotation()
+ , translation()
+ , vertices()
+ , surfaces()
+ , numRefs (0)
+ , subDiv (0)
+ , crease()
+ {}
- // Type description
- enum Type
- {
- World = 0x0,
- Poly = 0x1,
- Group = 0x2,
- Light = 0x4
- } type;
+ // Type description
+ enum Type
+ {
+ World = 0x0,
+ Poly = 0x1,
+ Group = 0x2,
+ Light = 0x4
+ } type;
- // name of the object
- std::string name;
+ // name of the object
+ std::string name;
- // object children
- std::vector<Object> children;
+ // object children
+ std::vector<Object> children;
- // texture to be assigned to all surfaces of the object
- std::string texture;
+ // texture to be assigned to all surfaces of the object
+ std::string texture;
- // texture repat factors (scaling for all coordinates)
- aiVector2D texRepeat, texOffset;
+ // texture repat factors (scaling for all coordinates)
+ aiVector2D texRepeat, texOffset;
- // rotation matrix
- aiMatrix3x3 rotation;
+ // rotation matrix
+ aiMatrix3x3 rotation;
- // translation vector
- aiVector3D translation;
+ // translation vector
+ aiVector3D translation;
- // vertices
- std::vector<aiVector3D> vertices;
+ // vertices
+ std::vector<aiVector3D> vertices;
- // surfaces
- std::vector<Surface> surfaces;
+ // surfaces
+ std::vector<Surface> surfaces;
- // number of indices (= num verts in verbose format)
- unsigned int numRefs;
-
- // number of subdivisions to be performed on the
- // imported data
- unsigned int subDiv;
-
- // max angle limit for smoothing
- float crease;
- };
+ // number of indices (= num verts in verbose format)
+ unsigned int numRefs;
+
+ // number of subdivisions to be performed on the
+ // imported data
+ unsigned int subDiv;
+
+ // max angle limit for smoothing
+ float crease;
+ };
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details*/
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details*/
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.*/
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.*/
+ void SetupProperties(const Importer* pImp);
private:
- // -------------------------------------------------------------------
- /** Get the next line from the file.
- * @return false if the end of the file was reached*/
- bool GetNextLine();
-
- // -------------------------------------------------------------------
- /** Load the object section. This method is called recursively to
- * load subobjects, the method returns after a 'kids 0' was
- * encountered.
- * @objects List of output objects*/
- void LoadObjectSection(std::vector<Object>& objects);
-
- // -------------------------------------------------------------------
- /** Convert all objects into meshes and nodes.
- * @param object Current object to work on
- * @param meshes Pointer to the list of output meshes
- * @param outMaterials List of output materials
- * @param materials Material list
- * @param Scenegraph node for the object */
- aiNode* ConvertObjectSection(Object& object,
- std::vector<aiMesh*>& meshes,
- std::vector<aiMaterial*>& outMaterials,
- const std::vector<Material>& materials,
- aiNode* parent = NULL);
-
- // -------------------------------------------------------------------
- /** Convert a material
- * @param object Current object
- * @param matSrc Source material description
- * @param matDest Destination material to be filled */
- void ConvertMaterial(const Object& object,
- const Material& matSrc,
- aiMaterial& matDest);
+ // -------------------------------------------------------------------
+ /** Get the next line from the file.
+ * @return false if the end of the file was reached*/
+ bool GetNextLine();
+
+ // -------------------------------------------------------------------
+ /** Load the object section. This method is called recursively to
+ * load subobjects, the method returns after a 'kids 0' was
+ * encountered.
+ * @objects List of output objects*/
+ void LoadObjectSection(std::vector<Object>& objects);
+
+ // -------------------------------------------------------------------
+ /** Convert all objects into meshes and nodes.
+ * @param object Current object to work on
+ * @param meshes Pointer to the list of output meshes
+ * @param outMaterials List of output materials
+ * @param materials Material list
+ * @param Scenegraph node for the object */
+ aiNode* ConvertObjectSection(Object& object,
+ std::vector<aiMesh*>& meshes,
+ std::vector<aiMaterial*>& outMaterials,
+ const std::vector<Material>& materials,
+ aiNode* parent = NULL);
+
+ // -------------------------------------------------------------------
+ /** Convert a material
+ * @param object Current object
+ * @param matSrc Source material description
+ * @param matDest Destination material to be filled */
+ void ConvertMaterial(const Object& object,
+ const Material& matSrc,
+ aiMaterial& matDest);
private:
- // points to the next data line
- const char* buffer;
+ // points to the next data line
+ const char* buffer;
- // Configuration option: if enabled, up to two meshes
- // are generated per material: those faces who have
- // their bf cull flags set are separated.
- bool configSplitBFCull;
+ // Configuration option: if enabled, up to two meshes
+ // are generated per material: those faces who have
+ // their bf cull flags set are separated.
+ bool configSplitBFCull;
- // Configuration switch: subdivision surfaces are only
- // evaluated if the value is true.
- bool configEvalSubdivision;
+ // Configuration switch: subdivision surfaces are only
+ // evaluated if the value is true.
+ bool configEvalSubdivision;
- // counts how many objects we have in the tree.
- // basing on this information we can find a
- // good estimate how many meshes we'll have in the final scene.
- unsigned int mNumMeshes;
+ // counts how many objects we have in the tree.
+ // basing on this information we can find a
+ // good estimate how many meshes we'll have in the final scene.
+ unsigned int mNumMeshes;
- // current list of light sources
- std::vector<aiLight*>* mLights;
+ // current list of light sources
+ std::vector<aiLight*>* mLights;
- // name counters
- unsigned int lights, groups, polys, worlds;
+ // name counters
+ unsigned int lights, groups, polys, worlds;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ASELoader.cpp b/src/3rdparty/assimp/code/ASELoader.cpp
index 9be97c87d..39a33e9fd 100644
--- a/src/3rdparty/assimp/code/ASELoader.cpp
+++ b/src/3rdparty/assimp/code/ASELoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the ASE importer class
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
// internal headers
@@ -51,6 +50,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h"
#include "SkeletonMeshBuilder.h"
#include "TargetAnimation.h"
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
+#include <memory>
// utilities
#include "fast_atof.h"
@@ -59,1258 +64,1258 @@ using namespace Assimp;
using namespace Assimp::ASE;
static const aiImporterDesc desc = {
- "ASE Importer",
- "",
- "",
- "Similar to 3DS but text-encoded",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "ase ask"
+ "ASE Importer",
+ "",
+ "",
+ "Similar to 3DS but text-encoded",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ase ask"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ASEImporter::ASEImporter()
-: noSkeletonMesh()
+ : mParser(),
+ mBuffer(),
+ pcScene(),
+ configRecomputeNormals(),
+ noSkeletonMesh()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
ASEImporter::~ASEImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
{
- // check file extension
- const std::string extension = GetExtension(pFile);
-
- if( extension == "ase" || extension == "ask")
- return true;
-
- if ((!extension.length() || cs) && pIOHandler) {
- const char* tokens[] = {"*3dsmax_asciiexport"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "ase" || extension == "ask")
+ return true;
+
+ if ((!extension.length() || cs) && pIOHandler) {
+ const char* tokens[] = {"*3dsmax_asciiexport"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* ASEImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration options
void ASEImporter::SetupProperties(const Importer* pImp)
{
- configRecomputeNormals = (pImp->GetPropertyInteger(
- AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false);
+ configRecomputeNormals = (pImp->GetPropertyInteger(
+ AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false);
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void ASEImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void ASEImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open ASE file " + pFile + ".");
- }
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
-
- this->mBuffer = &mBuffer2[0];
- this->pcScene = pScene;
-
- // ------------------------------------------------------------------
- // Guess the file format by looking at the extension
- // ASC is considered to be the older format 110,
- // ASE is the actual version 200 (that is currently written by max)
- // ------------------------------------------------------------------
- unsigned int defaultFormat;
- std::string::size_type s = pFile.length()-1;
- switch (pFile.c_str()[s]) {
-
- case 'C':
- case 'c':
- defaultFormat = AI_ASE_OLD_FILE_FORMAT;
- break;
- default:
- defaultFormat = AI_ASE_NEW_FILE_FORMAT;
- };
-
- // Construct an ASE parser and parse the file
- ASE::Parser parser(mBuffer,defaultFormat);
- mParser = &parser;
- mParser->Parse();
-
- //------------------------------------------------------------------
- // Check whether we god at least one mesh. If we did - generate
- // materials and copy meshes.
- // ------------------------------------------------------------------
- if ( !mParser->m_vMeshes.empty()) {
-
- // If absolutely no material has been loaded from the file
- // we need to generate a default material
- GenerateDefaultMaterial();
-
- // process all meshes
- bool tookNormals = false;
- std::vector<aiMesh*> avOutMeshes;
- avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
- for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
- if ((*i).bSkip) {
- continue;
- }
- BuildUniqueRepresentation(*i);
-
- // Need to generate proper vertex normals if necessary
- if(GenerateNormals(*i)) {
- tookNormals = true;
- }
-
- // Convert all meshes to aiMesh objects
- ConvertMeshes(*i,avOutMeshes);
- }
- if (tookNormals) {
- DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
- "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
- "experience problems");
- }
-
- // Now build the output mesh list. Remove dummies
- pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
- aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- for (std::vector<aiMesh*>::const_iterator i = avOutMeshes.begin();i != avOutMeshes.end();++i) {
- if (!(*i)->mNumFaces) {
- continue;
- }
- *pp++ = *i;
- }
- pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
-
- // Build final material indices (remove submaterials and setup
- // the final list)
- BuildMaterialIndices();
- }
-
- // ------------------------------------------------------------------
- // Copy all scene graph nodes - lights, cameras, dummies and meshes
- // into one huge list.
- //------------------------------------------------------------------
- std::vector<BaseNode*> nodes;
- nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size()
- + mParser->m_vCameras.size() + mParser->m_vDummies.size());
-
- // Lights
- for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(),
- end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it));
- // Cameras
- for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(),
- end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it));
- // Meshes
- for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(),
- end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it));
- // Dummies
- for (std::vector<ASE::Dummy>::iterator it = mParser->m_vDummies.begin(),
- end = mParser->m_vDummies.end();it != end; ++it)nodes.push_back(&(*it));
-
- // build the final node graph
- BuildNodes(nodes);
-
- // build output animations
- BuildAnimations(nodes);
-
- // build output cameras
- BuildCameras();
-
- // build output lights
- BuildLights();
-
- // ------------------------------------------------------------------
- // If we have no meshes use the SkeletonMeshBuilder helper class
- // to build a mesh for the animation skeleton
- // FIXME: very strange results
- // ------------------------------------------------------------------
- if (!pScene->mNumMeshes) {
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- if (!noSkeletonMesh) {
- SkeletonMeshBuilder skeleton(pScene);
- }
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open ASE file " + pFile + ".");
+ }
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+
+ this->mBuffer = &mBuffer2[0];
+ this->pcScene = pScene;
+
+ // ------------------------------------------------------------------
+ // Guess the file format by looking at the extension
+ // ASC is considered to be the older format 110,
+ // ASE is the actual version 200 (that is currently written by max)
+ // ------------------------------------------------------------------
+ unsigned int defaultFormat;
+ std::string::size_type s = pFile.length()-1;
+ switch (pFile.c_str()[s]) {
+
+ case 'C':
+ case 'c':
+ defaultFormat = AI_ASE_OLD_FILE_FORMAT;
+ break;
+ default:
+ defaultFormat = AI_ASE_NEW_FILE_FORMAT;
+ };
+
+ // Construct an ASE parser and parse the file
+ ASE::Parser parser(mBuffer,defaultFormat);
+ mParser = &parser;
+ mParser->Parse();
+
+ //------------------------------------------------------------------
+ // Check whether we god at least one mesh. If we did - generate
+ // materials and copy meshes.
+ // ------------------------------------------------------------------
+ if ( !mParser->m_vMeshes.empty()) {
+
+ // If absolutely no material has been loaded from the file
+ // we need to generate a default material
+ GenerateDefaultMaterial();
+
+ // process all meshes
+ bool tookNormals = false;
+ std::vector<aiMesh*> avOutMeshes;
+ avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
+ for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
+ if ((*i).bSkip) {
+ continue;
+ }
+ BuildUniqueRepresentation(*i);
+
+ // Need to generate proper vertex normals if necessary
+ if(GenerateNormals(*i)) {
+ tookNormals = true;
+ }
+
+ // Convert all meshes to aiMesh objects
+ ConvertMeshes(*i,avOutMeshes);
+ }
+ if (tookNormals) {
+ DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
+ "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
+ "experience problems");
+ }
+
+ // Now build the output mesh list. Remove dummies
+ pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
+ aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for (std::vector<aiMesh*>::const_iterator i = avOutMeshes.begin();i != avOutMeshes.end();++i) {
+ if (!(*i)->mNumFaces) {
+ continue;
+ }
+ *pp++ = *i;
+ }
+ pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
+
+ // Build final material indices (remove submaterials and setup
+ // the final list)
+ BuildMaterialIndices();
+ }
+
+ // ------------------------------------------------------------------
+ // Copy all scene graph nodes - lights, cameras, dummies and meshes
+ // into one huge list.
+ //------------------------------------------------------------------
+ std::vector<BaseNode*> nodes;
+ nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size()
+ + mParser->m_vCameras.size() + mParser->m_vDummies.size());
+
+ // Lights
+ for (auto &light : mParser->m_vLights)nodes.push_back(&light);
+ // Cameras
+ for (auto &camera : mParser->m_vCameras)nodes.push_back(&camera);
+ // Meshes
+ for (auto &mesh : mParser->m_vMeshes)nodes.push_back(&mesh);
+ // Dummies
+ for (auto &dummy : mParser->m_vDummies)nodes.push_back(&dummy);
+
+ // build the final node graph
+ BuildNodes(nodes);
+
+ // build output animations
+ BuildAnimations(nodes);
+
+ // build output cameras
+ BuildCameras();
+
+ // build output lights
+ BuildLights();
+
+ // ------------------------------------------------------------------
+ // If we have no meshes use the SkeletonMeshBuilder helper class
+ // to build a mesh for the animation skeleton
+ // FIXME: very strange results
+ // ------------------------------------------------------------------
+ if (!pScene->mNumMeshes) {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ if (!noSkeletonMesh) {
+ SkeletonMeshBuilder skeleton(pScene);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::GenerateDefaultMaterial()
{
- ai_assert(NULL != mParser);
-
- bool bHas = false;
- for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
- if ((*i).bSkip)continue;
- if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex) {
- (*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size();
- bHas = true;
- }
- }
- if (bHas || mParser->m_vMaterials.empty()) {
- // add a simple material without submaterials to the parser's list
- mParser->m_vMaterials.push_back ( ASE::Material() );
- ASE::Material& mat = mParser->m_vMaterials.back();
-
- mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
- mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
- mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
- mat.mShading = Discreet3DS::Gouraud;
- mat.mName = AI_DEFAULT_MATERIAL_NAME;
- }
+ ai_assert(NULL != mParser);
+
+ bool bHas = false;
+ for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
+ if ((*i).bSkip)continue;
+ if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex) {
+ (*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size();
+ bHas = true;
+ }
+ }
+ if (bHas || mParser->m_vMaterials.empty()) {
+ // add a simple material without submaterials to the parser's list
+ mParser->m_vMaterials.push_back ( ASE::Material() );
+ ASE::Material& mat = mParser->m_vMaterials.back();
+
+ mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f);
+ mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
+ mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
+ mat.mShading = Discreet3DS::Gouraud;
+ mat.mName = AI_DEFAULT_MATERIAL_NAME;
+ }
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes)
{
- // check whether we have at least one mesh which has animations
- std::vector<ASE::BaseNode*>::const_iterator i = nodes.begin();
- unsigned int iNum = 0;
- for (;i != nodes.end();++i) {
-
- // TODO: Implement Bezier & TCB support
- if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
- DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
- "This is not supported.");
- }
- if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
- DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
- "This is not supported.");
- }
- if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) {
- DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
- "This is not supported.");
- }
-
- // We compare against 1 here - firstly one key is not
- // really an animation and secondly MAX writes dummies
- // that represent the node transformation.
- if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){
- ++iNum;
- }
- if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) {
- ++iNum;
- }
- }
- if (iNum) {
- // Generate a new animation channel and setup everything for it
- pcScene->mNumAnimations = 1;
- pcScene->mAnimations = new aiAnimation*[1];
- aiAnimation* pcAnim = pcScene->mAnimations[0] = new aiAnimation();
- pcAnim->mNumChannels = iNum;
- pcAnim->mChannels = new aiNodeAnim*[iNum];
- pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame;
-
- iNum = 0;
-
- // Now iterate through all meshes and collect all data we can find
- for (i = nodes.begin();i != nodes.end();++i) {
-
- ASE::BaseNode* me = *i;
- if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x )) {
- // Generate an extra channel for the camera/light target.
- // BuildNodes() does also generate an extra node, named
- // <baseName>.Target.
- aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
- nd->mNodeName.Set(me->mName + ".Target");
-
- // If there is no input position channel we will need
- // to supply the default position from the node's
- // local transformation matrix.
- /*TargetAnimationHelper helper;
- if (me->mAnim.akeyPositions.empty())
- {
- aiMatrix4x4& mat = (*i)->mTransform;
- helper.SetFixedMainAnimationChannel(aiVector3D(
- mat.a4, mat.b4, mat.c4));
- }
- else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
- helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
-
- helper.Process(&me->mTargetAnim.akeyPositions);*/
-
- // Allocate the key array and fill it
- nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
- nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
-
- ::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0],
- nd->mNumPositionKeys * sizeof(aiVectorKey));
- }
-
- if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1) {
- // Begin a new node animation channel for this node
- aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
- nd->mNodeName.Set(me->mName);
-
- // copy position keys
- if (me->mAnim.akeyPositions.size() > 1 )
- {
- // Allocate the key array and fill it
- nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size();
- nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
-
- ::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0],
- nd->mNumPositionKeys * sizeof(aiVectorKey));
- }
- // copy rotation keys
- if (me->mAnim.akeyRotations.size() > 1 ) {
- // Allocate the key array and fill it
- nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size();
- nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
-
- // --------------------------------------------------------------------
- // Rotation keys are offsets to the previous keys.
- // We have the quaternion representations of all
- // of them, so we just need to concatenate all
- // (unit-length) quaternions to get the absolute
- // rotations.
- // Rotation keys are ABSOLUTE for older files
- // --------------------------------------------------------------------
-
- aiQuaternion cur;
- for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
- aiQuatKey q = me->mAnim.akeyRotations[a];
-
- if (mParser->iFileFormat > 110) {
- cur = (a ? cur*q.mValue : q.mValue);
- q.mValue = cur.Normalize();
- }
- nd->mRotationKeys[a] = q;
-
- // need this to get to Assimp quaternion conventions
- nd->mRotationKeys[a].mValue.w *= -1.f;
- }
- }
- // copy scaling keys
- if (me->mAnim.akeyScaling.size() > 1 ) {
- // Allocate the key array and fill it
- nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size();
- nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
-
- ::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0],
- nd->mNumScalingKeys * sizeof(aiVectorKey));
- }
- }
- }
- }
+ // check whether we have at least one mesh which has animations
+ std::vector<ASE::BaseNode*>::const_iterator i = nodes.begin();
+ unsigned int iNum = 0;
+ for (;i != nodes.end();++i) {
+
+ // TODO: Implement Bezier & TCB support
+ if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
+ DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+ "This is not supported.");
+ }
+ if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
+ DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
+ "This is not supported.");
+ }
+ if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) {
+ DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+ "This is not supported.");
+ }
+
+ // We compare against 1 here - firstly one key is not
+ // really an animation and secondly MAX writes dummies
+ // that represent the node transformation.
+ if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){
+ ++iNum;
+ }
+ if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) {
+ ++iNum;
+ }
+ }
+ if (iNum) {
+ // Generate a new animation channel and setup everything for it
+ pcScene->mNumAnimations = 1;
+ pcScene->mAnimations = new aiAnimation*[1];
+ aiAnimation* pcAnim = pcScene->mAnimations[0] = new aiAnimation();
+ pcAnim->mNumChannels = iNum;
+ pcAnim->mChannels = new aiNodeAnim*[iNum];
+ pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame;
+
+ iNum = 0;
+
+ // Now iterate through all meshes and collect all data we can find
+ for (i = nodes.begin();i != nodes.end();++i) {
+
+ ASE::BaseNode* me = *i;
+ if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x )) {
+ // Generate an extra channel for the camera/light target.
+ // BuildNodes() does also generate an extra node, named
+ // <baseName>.Target.
+ aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
+ nd->mNodeName.Set(me->mName + ".Target");
+
+ // If there is no input position channel we will need
+ // to supply the default position from the node's
+ // local transformation matrix.
+ /*TargetAnimationHelper helper;
+ if (me->mAnim.akeyPositions.empty())
+ {
+ aiMatrix4x4& mat = (*i)->mTransform;
+ helper.SetFixedMainAnimationChannel(aiVector3D(
+ mat.a4, mat.b4, mat.c4));
+ }
+ else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
+ helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
+
+ helper.Process(&me->mTargetAnim.akeyPositions);*/
+
+ // Allocate the key array and fill it
+ nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
+ nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+
+ ::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0],
+ nd->mNumPositionKeys * sizeof(aiVectorKey));
+ }
+
+ if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1) {
+ // Begin a new node animation channel for this node
+ aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
+ nd->mNodeName.Set(me->mName);
+
+ // copy position keys
+ if (me->mAnim.akeyPositions.size() > 1 )
+ {
+ // Allocate the key array and fill it
+ nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size();
+ nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+
+ ::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0],
+ nd->mNumPositionKeys * sizeof(aiVectorKey));
+ }
+ // copy rotation keys
+ if (me->mAnim.akeyRotations.size() > 1 ) {
+ // Allocate the key array and fill it
+ nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size();
+ nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+
+ // --------------------------------------------------------------------
+ // Rotation keys are offsets to the previous keys.
+ // We have the quaternion representations of all
+ // of them, so we just need to concatenate all
+ // (unit-length) quaternions to get the absolute
+ // rotations.
+ // Rotation keys are ABSOLUTE for older files
+ // --------------------------------------------------------------------
+
+ aiQuaternion cur;
+ for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
+ aiQuatKey q = me->mAnim.akeyRotations[a];
+
+ if (mParser->iFileFormat > 110) {
+ cur = (a ? cur*q.mValue : q.mValue);
+ q.mValue = cur.Normalize();
+ }
+ nd->mRotationKeys[a] = q;
+
+ // need this to get to Assimp quaternion conventions
+ nd->mRotationKeys[a].mValue.w *= -1.f;
+ }
+ }
+ // copy scaling keys
+ if (me->mAnim.akeyScaling.size() > 1 ) {
+ // Allocate the key array and fill it
+ nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size();
+ nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+
+ ::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0],
+ nd->mNumScalingKeys * sizeof(aiVectorKey));
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Build output cameras
void ASEImporter::BuildCameras()
{
- if (!mParser->m_vCameras.empty()) {
- pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size();
- pcScene->mCameras = new aiCamera*[pcScene->mNumCameras];
-
- for (unsigned int i = 0; i < pcScene->mNumCameras;++i) {
- aiCamera* out = pcScene->mCameras[i] = new aiCamera();
- ASE::Camera& in = mParser->m_vCameras[i];
-
- // copy members
- out->mClipPlaneFar = in.mFar;
- out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
- out->mHorizontalFOV = in.mFOV;
-
- out->mName.Set(in.mName);
- }
- }
+ if (!mParser->m_vCameras.empty()) {
+ pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size();
+ pcScene->mCameras = new aiCamera*[pcScene->mNumCameras];
+
+ for (unsigned int i = 0; i < pcScene->mNumCameras;++i) {
+ aiCamera* out = pcScene->mCameras[i] = new aiCamera();
+ ASE::Camera& in = mParser->m_vCameras[i];
+
+ // copy members
+ out->mClipPlaneFar = in.mFar;
+ out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
+ out->mHorizontalFOV = in.mFOV;
+
+ out->mName.Set(in.mName);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Build output lights
void ASEImporter::BuildLights()
{
- if (!mParser->m_vLights.empty()) {
- pcScene->mNumLights = (unsigned int)mParser->m_vLights.size();
- pcScene->mLights = new aiLight*[pcScene->mNumLights];
-
- for (unsigned int i = 0; i < pcScene->mNumLights;++i) {
- aiLight* out = pcScene->mLights[i] = new aiLight();
- ASE::Light& in = mParser->m_vLights[i];
-
- // The direction is encoded in the transformation matrix of the node.
- // In 3DS MAX the light source points into negative Z direction if
- // the node transformation is the identity.
- out->mDirection = aiVector3D(0.f,0.f,-1.f);
-
- out->mName.Set(in.mName);
- switch (in.mLightType)
- {
- case ASE::Light::TARGET:
- out->mType = aiLightSource_SPOT;
- out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle);
- out->mAngleOuterCone = (in.mFalloff ? AI_DEG_TO_RAD(in.mFalloff) : out->mAngleInnerCone);
- break;
-
- case ASE::Light::DIRECTIONAL:
- out->mType = aiLightSource_DIRECTIONAL;
- break;
-
- default:
- //case ASE::Light::OMNI:
- out->mType = aiLightSource_POINT;
- break;
- };
- out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity;
- }
- }
+ if (!mParser->m_vLights.empty()) {
+ pcScene->mNumLights = (unsigned int)mParser->m_vLights.size();
+ pcScene->mLights = new aiLight*[pcScene->mNumLights];
+
+ for (unsigned int i = 0; i < pcScene->mNumLights;++i) {
+ aiLight* out = pcScene->mLights[i] = new aiLight();
+ ASE::Light& in = mParser->m_vLights[i];
+
+ // The direction is encoded in the transformation matrix of the node.
+ // In 3DS MAX the light source points into negative Z direction if
+ // the node transformation is the identity.
+ out->mDirection = aiVector3D(0.f,0.f,-1.f);
+
+ out->mName.Set(in.mName);
+ switch (in.mLightType)
+ {
+ case ASE::Light::TARGET:
+ out->mType = aiLightSource_SPOT;
+ out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle);
+ out->mAngleOuterCone = (in.mFalloff ? AI_DEG_TO_RAD(in.mFalloff) : out->mAngleInnerCone);
+ break;
+
+ case ASE::Light::DIRECTIONAL:
+ out->mType = aiLightSource_DIRECTIONAL;
+ break;
+
+ default:
+ //case ASE::Light::OMNI:
+ out->mType = aiLightSource_POINT;
+ break;
+ };
+ out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(const std::vector<BaseNode*>& nodes,
- aiNode* pcParent,const char* szName)
+ aiNode* pcParent,const char* szName)
{
- aiMatrix4x4 m;
- AddNodes(nodes,pcParent,szName,m);
+ aiMatrix4x4 m;
+ AddNodes(nodes,pcParent,szName,m);
}
// ------------------------------------------------------------------------------------------------
// Add meshes to a given node
void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node)
{
- for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) {
- // Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color)
- const aiMesh* pcMesh = pcScene->mMeshes[i];
- const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
-
- if (mesh == snode) {
- ++node->mNumMeshes;
- }
- }
-
- if(node->mNumMeshes) {
- node->mMeshes = new unsigned int[node->mNumMeshes];
- for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i) {
-
- const aiMesh* pcMesh = pcScene->mMeshes[i];
- const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
- if (mesh == snode) {
- node->mMeshes[p++] = i;
-
- // Transform all vertices of the mesh back into their local space ->
- // at the moment they are pretransformed
- aiMatrix4x4 m = mesh->mTransform;
- m.Inverse();
-
- aiVector3D* pvCurPtr = pcMesh->mVertices;
- const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
- while (pvCurPtr != pvEndPtr) {
- *pvCurPtr = m * (*pvCurPtr);
- pvCurPtr++;
- }
-
- // Do the same for the normal vectors, if we have them.
- // As always, inverse transpose.
- if (pcMesh->mNormals) {
- aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
- m3.Transpose();
-
- pvCurPtr = pcMesh->mNormals;
- pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
- while (pvCurPtr != pvEndPtr) {
- *pvCurPtr = m3 * (*pvCurPtr);
- pvCurPtr++;
- }
- }
- }
- }
- }
+ for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) {
+ // Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color)
+ const aiMesh* pcMesh = pcScene->mMeshes[i];
+ const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
+
+ if (mesh == snode) {
+ ++node->mNumMeshes;
+ }
+ }
+
+ if(node->mNumMeshes) {
+ node->mMeshes = new unsigned int[node->mNumMeshes];
+ for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i) {
+
+ const aiMesh* pcMesh = pcScene->mMeshes[i];
+ const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
+ if (mesh == snode) {
+ node->mMeshes[p++] = i;
+
+ // Transform all vertices of the mesh back into their local space ->
+ // at the moment they are pretransformed
+ aiMatrix4x4 m = mesh->mTransform;
+ m.Inverse();
+
+ aiVector3D* pvCurPtr = pcMesh->mVertices;
+ const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
+ while (pvCurPtr != pvEndPtr) {
+ *pvCurPtr = m * (*pvCurPtr);
+ pvCurPtr++;
+ }
+
+ // Do the same for the normal vectors, if we have them.
+ // As always, inverse transpose.
+ if (pcMesh->mNormals) {
+ aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
+ m3.Transpose();
+
+ pvCurPtr = pcMesh->mNormals;
+ pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
+ while (pvCurPtr != pvEndPtr) {
+ *pvCurPtr = m3 * (*pvCurPtr);
+ pvCurPtr++;
+ }
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Add child nodes to a given parent node
void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
- aiNode* pcParent, const char* szName,
- const aiMatrix4x4& mat)
+ aiNode* pcParent, const char* szName,
+ const aiMatrix4x4& mat)
{
- const size_t len = szName ? ::strlen(szName) : 0;
- ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
-
- // Receives child nodes for the pcParent node
- std::vector<aiNode*> apcNodes;
-
- // Now iterate through all nodes in the scene and search for one
- // which has *us* as parent.
- for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
- const BaseNode* snode = *it;
- if (szName) {
- if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str()))
- continue;
- }
- else if (snode->mParent.length())
- continue;
-
- (*it)->mProcessed = true;
-
- // Allocate a new node and add it to the output data structure
- apcNodes.push_back(new aiNode());
- aiNode* node = apcNodes.back();
-
- node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
- node->mParent = pcParent;
-
- // Setup the transformation matrix of the node
- aiMatrix4x4 mParentAdjust = mat;
- mParentAdjust.Inverse();
- node->mTransformation = mParentAdjust*snode->mTransform;
-
- // Add sub nodes - prevent stack overflow due to recursive parenting
- if (node->mName != node->mParent->mName) {
- AddNodes(nodes,node,node->mName.data,snode->mTransform);
- }
-
- // Further processing depends on the type of the node
- if (snode->mType == ASE::BaseNode::Mesh) {
- // If the type of this node is "Mesh" we need to search
- // the list of output meshes in the data structure for
- // all those that belonged to this node once. This is
- // slightly inconvinient here and a better solution should
- // be used when this code is refactored next.
- AddMeshes(snode,node);
- }
- else if (is_not_qnan( snode->mTargetPosition.x )) {
- // If this is a target camera or light we generate a small
- // child node which marks the position of the camera
- // target (the direction information is contained in *this*
- // node's animation track but the exact target position
- // would be lost otherwise)
- if (!node->mNumChildren) {
- node->mChildren = new aiNode*[1];
- }
-
- aiNode* nd = new aiNode();
-
- nd->mName.Set ( snode->mName + ".Target" );
-
- nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4;
- nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4;
- nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4;
-
- nd->mParent = node;
-
- // The .Target node is always the first child node
- for (unsigned int m = 0; m < node->mNumChildren;++m)
- node->mChildren[m+1] = node->mChildren[m];
-
- node->mChildren[0] = nd;
- node->mNumChildren++;
-
- // What we did is so great, it is at least worth a debug message
- DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
- }
- }
-
- // Allocate enough space for the child nodes
- // We allocate one slot more in case this is a target camera/light
- pcParent->mNumChildren = (unsigned int)apcNodes.size();
- if (pcParent->mNumChildren) {
- pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */];
-
- // now build all nodes for our nice new children
- for (unsigned int p = 0; p < apcNodes.size();++p)
- pcParent->mChildren[p] = apcNodes[p];
- }
- return;
+ const size_t len = szName ? ::strlen(szName) : 0;
+ ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
+
+ // Receives child nodes for the pcParent node
+ std::vector<aiNode*> apcNodes;
+
+ // Now iterate through all nodes in the scene and search for one
+ // which has *us* as parent.
+ for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
+ const BaseNode* snode = *it;
+ if (szName) {
+ if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str()))
+ continue;
+ }
+ else if (snode->mParent.length())
+ continue;
+
+ (*it)->mProcessed = true;
+
+ // Allocate a new node and add it to the output data structure
+ apcNodes.push_back(new aiNode());
+ aiNode* node = apcNodes.back();
+
+ node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
+ node->mParent = pcParent;
+
+ // Setup the transformation matrix of the node
+ aiMatrix4x4 mParentAdjust = mat;
+ mParentAdjust.Inverse();
+ node->mTransformation = mParentAdjust*snode->mTransform;
+
+ // Add sub nodes - prevent stack overflow due to recursive parenting
+ if (node->mName != node->mParent->mName) {
+ AddNodes(nodes,node,node->mName.data,snode->mTransform);
+ }
+
+ // Further processing depends on the type of the node
+ if (snode->mType == ASE::BaseNode::Mesh) {
+ // If the type of this node is "Mesh" we need to search
+ // the list of output meshes in the data structure for
+ // all those that belonged to this node once. This is
+ // slightly inconvinient here and a better solution should
+ // be used when this code is refactored next.
+ AddMeshes(snode,node);
+ }
+ else if (is_not_qnan( snode->mTargetPosition.x )) {
+ // If this is a target camera or light we generate a small
+ // child node which marks the position of the camera
+ // target (the direction information is contained in *this*
+ // node's animation track but the exact target position
+ // would be lost otherwise)
+ if (!node->mNumChildren) {
+ node->mChildren = new aiNode*[1];
+ }
+
+ aiNode* nd = new aiNode();
+
+ nd->mName.Set ( snode->mName + ".Target" );
+
+ nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4;
+ nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4;
+ nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4;
+
+ nd->mParent = node;
+
+ // The .Target node is always the first child node
+ for (unsigned int m = 0; m < node->mNumChildren;++m)
+ node->mChildren[m+1] = node->mChildren[m];
+
+ node->mChildren[0] = nd;
+ node->mNumChildren++;
+
+ // What we did is so great, it is at least worth a debug message
+ DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
+ }
+ }
+
+ // Allocate enough space for the child nodes
+ // We allocate one slot more in case this is a target camera/light
+ pcParent->mNumChildren = (unsigned int)apcNodes.size();
+ if (pcParent->mNumChildren) {
+ pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */];
+
+ // now build all nodes for our nice new children
+ for (unsigned int p = 0; p < apcNodes.size();++p)
+ pcParent->mChildren[p] = apcNodes[p];
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Build the output node graph
-void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes) {
- ai_assert(NULL != pcScene);
-
- // allocate the one and only root node
- aiNode* root = pcScene->mRootNode = new aiNode();
- root->mName.Set("<ASERoot>");
-
- // Setup the coordinate system transformation
- pcScene->mRootNode->mNumChildren = 1;
- pcScene->mRootNode->mChildren = new aiNode*[1];
- aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode();
- ch->mParent = root;
-
- // Change the transformation matrix of all nodes
- for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) {
- aiMatrix4x4& m = (*it)->mTransform;
- m.Transpose(); // row-order vs column-order
- }
-
- // add all nodes
- AddNodes(nodes,ch,NULL);
-
- // now iterate through al nodes and find those that have not yet
- // been added to the nodegraph (= their parent could not be recognized)
- std::vector<const BaseNode*> aiList;
- for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) {
- if ((*it)->mProcessed) {
- continue;
- }
-
- // check whether our parent is known
- bool bKnowParent = false;
-
- // search the list another time, starting *here* and try to find out whether
- // there is a node that references *us* as a parent
- for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();it2 != end; ++it2) {
- if (it2 == it) {
- continue;
- }
-
- if ((*it2)->mName == (*it)->mParent) {
- bKnowParent = true;
- break;
- }
- }
- if (!bKnowParent) {
- aiList.push_back(*it);
- }
- }
-
- // Are there ane orphaned nodes?
- if (!aiList.empty()) {
- std::vector<aiNode*> apcNodes;
- apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);
-
- for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i)
- apcNodes.push_back(pcScene->mRootNode->mChildren[i]);
-
- delete[] pcScene->mRootNode->mChildren;
- for (std::vector<const BaseNode*>::/*const_*/iterator i = aiList.begin();i != aiList.end();++i) {
- const ASE::BaseNode* src = *i;
-
- // The parent is not known, so we can assume that we must add
- // this node to the root node of the whole scene
- aiNode* pcNode = new aiNode();
- pcNode->mParent = pcScene->mRootNode;
- pcNode->mName.Set(src->mName);
- AddMeshes(src,pcNode);
- AddNodes(nodes,pcNode,pcNode->mName.data);
- apcNodes.push_back(pcNode);
- }
-
- // Regenerate our output array
- pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
- for (unsigned int i = 0; i < apcNodes.size();++i)
- pcScene->mRootNode->mChildren[i] = apcNodes[i];
-
- pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
- }
-
- // Reset the third color set to NULL - we used this field to store a temporary pointer
- for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
- pcScene->mMeshes[i]->mColors[2] = NULL;
-
- // The root node should not have at least one child or the file is valid
- if (!pcScene->mRootNode->mNumChildren) {
- throw DeadlyImportError("ASE: No nodes loaded. The file is either empty or corrupt");
- }
-
- // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
- pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes) {
+ ai_assert(NULL != pcScene);
+
+ // allocate the one and only root node
+ aiNode* root = pcScene->mRootNode = new aiNode();
+ root->mName.Set("<ASERoot>");
+
+ // Setup the coordinate system transformation
+ pcScene->mRootNode->mNumChildren = 1;
+ pcScene->mRootNode->mChildren = new aiNode*[1];
+ aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode();
+ ch->mParent = root;
+
+ // Change the transformation matrix of all nodes
+ for (BaseNode *node : nodes) {
+ aiMatrix4x4& m = node->mTransform;
+ m.Transpose(); // row-order vs column-order
+ }
+
+ // add all nodes
+ AddNodes(nodes,ch,NULL);
+
+ // now iterate through al nodes and find those that have not yet
+ // been added to the nodegraph (= their parent could not be recognized)
+ std::vector<const BaseNode*> aiList;
+ for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) {
+ if ((*it)->mProcessed) {
+ continue;
+ }
+
+ // check whether our parent is known
+ bool bKnowParent = false;
+
+ // search the list another time, starting *here* and try to find out whether
+ // there is a node that references *us* as a parent
+ for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();it2 != end; ++it2) {
+ if (it2 == it) {
+ continue;
+ }
+
+ if ((*it2)->mName == (*it)->mParent) {
+ bKnowParent = true;
+ break;
+ }
+ }
+ if (!bKnowParent) {
+ aiList.push_back(*it);
+ }
+ }
+
+ // Are there ane orphaned nodes?
+ if (!aiList.empty()) {
+ std::vector<aiNode*> apcNodes;
+ apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);
+
+ for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i)
+ apcNodes.push_back(pcScene->mRootNode->mChildren[i]);
+
+ delete[] pcScene->mRootNode->mChildren;
+ for (std::vector<const BaseNode*>::/*const_*/iterator i = aiList.begin();i != aiList.end();++i) {
+ const ASE::BaseNode* src = *i;
+
+ // The parent is not known, so we can assume that we must add
+ // this node to the root node of the whole scene
+ aiNode* pcNode = new aiNode();
+ pcNode->mParent = pcScene->mRootNode;
+ pcNode->mName.Set(src->mName);
+ AddMeshes(src,pcNode);
+ AddNodes(nodes,pcNode,pcNode->mName.data);
+ apcNodes.push_back(pcNode);
+ }
+
+ // Regenerate our output array
+ pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
+ for (unsigned int i = 0; i < apcNodes.size();++i)
+ pcScene->mRootNode->mChildren[i] = apcNodes[i];
+
+ pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
+ }
+
+ // Reset the third color set to NULL - we used this field to store a temporary pointer
+ for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
+ pcScene->mMeshes[i]->mColors[2] = NULL;
+
+ // The root node should not have at least one child or the file is valid
+ if (!pcScene->mRootNode->mNumChildren) {
+ throw DeadlyImportError("ASE: No nodes loaded. The file is either empty or corrupt");
+ }
+
+ // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+ pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
}
// ------------------------------------------------------------------------------------------------
// Convert the imported data to the internal verbose representation
-void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) {
- // allocate output storage
- std::vector<aiVector3D> mPositions;
- std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- std::vector<aiColor4D> mVertexColors;
- std::vector<aiVector3D> mNormals;
- std::vector<BoneVertex> mBoneVertices;
-
- unsigned int iSize = (unsigned int)mesh.mFaces.size() * 3;
- mPositions.resize(iSize);
-
- // optional texture coordinates
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) {
- if (!mesh.amTexCoords[i].empty()) {
- amTexCoords[i].resize(iSize);
- }
- }
- // optional vertex colors
- if (!mesh.mVertexColors.empty()) {
- mVertexColors.resize(iSize);
- }
-
- // optional vertex normals (vertex normals can simply be copied)
- if (!mesh.mNormals.empty()) {
- mNormals.resize(iSize);
- }
- // bone vertices. There is no need to change the bone list
- if (!mesh.mBoneVertices.empty()) {
- mBoneVertices.resize(iSize);
- }
-
- // iterate through all faces in the mesh
- unsigned int iCurrent = 0, fi = 0;
- for (std::vector<ASE::Face>::iterator i = mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi) {
- for (unsigned int n = 0; n < 3;++n,++iCurrent)
- {
- mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
-
- // add texture coordinates
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
- if (mesh.amTexCoords[c].empty())break;
- amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
- }
- // add vertex colors
- if (!mesh.mVertexColors.empty()) {
- mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]];
- }
- // add normal vectors
- if (!mesh.mNormals.empty()) {
- mNormals[iCurrent] = mesh.mNormals[fi*3+n];
- mNormals[iCurrent].Normalize();
- }
-
- // handle bone vertices
- if ((*i).mIndices[n] < mesh.mBoneVertices.size()) {
- // (sometimes this will cause bone verts to be duplicated
- // however, I' quite sure Schrompf' JoinVerticesStep
- // will fix that again ...)
- mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]];
- }
- (*i).mIndices[n] = iCurrent;
- }
- }
-
- // replace the old arrays
- mesh.mNormals = mNormals;
- mesh.mPositions = mPositions;
- mesh.mVertexColors = mVertexColors;
-
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
- mesh.amTexCoords[c] = amTexCoords[c];
+void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) {
+ // allocate output storage
+ std::vector<aiVector3D> mPositions;
+ std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ std::vector<aiColor4D> mVertexColors;
+ std::vector<aiVector3D> mNormals;
+ std::vector<BoneVertex> mBoneVertices;
+
+ unsigned int iSize = (unsigned int)mesh.mFaces.size() * 3;
+ mPositions.resize(iSize);
+
+ // optional texture coordinates
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) {
+ if (!mesh.amTexCoords[i].empty()) {
+ amTexCoords[i].resize(iSize);
+ }
+ }
+ // optional vertex colors
+ if (!mesh.mVertexColors.empty()) {
+ mVertexColors.resize(iSize);
+ }
+
+ // optional vertex normals (vertex normals can simply be copied)
+ if (!mesh.mNormals.empty()) {
+ mNormals.resize(iSize);
+ }
+ // bone vertices. There is no need to change the bone list
+ if (!mesh.mBoneVertices.empty()) {
+ mBoneVertices.resize(iSize);
+ }
+
+ // iterate through all faces in the mesh
+ unsigned int iCurrent = 0, fi = 0;
+ for (std::vector<ASE::Face>::iterator i = mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi) {
+ for (unsigned int n = 0; n < 3;++n,++iCurrent)
+ {
+ mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
+
+ // add texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ if (mesh.amTexCoords[c].empty())break;
+ amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
+ }
+ // add vertex colors
+ if (!mesh.mVertexColors.empty()) {
+ mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]];
+ }
+ // add normal vectors
+ if (!mesh.mNormals.empty()) {
+ mNormals[iCurrent] = mesh.mNormals[fi*3+n];
+ mNormals[iCurrent].Normalize();
+ }
+
+ // handle bone vertices
+ if ((*i).mIndices[n] < mesh.mBoneVertices.size()) {
+ // (sometimes this will cause bone verts to be duplicated
+ // however, I' quite sure Schrompf' JoinVerticesStep
+ // will fix that again ...)
+ mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]];
+ }
+ (*i).mIndices[n] = iCurrent;
+ }
+ }
+
+ // replace the old arrays
+ mesh.mNormals = mNormals;
+ mesh.mPositions = mPositions;
+ mesh.mVertexColors = mVertexColors;
+
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+ mesh.amTexCoords[c] = amTexCoords[c];
}
// ------------------------------------------------------------------------------------------------
// Copy a texture from the ASE structs to the output material
void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type)
{
- // Setup the texture name
- aiString tex;
- tex.Set( texture.mMapName);
- mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
+ // Setup the texture name
+ aiString tex;
+ tex.Set( texture.mMapName);
+ mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
- // Setup the texture blend factor
- if (is_not_qnan(texture.mTextureBlend))
- mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+ // Setup the texture blend factor
+ if (is_not_qnan(texture.mTextureBlend))
+ mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
- // Setup texture UV transformations
- mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+ // Setup texture UV transformations
+ mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------
// Convert from ASE material to output material
void ASEImporter::ConvertMaterial(ASE::Material& mat)
{
- // LARGE TODO: Much code her is copied from 3DS ... join them maybe?
-
- // Allocate the output material
- mat.pcInstance = new aiMaterial();
-
- // At first add the base ambient color of the
- // scene to the material
- mat.mAmbient.r += mParser->m_clrAmbient.r;
- mat.mAmbient.g += mParser->m_clrAmbient.g;
- mat.mAmbient.b += mParser->m_clrAmbient.b;
-
- aiString name;
- name.Set( mat.mName);
- mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME);
-
- // material colors
- mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
- mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
- mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-
- // shininess
- if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength)
- {
- mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
- mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
- }
- // If there is no shininess, we can disable phong lighting
- else if (D3DS::Discreet3DS::Metal == mat.mShading ||
- D3DS::Discreet3DS::Phong == mat.mShading ||
- D3DS::Discreet3DS::Blinn == mat.mShading)
- {
- mat.mShading = D3DS::Discreet3DS::Gouraud;
- }
-
- // opacity
- mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
-
- // Two sided rendering?
- if (mat.mTwoSided)
- {
- int i = 1;
- mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
- }
-
- // shading mode
- aiShadingMode eShading = aiShadingMode_NoShading;
- switch (mat.mShading)
- {
- case D3DS::Discreet3DS::Flat:
- eShading = aiShadingMode_Flat; break;
- case D3DS::Discreet3DS::Phong :
- eShading = aiShadingMode_Phong; break;
- case D3DS::Discreet3DS::Blinn :
- eShading = aiShadingMode_Blinn; break;
-
- // I don't know what "Wire" shading should be,
- // assume it is simple lambertian diffuse (L dot N) shading
- case D3DS::Discreet3DS::Wire:
- {
- // set the wireframe flag
- unsigned int iWire = 1;
- mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
- }
- case D3DS::Discreet3DS::Gouraud:
- eShading = aiShadingMode_Gouraud; break;
- case D3DS::Discreet3DS::Metal :
- eShading = aiShadingMode_CookTorrance; break;
- }
- mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
-
- // DIFFUSE texture
- if( mat.sTexDiffuse.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
-
- // SPECULAR texture
- if( mat.sTexSpecular.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
-
- // AMBIENT texture
- if( mat.sTexAmbient.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
-
- // OPACITY texture
- if( mat.sTexOpacity.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY);
-
- // EMISSIVE texture
- if( mat.sTexEmissive.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE);
-
- // BUMP texture
- if( mat.sTexBump.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
-
- // SHININESS texture
- if( mat.sTexShininess.mMapName.length() > 0)
- CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
-
- // store the name of the material itself, too
- if( mat.mName.length() > 0) {
- aiString tex;tex.Set( mat.mName);
- mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME);
- }
- return;
+ // LARGE TODO: Much code her is copied from 3DS ... join them maybe?
+
+ // Allocate the output material
+ mat.pcInstance = new aiMaterial();
+
+ // At first add the base ambient color of the
+ // scene to the material
+ mat.mAmbient.r += mParser->m_clrAmbient.r;
+ mat.mAmbient.g += mParser->m_clrAmbient.g;
+ mat.mAmbient.b += mParser->m_clrAmbient.b;
+
+ aiString name;
+ name.Set( mat.mName);
+ mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME);
+
+ // material colors
+ mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+ mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+ mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+
+ // shininess
+ if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength)
+ {
+ mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+ mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+ }
+ // If there is no shininess, we can disable phong lighting
+ else if (D3DS::Discreet3DS::Metal == mat.mShading ||
+ D3DS::Discreet3DS::Phong == mat.mShading ||
+ D3DS::Discreet3DS::Blinn == mat.mShading)
+ {
+ mat.mShading = D3DS::Discreet3DS::Gouraud;
+ }
+
+ // opacity
+ mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
+
+ // Two sided rendering?
+ if (mat.mTwoSided)
+ {
+ int i = 1;
+ mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
+ }
+
+ // shading mode
+ aiShadingMode eShading = aiShadingMode_NoShading;
+ switch (mat.mShading)
+ {
+ case D3DS::Discreet3DS::Flat:
+ eShading = aiShadingMode_Flat; break;
+ case D3DS::Discreet3DS::Phong :
+ eShading = aiShadingMode_Phong; break;
+ case D3DS::Discreet3DS::Blinn :
+ eShading = aiShadingMode_Blinn; break;
+
+ // I don't know what "Wire" shading should be,
+ // assume it is simple lambertian diffuse (L dot N) shading
+ case D3DS::Discreet3DS::Wire:
+ {
+ // set the wireframe flag
+ unsigned int iWire = 1;
+ mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+ }
+ case D3DS::Discreet3DS::Gouraud:
+ eShading = aiShadingMode_Gouraud; break;
+ case D3DS::Discreet3DS::Metal :
+ eShading = aiShadingMode_CookTorrance; break;
+ }
+ mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+
+ // DIFFUSE texture
+ if( mat.sTexDiffuse.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
+
+ // SPECULAR texture
+ if( mat.sTexSpecular.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
+
+ // AMBIENT texture
+ if( mat.sTexAmbient.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
+
+ // OPACITY texture
+ if( mat.sTexOpacity.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY);
+
+ // EMISSIVE texture
+ if( mat.sTexEmissive.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE);
+
+ // BUMP texture
+ if( mat.sTexBump.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
+
+ // SHININESS texture
+ if( mat.sTexShininess.mMapName.length() > 0)
+ CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
+
+ // store the name of the material itself, too
+ if( mat.mName.length() > 0) {
+ aiString tex;tex.Set( mat.mName);
+ mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME);
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Build output meshes
void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMeshes)
{
- // validate the material index of the mesh
- if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
- mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
- DefaultLogger::get()->warn("Material index is out of range");
- }
-
- // If the material the mesh is assigned to is consisting of submeshes, split it
- if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) {
- std::vector<ASE::Material> vSubMaterials = mParser->
- m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
-
- std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
-
- // build a list of all faces per submaterial
- for (unsigned int i = 0; i < mesh.mFaces.size();++i) {
- // check range
- if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
- DefaultLogger::get()->warn("Submaterial index is out of range");
-
- // use the last material instead
- aiSplit[vSubMaterials.size()-1].push_back(i);
- }
- else aiSplit[mesh.mFaces[i].iMaterial].push_back(i);
- }
-
- // now generate submeshes
- for (unsigned int p = 0; p < vSubMaterials.size();++p) {
- if (!aiSplit[p].empty()) {
-
- aiMesh* p_pcOut = new aiMesh();
- p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // let the sub material index
- p_pcOut->mMaterialIndex = p;
-
- // we will need this material
- mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
-
- // store the real index here ... color channel 3
- p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
-
- // store a pointer to the mesh in color channel 2
- p_pcOut->mColors[2] = (aiColor4D*) &mesh;
- avOutMeshes.push_back(p_pcOut);
-
- // convert vertices
- p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
- p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
-
- // receive output vertex weights
- std::vector<std::pair<unsigned int, float> > *avOutputBones = NULL;
- if (!mesh.mBones.empty()) {
- avOutputBones = new std::vector<std::pair<unsigned int, float> >[mesh.mBones.size()];
- }
-
- // allocate enough storage for faces
- p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
-
- unsigned int iBase = 0,iIndex;
- if (p_pcOut->mNumVertices) {
- p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
- p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
- for (unsigned int q = 0; q < aiSplit[p].size();++q) {
-
- iIndex = aiSplit[p][q];
-
- p_pcOut->mFaces[q].mIndices = new unsigned int[3];
- p_pcOut->mFaces[q].mNumIndices = 3;
-
- for (unsigned int t = 0; t < 3;++t, ++iBase) {
- const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
-
- p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2];
- p_pcOut->mNormals [iBase] = mesh.mNormals [iIndex2];
-
- // convert bones, if existing
- if (!mesh.mBones.empty()) {
- // check whether there is a vertex weight for this vertex index
- if (iIndex2 < mesh.mBoneVertices.size()) {
-
- for (std::vector<std::pair<int,float> >::const_iterator
- blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin();
- blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb) {
-
- // NOTE: illegal cases have already been filtered out
- avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
- iBase,(*blubb).second));
- }
- }
- }
- p_pcOut->mFaces[q].mIndices[t] = iBase;
- }
- }
- }
- // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
- if (!mesh.amTexCoords[c].empty())
- {
- p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
- iBase = 0;
- for (unsigned int q = 0; q < aiSplit[p].size();++q) {
- iIndex = aiSplit[p][q];
- for (unsigned int t = 0; t < 3;++t) {
- p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
- }
- }
- // Setup the number of valid vertex components
- p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
- }
- }
-
- // Convert vertex colors (only one set supported)
- if (!mesh.mVertexColors.empty()){
- p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
- iBase = 0;
- for (unsigned int q = 0; q < aiSplit[p].size();++q) {
- iIndex = aiSplit[p][q];
- for (unsigned int t = 0; t < 3;++t) {
- p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
- }
- }
- }
- // Copy bones
- if (!mesh.mBones.empty()) {
- p_pcOut->mNumBones = 0;
- for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
- if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
-
- p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
- aiBone** pcBone = p_pcOut->mBones;
- for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
- {
- if (!avOutputBones[mrspock].empty()) {
- // we will need this bone. add it to the output mesh and
- // add all per-vertex weights
- aiBone* pc = *pcBone = new aiBone();
- pc->mName.Set(mesh.mBones[mrspock].mName);
-
- pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size();
- pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-
- for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk)
- {
- const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
- pc->mWeights[captainkirk].mVertexId = ref.first;
- pc->mWeights[captainkirk].mWeight = ref.second;
- }
- ++pcBone;
- }
- }
- // delete allocated storage
- delete[] avOutputBones;
- }
- }
- }
- // delete storage
- delete[] aiSplit;
- }
- else
- {
- // Otherwise we can simply copy the data to one output mesh
- // This codepath needs less memory and uses fast memcpy()s
- // to do the actual copying. So I think it is worth the
- // effort here.
-
- aiMesh* p_pcOut = new aiMesh();
- p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // set an empty sub material index
- p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
- mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
-
- // store the real index here ... in color channel 3
- p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
-
- // store a pointer to the mesh in color channel 2
- p_pcOut->mColors[2] = (aiColor4D*) &mesh;
- avOutMeshes.push_back(p_pcOut);
-
- // If the mesh hasn't faces or vertices, there are two cases
- // possible: 1. the model is invalid. 2. This is a dummy
- // helper object which we are going to remove later ...
- if (mesh.mFaces.empty() || mesh.mPositions.empty()) {
- return;
- }
-
- // convert vertices
- p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size();
- p_pcOut->mNumFaces = (unsigned int)mesh.mFaces.size();
-
- // allocate enough storage for faces
- p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
-
- // copy vertices
- p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()];
- memcpy(p_pcOut->mVertices,&mesh.mPositions[0],
- mesh.mPositions.size() * sizeof(aiVector3D));
-
- // copy normals
- p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()];
- memcpy(p_pcOut->mNormals,&mesh.mNormals[0],
- mesh.mNormals.size() * sizeof(aiVector3D));
-
- // copy texture coordinates
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
- if (!mesh.amTexCoords[c].empty()) {
- p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()];
- memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0],
- mesh.amTexCoords[c].size() * sizeof(aiVector3D));
-
- // setup the number of valid vertex components
- p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
- }
- }
-
- // copy vertex colors
- if (!mesh.mVertexColors.empty()) {
- p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()];
- memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0],
- mesh.mVertexColors.size() * sizeof(aiColor4D));
- }
-
- // copy faces
- for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace) {
- p_pcOut->mFaces[iFace].mNumIndices = 3;
- p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
-
- // copy indices
- p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
- p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
- p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
- }
-
- // copy vertex bones
- if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty()) {
- std::vector<std::vector<aiVertexWeight> > avBonesOut( mesh.mBones.size() );
-
- // find all vertex weights for this bone
- unsigned int quak = 0;
- for (std::vector<BoneVertex>::const_iterator harrypotter = mesh.mBoneVertices.begin();
- harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak) {
-
- for (std::vector<std::pair<int,float> >::const_iterator
- ronaldweasley = (*harrypotter).mBoneWeights.begin();
- ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley)
- {
- aiVertexWeight weight;
- weight.mVertexId = quak;
- weight.mWeight = (*ronaldweasley).second;
- avBonesOut[(*ronaldweasley).first].push_back(weight);
- }
- }
-
- // now build a final bone list
- p_pcOut->mNumBones = 0;
- for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
- if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
-
- p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
- aiBone** pcBone = p_pcOut->mBones;
- for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) {
- if (!avBonesOut[jfkennedy].empty()) {
- aiBone* pc = *pcBone = new aiBone();
- pc->mName.Set(mesh.mBones[jfkennedy].mName);
- pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
- pc->mWeights = new aiVertexWeight[pc->mNumWeights];
- ::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
- sizeof(aiVertexWeight) * pc->mNumWeights);
- ++pcBone;
- }
- }
- }
- }
+ // validate the material index of the mesh
+ if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) {
+ mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
+ DefaultLogger::get()->warn("Material index is out of range");
+ }
+
+ // If the material the mesh is assigned to is consisting of submeshes, split it
+ if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) {
+ std::vector<ASE::Material> vSubMaterials = mParser->
+ m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
+
+ std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
+
+ // build a list of all faces per submaterial
+ for (unsigned int i = 0; i < mesh.mFaces.size();++i) {
+ // check range
+ if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
+ DefaultLogger::get()->warn("Submaterial index is out of range");
+
+ // use the last material instead
+ aiSplit[vSubMaterials.size()-1].push_back(i);
+ }
+ else aiSplit[mesh.mFaces[i].iMaterial].push_back(i);
+ }
+
+ // now generate submeshes
+ for (unsigned int p = 0; p < vSubMaterials.size();++p) {
+ if (!aiSplit[p].empty()) {
+
+ aiMesh* p_pcOut = new aiMesh();
+ p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // let the sub material index
+ p_pcOut->mMaterialIndex = p;
+
+ // we will need this material
+ mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
+
+ // store the real index here ... color channel 3
+ p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
+ // store a pointer to the mesh in color channel 2
+ p_pcOut->mColors[2] = (aiColor4D*) &mesh;
+ avOutMeshes.push_back(p_pcOut);
+
+ // convert vertices
+ p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
+ p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
+
+ // receive output vertex weights
+ std::vector<std::pair<unsigned int, float> > *avOutputBones = NULL;
+ if (!mesh.mBones.empty()) {
+ avOutputBones = new std::vector<std::pair<unsigned int, float> >[mesh.mBones.size()];
+ }
+
+ // allocate enough storage for faces
+ p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+ unsigned int iBase = 0,iIndex;
+ if (p_pcOut->mNumVertices) {
+ p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
+ p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices];
+ for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+
+ iIndex = aiSplit[p][q];
+
+ p_pcOut->mFaces[q].mIndices = new unsigned int[3];
+ p_pcOut->mFaces[q].mNumIndices = 3;
+
+ for (unsigned int t = 0; t < 3;++t, ++iBase) {
+ const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
+
+ p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2];
+ p_pcOut->mNormals [iBase] = mesh.mNormals [iIndex2];
+
+ // convert bones, if existing
+ if (!mesh.mBones.empty()) {
+ // check whether there is a vertex weight for this vertex index
+ if (iIndex2 < mesh.mBoneVertices.size()) {
+
+ for (std::vector<std::pair<int,float> >::const_iterator
+ blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin();
+ blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb) {
+
+ // NOTE: illegal cases have already been filtered out
+ avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
+ iBase,(*blubb).second));
+ }
+ }
+ }
+ p_pcOut->mFaces[q].mIndices[t] = iBase;
+ }
+ }
+ }
+ // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ if (!mesh.amTexCoords[c].empty())
+ {
+ p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
+ iBase = 0;
+ for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+ iIndex = aiSplit[p][q];
+ for (unsigned int t = 0; t < 3;++t) {
+ p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
+ }
+ }
+ // Setup the number of valid vertex components
+ p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+ }
+ }
+
+ // Convert vertex colors (only one set supported)
+ if (!mesh.mVertexColors.empty()){
+ p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
+ iBase = 0;
+ for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+ iIndex = aiSplit[p][q];
+ for (unsigned int t = 0; t < 3;++t) {
+ p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
+ }
+ }
+ }
+ // Copy bones
+ if (!mesh.mBones.empty()) {
+ p_pcOut->mNumBones = 0;
+ for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
+ if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
+
+ p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
+ aiBone** pcBone = p_pcOut->mBones;
+ for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
+ {
+ if (!avOutputBones[mrspock].empty()) {
+ // we will need this bone. add it to the output mesh and
+ // add all per-vertex weights
+ aiBone* pc = *pcBone = new aiBone();
+ pc->mName.Set(mesh.mBones[mrspock].mName);
+
+ pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size();
+ pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+
+ for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk)
+ {
+ const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
+ pc->mWeights[captainkirk].mVertexId = ref.first;
+ pc->mWeights[captainkirk].mWeight = ref.second;
+ }
+ ++pcBone;
+ }
+ }
+ // delete allocated storage
+ delete[] avOutputBones;
+ }
+ }
+ }
+ // delete storage
+ delete[] aiSplit;
+ }
+ else
+ {
+ // Otherwise we can simply copy the data to one output mesh
+ // This codepath needs less memory and uses fast memcpy()s
+ // to do the actual copying. So I think it is worth the
+ // effort here.
+
+ aiMesh* p_pcOut = new aiMesh();
+ p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // set an empty sub material index
+ p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
+ mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
+
+ // store the real index here ... in color channel 3
+ p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
+ // store a pointer to the mesh in color channel 2
+ p_pcOut->mColors[2] = (aiColor4D*) &mesh;
+ avOutMeshes.push_back(p_pcOut);
+
+ // If the mesh hasn't faces or vertices, there are two cases
+ // possible: 1. the model is invalid. 2. This is a dummy
+ // helper object which we are going to remove later ...
+ if (mesh.mFaces.empty() || mesh.mPositions.empty()) {
+ return;
+ }
+
+ // convert vertices
+ p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size();
+ p_pcOut->mNumFaces = (unsigned int)mesh.mFaces.size();
+
+ // allocate enough storage for faces
+ p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+ // copy vertices
+ p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()];
+ memcpy(p_pcOut->mVertices,&mesh.mPositions[0],
+ mesh.mPositions.size() * sizeof(aiVector3D));
+
+ // copy normals
+ p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()];
+ memcpy(p_pcOut->mNormals,&mesh.mNormals[0],
+ mesh.mNormals.size() * sizeof(aiVector3D));
+
+ // copy texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+ if (!mesh.amTexCoords[c].empty()) {
+ p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()];
+ memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0],
+ mesh.amTexCoords[c].size() * sizeof(aiVector3D));
+
+ // setup the number of valid vertex components
+ p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+ }
+ }
+
+ // copy vertex colors
+ if (!mesh.mVertexColors.empty()) {
+ p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()];
+ memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0],
+ mesh.mVertexColors.size() * sizeof(aiColor4D));
+ }
+
+ // copy faces
+ for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace) {
+ p_pcOut->mFaces[iFace].mNumIndices = 3;
+ p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
+
+ // copy indices
+ p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
+ p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
+ p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
+ }
+
+ // copy vertex bones
+ if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty()) {
+ std::vector<std::vector<aiVertexWeight> > avBonesOut( mesh.mBones.size() );
+
+ // find all vertex weights for this bone
+ unsigned int quak = 0;
+ for (std::vector<BoneVertex>::const_iterator harrypotter = mesh.mBoneVertices.begin();
+ harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak) {
+
+ for (std::vector<std::pair<int,float> >::const_iterator
+ ronaldweasley = (*harrypotter).mBoneWeights.begin();
+ ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley)
+ {
+ aiVertexWeight weight;
+ weight.mVertexId = quak;
+ weight.mWeight = (*ronaldweasley).second;
+ avBonesOut[(*ronaldweasley).first].push_back(weight);
+ }
+ }
+
+ // now build a final bone list
+ p_pcOut->mNumBones = 0;
+ for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
+ if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
+
+ p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
+ aiBone** pcBone = p_pcOut->mBones;
+ for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) {
+ if (!avBonesOut[jfkennedy].empty()) {
+ aiBone* pc = *pcBone = new aiBone();
+ pc->mName.Set(mesh.mBones[jfkennedy].mName);
+ pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
+ pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+ ::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
+ sizeof(aiVertexWeight) * pc->mNumWeights);
+ ++pcBone;
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Setup proper material indices and build output materials
void ASEImporter::BuildMaterialIndices()
{
- ai_assert(NULL != pcScene);
-
- // iterate through all materials and check whether we need them
- for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
- {
- ASE::Material& mat = mParser->m_vMaterials[iMat];
- if (mat.bNeed) {
- // Convert it to the aiMaterial layout
- ConvertMaterial(mat);
- ++pcScene->mNumMaterials;
- }
- for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
- {
- ASE::Material& submat = mat.avSubMaterials[iSubMat];
- if (submat.bNeed) {
- // Convert it to the aiMaterial layout
- ConvertMaterial(submat);
- ++pcScene->mNumMaterials;
- }
- }
- }
-
- // allocate the output material array
- pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
- D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials];
-
- unsigned int iNum = 0;
- for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) {
- ASE::Material& mat = mParser->m_vMaterials[iMat];
- if (mat.bNeed)
- {
- ai_assert(NULL != mat.pcInstance);
- pcScene->mMaterials[iNum] = mat.pcInstance;
-
- // Store the internal material, too
- pcIntMaterials[iNum] = &mat;
-
- // Iterate through all meshes and search for one which is using
- // this top-level material index
- for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
- {
- aiMesh* mesh = pcScene->mMeshes[iMesh];
- if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
- iMat == (uintptr_t)mesh->mColors[3])
- {
- mesh->mMaterialIndex = iNum;
- mesh->mColors[3] = NULL;
- }
- }
- iNum++;
- }
- for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) {
- ASE::Material& submat = mat.avSubMaterials[iSubMat];
- if (submat.bNeed) {
- ai_assert(NULL != submat.pcInstance);
- pcScene->mMaterials[iNum] = submat.pcInstance;
-
- // Store the internal material, too
- pcIntMaterials[iNum] = &submat;
-
- // Iterate through all meshes and search for one which is using
- // this sub-level material index
- for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) {
- aiMesh* mesh = pcScene->mMeshes[iMesh];
-
- if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3]) {
- mesh->mMaterialIndex = iNum;
- mesh->mColors[3] = NULL;
- }
- }
- iNum++;
- }
- }
- }
-
- // Dekete our temporary array
- delete[] pcIntMaterials;
+ ai_assert(NULL != pcScene);
+
+ // iterate through all materials and check whether we need them
+ for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
+ {
+ ASE::Material& mat = mParser->m_vMaterials[iMat];
+ if (mat.bNeed) {
+ // Convert it to the aiMaterial layout
+ ConvertMaterial(mat);
+ ++pcScene->mNumMaterials;
+ }
+ for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
+ {
+ ASE::Material& submat = mat.avSubMaterials[iSubMat];
+ if (submat.bNeed) {
+ // Convert it to the aiMaterial layout
+ ConvertMaterial(submat);
+ ++pcScene->mNumMaterials;
+ }
+ }
+ }
+
+ // allocate the output material array
+ pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
+ D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials];
+
+ unsigned int iNum = 0;
+ for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) {
+ ASE::Material& mat = mParser->m_vMaterials[iMat];
+ if (mat.bNeed)
+ {
+ ai_assert(NULL != mat.pcInstance);
+ pcScene->mMaterials[iNum] = mat.pcInstance;
+
+ // Store the internal material, too
+ pcIntMaterials[iNum] = &mat;
+
+ // Iterate through all meshes and search for one which is using
+ // this top-level material index
+ for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
+ {
+ aiMesh* mesh = pcScene->mMeshes[iMesh];
+ if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
+ iMat == (uintptr_t)mesh->mColors[3])
+ {
+ mesh->mMaterialIndex = iNum;
+ mesh->mColors[3] = NULL;
+ }
+ }
+ iNum++;
+ }
+ for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) {
+ ASE::Material& submat = mat.avSubMaterials[iSubMat];
+ if (submat.bNeed) {
+ ai_assert(NULL != submat.pcInstance);
+ pcScene->mMaterials[iNum] = submat.pcInstance;
+
+ // Store the internal material, too
+ pcIntMaterials[iNum] = &submat;
+
+ // Iterate through all meshes and search for one which is using
+ // this sub-level material index
+ for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) {
+ aiMesh* mesh = pcScene->mMeshes[iMesh];
+
+ if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3]) {
+ mesh->mMaterialIndex = iNum;
+ mesh->mColors[3] = NULL;
+ }
+ }
+ iNum++;
+ }
+ }
+ }
+
+ // Dekete our temporary array
+ delete[] pcIntMaterials;
}
// ------------------------------------------------------------------------------------------------
// Generate normal vectors basing on smoothing groups
-bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) {
-
- if (!mesh.mNormals.empty() && !configRecomputeNormals)
- {
- // Check whether there are only uninitialized normals. If there are
- // some, skip all normals from the file and compute them on our own
- for (std::vector<aiVector3D>::const_iterator qq = mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) {
- if ((*qq).x || (*qq).y || (*qq).z)
- {
- return true;
- }
- }
- }
- // The array is reused.
- ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
- return false;
+bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) {
+
+ if (!mesh.mNormals.empty() && !configRecomputeNormals)
+ {
+ // Check whether there are only uninitialized normals. If there are
+ // some, skip all normals from the file and compute them on our own
+ for (std::vector<aiVector3D>::const_iterator qq = mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) {
+ if ((*qq).x || (*qq).y || (*qq).z)
+ {
+ return true;
+ }
+ }
+ }
+ // The array is reused.
+ ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
+ return false;
}
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ASELoader.h b/src/3rdparty/assimp/code/ASELoader.h
index 903376a3c..b775fc6bb 100644
--- a/src/3rdparty/assimp/code/ASELoader.h
+++ b/src/3rdparty/assimp/code/ASELoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_ASELOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
struct aiNode;
#include "ASEParser.h"
@@ -57,147 +57,147 @@ namespace Assimp {
/** Importer class for the 3DS ASE ASCII format.
*
*/
-class ASEImporter : public BaseImporter {
+class ASEImporter : public BaseImporter {
public:
- ASEImporter();
- ~ASEImporter();
+ ASEImporter();
+ ~ASEImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
private:
- // -------------------------------------------------------------------
- /** Generate normal vectors basing on smoothing groups
- * (in some cases the normal are already contained in the file)
- * \param mesh Mesh to work on
- * \return false if the normals have been recomputed
- */
- bool GenerateNormals(ASE::Mesh& mesh);
+ // -------------------------------------------------------------------
+ /** Generate normal vectors basing on smoothing groups
+ * (in some cases the normal are already contained in the file)
+ * \param mesh Mesh to work on
+ * \return false if the normals have been recomputed
+ */
+ bool GenerateNormals(ASE::Mesh& mesh);
- // -------------------------------------------------------------------
- /** Create valid vertex/normal/UV/color/face lists.
- * All elements are unique, faces have only one set of indices
- * after this step occurs.
- * \param mesh Mesh to work on
- */
- void BuildUniqueRepresentation(ASE::Mesh& mesh);
+ // -------------------------------------------------------------------
+ /** Create valid vertex/normal/UV/color/face lists.
+ * All elements are unique, faces have only one set of indices
+ * after this step occurs.
+ * \param mesh Mesh to work on
+ */
+ void BuildUniqueRepresentation(ASE::Mesh& mesh);
- /** Create one-material-per-mesh meshes ;-)
- * \param mesh Mesh to work with
- * \param Receives the list of all created meshes
- */
- void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
+ /** Create one-material-per-mesh meshes ;-)
+ * \param mesh Mesh to work with
+ * \param Receives the list of all created meshes
+ */
+ void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
- // -------------------------------------------------------------------
- /** Convert a material to a aiMaterial object
- * \param mat Input material
- */
- void ConvertMaterial(ASE::Material& mat);
+ // -------------------------------------------------------------------
+ /** Convert a material to a aiMaterial object
+ * \param mat Input material
+ */
+ void ConvertMaterial(ASE::Material& mat);
- // -------------------------------------------------------------------
- /** Setup the final material indices for each mesh
- */
- void BuildMaterialIndices();
+ // -------------------------------------------------------------------
+ /** Setup the final material indices for each mesh
+ */
+ void BuildMaterialIndices();
- // -------------------------------------------------------------------
- /** Build the node graph
- */
- void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
+ // -------------------------------------------------------------------
+ /** Build the node graph
+ */
+ void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
- // -------------------------------------------------------------------
- /** Build output cameras
- */
- void BuildCameras();
+ // -------------------------------------------------------------------
+ /** Build output cameras
+ */
+ void BuildCameras();
- // -------------------------------------------------------------------
- /** Build output lights
- */
- void BuildLights();
+ // -------------------------------------------------------------------
+ /** Build output lights
+ */
+ void BuildLights();
- // -------------------------------------------------------------------
- /** Build output animations
- */
- void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
+ // -------------------------------------------------------------------
+ /** Build output animations
+ */
+ void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
- // -------------------------------------------------------------------
- /** Add sub nodes to a node
- * \param pcParent parent node to be filled
- * \param szName Name of the parent node
- * \param matrix Current transform
- */
- void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
- aiNode* pcParent,const char* szName);
+ // -------------------------------------------------------------------
+ /** Add sub nodes to a node
+ * \param pcParent parent node to be filled
+ * \param szName Name of the parent node
+ * \param matrix Current transform
+ */
+ void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
+ aiNode* pcParent,const char* szName);
- void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
- aiNode* pcParent,const char* szName,
- const aiMatrix4x4& matrix);
+ void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
+ aiNode* pcParent,const char* szName,
+ const aiMatrix4x4& matrix);
- void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
+ void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
- // -------------------------------------------------------------------
- /** Generate a default material and add it to the parser's list
- * Called if no material has been found in the file (rare for ASE,
- * but not impossible)
- */
- void GenerateDefaultMaterial();
+ // -------------------------------------------------------------------
+ /** Generate a default material and add it to the parser's list
+ * Called if no material has been found in the file (rare for ASE,
+ * but not impossible)
+ */
+ void GenerateDefaultMaterial();
protected:
- /** Parser instance */
- ASE::Parser* mParser;
+ /** Parser instance */
+ ASE::Parser* mParser;
- /** Buffer to hold the loaded file */
- char* mBuffer;
+ /** Buffer to hold the loaded file */
+ char* mBuffer;
- /** Scene to be filled */
- aiScene* pcScene;
+ /** Scene to be filled */
+ aiScene* pcScene;
- /** Config options: Recompute the normals in every case - WA
- for 3DS Max broken ASE normal export */
- bool configRecomputeNormals;
- bool noSkeletonMesh;
+ /** Config options: Recompute the normals in every case - WA
+ for 3DS Max broken ASE normal export */
+ bool configRecomputeNormals;
+ bool noSkeletonMesh;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ASEParser.cpp b/src/3rdparty/assimp/code/ASEParser.cpp
index df505a445..204f8bf62 100644
--- a/src/3rdparty/assimp/code/ASEParser.cpp
+++ b/src/3rdparty/assimp/code/ASEParser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,25 +25,25 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file ASEParser.cpp
- * @brief Implementation of the ASE parser class
+ * @brief Implementation of the ASE parser class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
// internal headers
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ASELoader.h"
#include "MaterialSystem.h"
#include "fast_atof.h"
+#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
using namespace Assimp::ASE;
@@ -60,32 +61,32 @@ using namespace Assimp::ASE;
// Begin an ASE parsing function
#define AI_ASE_PARSER_INIT() \
- int iDepth = 0;
+ int iDepth = 0;
// ------------------------------------------------------------------------------------------------
// Handle a "top-level" section in the file. EOF is no error in this case.
#define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \
- else if ('{' == *filePtr)iDepth++; \
- else if ('}' == *filePtr) \
- { \
- if (0 == --iDepth) \
- { \
- ++filePtr; \
- SkipToNextToken(); \
- return; \
- } \
- } \
- else if ('\0' == *filePtr) \
- { \
- return; \
- } \
- if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
- { \
- ++iLineNumber; \
- bLastWasEndLine = true; \
- } else bLastWasEndLine = false; \
- ++filePtr;
+ else if ('{' == *filePtr)iDepth++; \
+ else if ('}' == *filePtr) \
+ { \
+ if (0 == --iDepth) \
+ { \
+ ++filePtr; \
+ SkipToNextToken(); \
+ return; \
+ } \
+ } \
+ else if ('\0' == *filePtr) \
+ { \
+ return; \
+ } \
+ if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
+ { \
+ ++iLineNumber; \
+ bLastWasEndLine = true; \
+ } else bLastWasEndLine = false; \
+ ++filePtr;
// ------------------------------------------------------------------------------------------------
// Handle a nested section in the file. EOF is an error in this case
@@ -93,2061 +94,2061 @@ using namespace Assimp::ASE;
// @param msg Full name of the section (including the asterisk)
#define AI_ASE_HANDLE_SECTION(level, msg) \
- if ('{' == *filePtr)iDepth++; \
- else if ('}' == *filePtr) \
- { \
- if (0 == --iDepth) \
- { \
- ++filePtr; \
- SkipToNextToken(); \
- return; \
- } \
- } \
- else if ('\0' == *filePtr) \
- { \
- LogError("Encountered unexpected EOL while parsing a " msg \
- " chunk (Level " level ")"); \
- } \
- if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
- { \
- ++iLineNumber; \
- bLastWasEndLine = true; \
- } else bLastWasEndLine = false; \
- ++filePtr;
+ if ('{' == *filePtr)iDepth++; \
+ else if ('}' == *filePtr) \
+ { \
+ if (0 == --iDepth) \
+ { \
+ ++filePtr; \
+ SkipToNextToken(); \
+ return; \
+ } \
+ } \
+ else if ('\0' == *filePtr) \
+ { \
+ LogError("Encountered unexpected EOL while parsing a " msg \
+ " chunk (Level " level ")"); \
+ } \
+ if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
+ { \
+ ++iLineNumber; \
+ bLastWasEndLine = true; \
+ } else bLastWasEndLine = false; \
+ ++filePtr;
// ------------------------------------------------------------------------------------------------
Parser::Parser (const char* szFile, unsigned int fileFormatDefault)
{
- ai_assert(NULL != szFile);
- filePtr = szFile;
- iFileFormat = fileFormatDefault;
-
- // make sure that the color values are invalid
- m_clrBackground.r = get_qnan();
- m_clrAmbient.r = get_qnan();
-
- // setup some default values
- iLineNumber = 0;
- iFirstFrame = 0;
- iLastFrame = 0;
- iFrameSpeed = 30; // use 30 as default value for this property
- iTicksPerFrame = 1; // use 1 as default value for this property
- bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
+ ai_assert(NULL != szFile);
+ filePtr = szFile;
+ iFileFormat = fileFormatDefault;
+
+ // make sure that the color values are invalid
+ m_clrBackground.r = get_qnan();
+ m_clrAmbient.r = get_qnan();
+
+ // setup some default values
+ iLineNumber = 0;
+ iFirstFrame = 0;
+ iLastFrame = 0;
+ iFrameSpeed = 30; // use 30 as default value for this property
+ iTicksPerFrame = 1; // use 1 as default value for this property
+ bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
}
// ------------------------------------------------------------------------------------------------
void Parser::LogWarning(const char* szWarn)
{
- ai_assert(NULL != szWarn);
+ ai_assert(NULL != szWarn);
- char szTemp[1024];
+ char szTemp[1024];
#if _MSC_VER >= 1400
- sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+ sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn);
#else
- snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+ ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif
- // output the warning to the logger ...
- DefaultLogger::get()->warn(szTemp);
+ // output the warning to the logger ...
+ DefaultLogger::get()->warn(szTemp);
}
// ------------------------------------------------------------------------------------------------
void Parser::LogInfo(const char* szWarn)
{
- ai_assert(NULL != szWarn);
+ ai_assert(NULL != szWarn);
- char szTemp[1024];
+ char szTemp[1024];
#if _MSC_VER >= 1400
- sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+ sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
#else
- snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+ ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif
- // output the information to the logger ...
- DefaultLogger::get()->info(szTemp);
+ // output the information to the logger ...
+ DefaultLogger::get()->info(szTemp);
}
// ------------------------------------------------------------------------------------------------
-void Parser::LogError(const char* szWarn)
+AI_WONT_RETURN void Parser::LogError(const char* szWarn)
{
- ai_assert(NULL != szWarn);
+ ai_assert(NULL != szWarn);
- char szTemp[1024];
+ char szTemp[1024];
#if _MSC_VER >= 1400
- sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+ sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
#else
- snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+ ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif
- // throw an exception
- throw DeadlyImportError(szTemp);
+ // throw an exception
+ throw DeadlyImportError(szTemp);
}
// ------------------------------------------------------------------------------------------------
bool Parser::SkipToNextToken()
{
- while (true)
- {
- char me = *filePtr;
-
- // increase the line number counter if necessary
- if (IsLineEnd(me) && !bLastWasEndLine)
- {
- ++iLineNumber;
- bLastWasEndLine = true;
- }
- else bLastWasEndLine = false;
- if ('*' == me || '}' == me || '{' == me)return true;
- if ('\0' == me)return false;
-
- ++filePtr;
- }
+ while (true)
+ {
+ char me = *filePtr;
+
+ // increase the line number counter if necessary
+ if (IsLineEnd(me) && !bLastWasEndLine)
+ {
+ ++iLineNumber;
+ bLastWasEndLine = true;
+ }
+ else bLastWasEndLine = false;
+ if ('*' == me || '}' == me || '{' == me)return true;
+ if ('\0' == me)return false;
+
+ ++filePtr;
+ }
}
// ------------------------------------------------------------------------------------------------
bool Parser::SkipSection()
{
- // must handle subsections ...
- int iCnt = 0;
- while (true)
- {
- if ('}' == *filePtr)
- {
- --iCnt;
- if (0 == iCnt)
- {
- // go to the next valid token ...
- ++filePtr;
- SkipToNextToken();
- return true;
- }
- }
- else if ('{' == *filePtr)
- {
- ++iCnt;
- }
- else if ('\0' == *filePtr)
- {
- LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
- return false;
- }
- else if(IsLineEnd(*filePtr))++iLineNumber;
- ++filePtr;
- }
+ // must handle subsections ...
+ int iCnt = 0;
+ while (true)
+ {
+ if ('}' == *filePtr)
+ {
+ --iCnt;
+ if (0 == iCnt)
+ {
+ // go to the next valid token ...
+ ++filePtr;
+ SkipToNextToken();
+ return true;
+ }
+ }
+ else if ('{' == *filePtr)
+ {
+ ++iCnt;
+ }
+ else if ('\0' == *filePtr)
+ {
+ LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
+ return false;
+ }
+ else if(IsLineEnd(*filePtr))++iLineNumber;
+ ++filePtr;
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::Parse()
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Version should be 200. Validate this ...
- if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
- {
- unsigned int fmt;
- ParseLV4MeshLong(fmt);
-
- if (fmt > 200)
- {
- LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
- be <= 200");
- }
- // *************************************************************
- // - fmt will be 0 if we're unable to read the version number
- // there are some faulty files without a version number ...
- // in this case we'll guess the exact file format by looking
- // at the file extension (ASE, ASK, ASC)
- // *************************************************************
-
- if (fmt)iFileFormat = fmt;
- continue;
- }
- // main scene information
- if (TokenMatch(filePtr,"SCENE",5))
- {
- ParseLV1SceneBlock();
- continue;
- }
- // "group" - no implementation yet, in facte
- // we're just ignoring them for the moment
- if (TokenMatch(filePtr,"GROUP",5))
- {
- Parse();
- continue;
- }
- // material list
- if (TokenMatch(filePtr,"MATERIAL_LIST",13))
- {
- ParseLV1MaterialListBlock();
- continue;
- }
- // geometric object (mesh)
- if (TokenMatch(filePtr,"GEOMOBJECT",10))
-
- {
- m_vMeshes.push_back(Mesh());
- ParseLV1ObjectBlock(m_vMeshes.back());
- continue;
- }
- // helper object = dummy in the hierarchy
- if (TokenMatch(filePtr,"HELPEROBJECT",12))
-
- {
- m_vDummies.push_back(Dummy());
- ParseLV1ObjectBlock(m_vDummies.back());
- continue;
- }
- // light object
- if (TokenMatch(filePtr,"LIGHTOBJECT",11))
-
- {
- m_vLights.push_back(Light());
- ParseLV1ObjectBlock(m_vLights.back());
- continue;
- }
- // camera object
- if (TokenMatch(filePtr,"CAMERAOBJECT",12))
- {
- m_vCameras.push_back(Camera());
- ParseLV1ObjectBlock(m_vCameras.back());
- continue;
- }
- // comment - print it on the console
- if (TokenMatch(filePtr,"COMMENT",7))
- {
- std::string out = "<unknown>";
- ParseString(out,"*COMMENT");
- LogInfo(("Comment: " + out).c_str());
- continue;
- }
- // ASC bone weights
- if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18))
- {
- ParseLV1SoftSkinBlock();
- }
- }
- AI_ASE_HANDLE_TOP_LEVEL_SECTION();
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Version should be 200. Validate this ...
+ if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
+ {
+ unsigned int fmt;
+ ParseLV4MeshLong(fmt);
+
+ if (fmt > 200)
+ {
+ LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
+ be <= 200");
+ }
+ // *************************************************************
+ // - fmt will be 0 if we're unable to read the version number
+ // there are some faulty files without a version number ...
+ // in this case we'll guess the exact file format by looking
+ // at the file extension (ASE, ASK, ASC)
+ // *************************************************************
+
+ if (fmt)iFileFormat = fmt;
+ continue;
+ }
+ // main scene information
+ if (TokenMatch(filePtr,"SCENE",5))
+ {
+ ParseLV1SceneBlock();
+ continue;
+ }
+ // "group" - no implementation yet, in facte
+ // we're just ignoring them for the moment
+ if (TokenMatch(filePtr,"GROUP",5))
+ {
+ Parse();
+ continue;
+ }
+ // material list
+ if (TokenMatch(filePtr,"MATERIAL_LIST",13))
+ {
+ ParseLV1MaterialListBlock();
+ continue;
+ }
+ // geometric object (mesh)
+ if (TokenMatch(filePtr,"GEOMOBJECT",10))
+
+ {
+ m_vMeshes.push_back(Mesh());
+ ParseLV1ObjectBlock(m_vMeshes.back());
+ continue;
+ }
+ // helper object = dummy in the hierarchy
+ if (TokenMatch(filePtr,"HELPEROBJECT",12))
+
+ {
+ m_vDummies.push_back(Dummy());
+ ParseLV1ObjectBlock(m_vDummies.back());
+ continue;
+ }
+ // light object
+ if (TokenMatch(filePtr,"LIGHTOBJECT",11))
+
+ {
+ m_vLights.push_back(Light());
+ ParseLV1ObjectBlock(m_vLights.back());
+ continue;
+ }
+ // camera object
+ if (TokenMatch(filePtr,"CAMERAOBJECT",12))
+ {
+ m_vCameras.push_back(Camera());
+ ParseLV1ObjectBlock(m_vCameras.back());
+ continue;
+ }
+ // comment - print it on the console
+ if (TokenMatch(filePtr,"COMMENT",7))
+ {
+ std::string out = "<unknown>";
+ ParseString(out,"*COMMENT");
+ LogInfo(("Comment: " + out).c_str());
+ continue;
+ }
+ // ASC bone weights
+ if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18))
+ {
+ ParseLV1SoftSkinBlock();
+ }
+ }
+ AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV1SoftSkinBlock()
{
- // TODO: fix line counting here
-
- // **************************************************************
- // The soft skin block is formatted differently. There are no
- // nested sections supported and the single elements aren't
- // marked by keywords starting with an asterisk.
-
- /**
- FORMAT BEGIN
-
- *MESH_SOFTSKINVERTS {
- <nodename>
- <number of vertices>
-
- [for <number of vertices> times:]
- <number of weights> [for <number of weights> times:] <bone name> <weight>
- }
-
- FORMAT END
- */
- // **************************************************************
- while (true)
- {
- if (*filePtr == '}' ) {++filePtr;return;}
- else if (*filePtr == '\0') return;
- else if (*filePtr == '{' ) ++filePtr;
-
- else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
- {
- ASE::Mesh* curMesh = NULL;
- unsigned int numVerts = 0;
-
- const char* sz = filePtr;
- while (!IsSpaceOrNewLine(*filePtr))++filePtr;
-
- const unsigned int diff = (unsigned int)(filePtr-sz);
- if (diff)
- {
- std::string name = std::string(sz,diff);
- for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
- it != m_vMeshes.end(); ++it)
- {
- if ((*it).mName == name)
- {
- curMesh = & (*it);
- break;
- }
- }
- if (!curMesh)
- {
- LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
-
- // Skip the mesh data - until we find a new mesh
- // or the end of the *MESH_SOFTSKINVERTS section
- while (true)
- {
- SkipSpacesAndLineEnd(&filePtr);
- if (*filePtr == '}')
- {++filePtr;return;}
- else if (!IsNumeric(*filePtr))
- break;
-
- SkipLine(&filePtr);
- }
- }
- else
- {
- SkipSpacesAndLineEnd(&filePtr);
- ParseLV4MeshLong(numVerts);
-
- // Reserve enough storage
- curMesh->mBoneVertices.reserve(numVerts);
-
- for (unsigned int i = 0; i < numVerts;++i)
- {
- SkipSpacesAndLineEnd(&filePtr);
- unsigned int numWeights;
- ParseLV4MeshLong(numWeights);
-
- curMesh->mBoneVertices.push_back(ASE::BoneVertex());
- ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
-
- // Reserve enough storage
- vert.mBoneWeights.reserve(numWeights);
-
- for (unsigned int w = 0; w < numWeights;++w)
- {
- std::string bone;
- ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
-
- // Find the bone in the mesh's list
- std::pair<int,float> me;
- me.first = -1;
-
- for (unsigned int n = 0; n < curMesh->mBones.size();++n)
- {
- if (curMesh->mBones[n].mName == bone)
- {
- me.first = n;
- break;
- }
- }
- if (-1 == me.first)
- {
- // We don't have this bone yet, so add it to the list
- me.first = (int)curMesh->mBones.size();
- curMesh->mBones.push_back(ASE::Bone(bone));
- }
- ParseLV4MeshFloat( me.second );
-
- // Add the new bone weight to list
- vert.mBoneWeights.push_back(me);
- }
- }
- }
- }
- }
- ++filePtr;
- SkipSpacesAndLineEnd(&filePtr);
- }
+ // TODO: fix line counting here
+
+ // **************************************************************
+ // The soft skin block is formatted differently. There are no
+ // nested sections supported and the single elements aren't
+ // marked by keywords starting with an asterisk.
+
+ /**
+ FORMAT BEGIN
+
+ *MESH_SOFTSKINVERTS {
+ <nodename>
+ <number of vertices>
+
+ [for <number of vertices> times:]
+ <number of weights> [for <number of weights> times:] <bone name> <weight>
+ }
+
+ FORMAT END
+ */
+ // **************************************************************
+ while (true)
+ {
+ if (*filePtr == '}' ) {++filePtr;return;}
+ else if (*filePtr == '\0') return;
+ else if (*filePtr == '{' ) ++filePtr;
+
+ else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
+ {
+ ASE::Mesh* curMesh = NULL;
+ unsigned int numVerts = 0;
+
+ const char* sz = filePtr;
+ while (!IsSpaceOrNewLine(*filePtr))++filePtr;
+
+ const unsigned int diff = (unsigned int)(filePtr-sz);
+ if (diff)
+ {
+ std::string name = std::string(sz,diff);
+ for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
+ it != m_vMeshes.end(); ++it)
+ {
+ if ((*it).mName == name)
+ {
+ curMesh = & (*it);
+ break;
+ }
+ }
+ if (!curMesh)
+ {
+ LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
+
+ // Skip the mesh data - until we find a new mesh
+ // or the end of the *MESH_SOFTSKINVERTS section
+ while (true)
+ {
+ SkipSpacesAndLineEnd(&filePtr);
+ if (*filePtr == '}')
+ {++filePtr;return;}
+ else if (!IsNumeric(*filePtr))
+ break;
+
+ SkipLine(&filePtr);
+ }
+ }
+ else
+ {
+ SkipSpacesAndLineEnd(&filePtr);
+ ParseLV4MeshLong(numVerts);
+
+ // Reserve enough storage
+ curMesh->mBoneVertices.reserve(numVerts);
+
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ SkipSpacesAndLineEnd(&filePtr);
+ unsigned int numWeights;
+ ParseLV4MeshLong(numWeights);
+
+ curMesh->mBoneVertices.push_back(ASE::BoneVertex());
+ ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
+
+ // Reserve enough storage
+ vert.mBoneWeights.reserve(numWeights);
+
+ for (unsigned int w = 0; w < numWeights;++w)
+ {
+ std::string bone;
+ ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
+
+ // Find the bone in the mesh's list
+ std::pair<int,float> me;
+ me.first = -1;
+
+ for (unsigned int n = 0; n < curMesh->mBones.size();++n)
+ {
+ if (curMesh->mBones[n].mName == bone)
+ {
+ me.first = n;
+ break;
+ }
+ }
+ if (-1 == me.first)
+ {
+ // We don't have this bone yet, so add it to the list
+ me.first = (int)curMesh->mBones.size();
+ curMesh->mBones.push_back(ASE::Bone(bone));
+ }
+ ParseLV4MeshFloat( me.second );
+
+ // Add the new bone weight to list
+ vert.mBoneWeights.push_back(me);
+ }
+ }
+ }
+ }
+ }
+ ++filePtr;
+ SkipSpacesAndLineEnd(&filePtr);
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV1SceneBlock()
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23))
-
- {
- // parse a color triple and assume it is really the bg color
- ParseLV4MeshFloatTriple( &m_clrBackground.r );
- continue;
- }
- if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20))
-
- {
- // parse a color triple and assume it is really the bg color
- ParseLV4MeshFloatTriple( &m_clrAmbient.r );
- continue;
- }
- if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16))
- {
- ParseLV4MeshLong(iFirstFrame);
- continue;
- }
- if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
- {
- ParseLV4MeshLong(iLastFrame);
- continue;
- }
- if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16))
- {
- ParseLV4MeshLong(iFrameSpeed);
- continue;
- }
- if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
- {
- ParseLV4MeshLong(iTicksPerFrame);
- continue;
- }
- }
- AI_ASE_HANDLE_TOP_LEVEL_SECTION();
- }
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23))
+
+ {
+ // parse a color triple and assume it is really the bg color
+ ParseLV4MeshFloatTriple( &m_clrBackground.r );
+ continue;
+ }
+ if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20))
+
+ {
+ // parse a color triple and assume it is really the bg color
+ ParseLV4MeshFloatTriple( &m_clrAmbient.r );
+ continue;
+ }
+ if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16))
+ {
+ ParseLV4MeshLong(iFirstFrame);
+ continue;
+ }
+ if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
+ {
+ ParseLV4MeshLong(iLastFrame);
+ continue;
+ }
+ if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16))
+ {
+ ParseLV4MeshLong(iFrameSpeed);
+ continue;
+ }
+ if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
+ {
+ ParseLV4MeshLong(iTicksPerFrame);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV1MaterialListBlock()
{
- AI_ASE_PARSER_INIT();
-
- unsigned int iMaterialCount = 0;
- unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
- {
- ParseLV4MeshLong(iMaterialCount);
-
- // now allocate enough storage to hold all materials
- m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
- continue;
- }
- if (TokenMatch(filePtr,"MATERIAL",8))
- {
- unsigned int iIndex = 0;
- ParseLV4MeshLong(iIndex);
-
- if (iIndex >= iMaterialCount)
- {
- LogWarning("Out of range: material index is too large");
- iIndex = iMaterialCount-1;
- }
-
- // get a reference to the material
- Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
- // parse the material block
- ParseLV2MaterialBlock(sMat);
- continue;
- }
- }
- AI_ASE_HANDLE_TOP_LEVEL_SECTION();
- }
+ AI_ASE_PARSER_INIT();
+
+ unsigned int iMaterialCount = 0;
+ unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
+ {
+ ParseLV4MeshLong(iMaterialCount);
+
+ // now allocate enough storage to hold all materials
+ m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
+ continue;
+ }
+ if (TokenMatch(filePtr,"MATERIAL",8))
+ {
+ unsigned int iIndex = 0;
+ ParseLV4MeshLong(iIndex);
+
+ if (iIndex >= iMaterialCount)
+ {
+ LogWarning("Out of range: material index is too large");
+ iIndex = iMaterialCount-1;
+ }
+
+ // get a reference to the material
+ Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
+ // parse the material block
+ ParseLV2MaterialBlock(sMat);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
{
- AI_ASE_PARSER_INIT();
-
- unsigned int iNumSubMaterials = 0;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"MATERIAL_NAME",13))
- {
- if (!ParseString(mat.mName,"*MATERIAL_NAME"))
- SkipToNextToken();
- continue;
- }
- // ambient material color
- if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
- {
- ParseLV4MeshFloatTriple(&mat.mAmbient.r);
- continue;
- }
- // diffuse material color
- if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
- {
- ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
- continue;
- }
- // specular material color
- if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
- {
- ParseLV4MeshFloatTriple(&mat.mSpecular.r);
- continue;
- }
- // material shading type
- if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
- {
- if (TokenMatch(filePtr,"Blinn",5))
- {
- mat.mShading = Discreet3DS::Blinn;
- }
- else if (TokenMatch(filePtr,"Phong",5))
- {
- mat.mShading = Discreet3DS::Phong;
- }
- else if (TokenMatch(filePtr,"Flat",4))
- {
- mat.mShading = Discreet3DS::Flat;
- }
- else if (TokenMatch(filePtr,"Wire",4))
- {
- mat.mShading = Discreet3DS::Wire;
- }
- else
- {
- // assume gouraud shading
- mat.mShading = Discreet3DS::Gouraud;
- SkipToNextToken();
- }
- continue;
- }
- // material transparency
- if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
- {
- ParseLV4MeshFloat(mat.mTransparency);
- mat.mTransparency = 1.0f - mat.mTransparency;continue;
- }
- // material self illumination
- if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
- {
- float f = 0.0f;
- ParseLV4MeshFloat(f);
-
- mat.mEmissive.r = f;
- mat.mEmissive.g = f;
- mat.mEmissive.b = f;
- continue;
- }
- // material shininess
- if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
- {
- ParseLV4MeshFloat(mat.mSpecularExponent);
- mat.mSpecularExponent *= 15;
- continue;
- }
- // two-sided material
- if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
- {
- mat.mTwoSided = true;
- continue;
- }
- // material shininess strength
- if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
- {
- ParseLV4MeshFloat(mat.mShininessStrength);
- continue;
- }
- // diffuse color map
- if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexDiffuse);
- continue;
- }
- // ambient color map
- if (TokenMatch(filePtr,"MAP_AMBIENT",11))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexAmbient);
- continue;
- }
- // specular color map
- if (TokenMatch(filePtr,"MAP_SPECULAR",12))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexSpecular);
- continue;
- }
- // opacity map
- if (TokenMatch(filePtr,"MAP_OPACITY",11))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexOpacity);
- continue;
- }
- // emissive map
- if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexEmissive);
- continue;
- }
- // bump map
- if (TokenMatch(filePtr,"MAP_BUMP",8))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexBump);
- }
- // specular/shininess map
- if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
- {
- // parse the texture block
- ParseLV3MapBlock(mat.sTexShininess);
- continue;
- }
- // number of submaterials
- if (TokenMatch(filePtr,"NUMSUBMTLS",10))
- {
- ParseLV4MeshLong(iNumSubMaterials);
-
- // allocate enough storage
- mat.avSubMaterials.resize(iNumSubMaterials);
- }
- // submaterial chunks
- if (TokenMatch(filePtr,"SUBMATERIAL",11))
- {
-
- unsigned int iIndex = 0;
- ParseLV4MeshLong(iIndex);
-
- if (iIndex >= iNumSubMaterials)
- {
- LogWarning("Out of range: submaterial index is too large");
- iIndex = iNumSubMaterials-1;
- }
-
- // get a reference to the material
- Material& sMat = mat.avSubMaterials[iIndex];
-
- // parse the material block
- ParseLV2MaterialBlock(sMat);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("2","*MATERIAL");
- }
+ AI_ASE_PARSER_INIT();
+
+ unsigned int iNumSubMaterials = 0;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"MATERIAL_NAME",13))
+ {
+ if (!ParseString(mat.mName,"*MATERIAL_NAME"))
+ SkipToNextToken();
+ continue;
+ }
+ // ambient material color
+ if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
+ {
+ ParseLV4MeshFloatTriple(&mat.mAmbient.r);
+ continue;
+ }
+ // diffuse material color
+ if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
+ {
+ ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
+ continue;
+ }
+ // specular material color
+ if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
+ {
+ ParseLV4MeshFloatTriple(&mat.mSpecular.r);
+ continue;
+ }
+ // material shading type
+ if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
+ {
+ if (TokenMatch(filePtr,"Blinn",5))
+ {
+ mat.mShading = Discreet3DS::Blinn;
+ }
+ else if (TokenMatch(filePtr,"Phong",5))
+ {
+ mat.mShading = Discreet3DS::Phong;
+ }
+ else if (TokenMatch(filePtr,"Flat",4))
+ {
+ mat.mShading = Discreet3DS::Flat;
+ }
+ else if (TokenMatch(filePtr,"Wire",4))
+ {
+ mat.mShading = Discreet3DS::Wire;
+ }
+ else
+ {
+ // assume gouraud shading
+ mat.mShading = Discreet3DS::Gouraud;
+ SkipToNextToken();
+ }
+ continue;
+ }
+ // material transparency
+ if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
+ {
+ ParseLV4MeshFloat(mat.mTransparency);
+ mat.mTransparency = 1.0f - mat.mTransparency;continue;
+ }
+ // material self illumination
+ if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
+ {
+ float f = 0.0f;
+ ParseLV4MeshFloat(f);
+
+ mat.mEmissive.r = f;
+ mat.mEmissive.g = f;
+ mat.mEmissive.b = f;
+ continue;
+ }
+ // material shininess
+ if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
+ {
+ ParseLV4MeshFloat(mat.mSpecularExponent);
+ mat.mSpecularExponent *= 15;
+ continue;
+ }
+ // two-sided material
+ if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
+ {
+ mat.mTwoSided = true;
+ continue;
+ }
+ // material shininess strength
+ if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
+ {
+ ParseLV4MeshFloat(mat.mShininessStrength);
+ continue;
+ }
+ // diffuse color map
+ if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexDiffuse);
+ continue;
+ }
+ // ambient color map
+ if (TokenMatch(filePtr,"MAP_AMBIENT",11))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexAmbient);
+ continue;
+ }
+ // specular color map
+ if (TokenMatch(filePtr,"MAP_SPECULAR",12))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexSpecular);
+ continue;
+ }
+ // opacity map
+ if (TokenMatch(filePtr,"MAP_OPACITY",11))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexOpacity);
+ continue;
+ }
+ // emissive map
+ if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexEmissive);
+ continue;
+ }
+ // bump map
+ if (TokenMatch(filePtr,"MAP_BUMP",8))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexBump);
+ }
+ // specular/shininess map
+ if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
+ {
+ // parse the texture block
+ ParseLV3MapBlock(mat.sTexShininess);
+ continue;
+ }
+ // number of submaterials
+ if (TokenMatch(filePtr,"NUMSUBMTLS",10))
+ {
+ ParseLV4MeshLong(iNumSubMaterials);
+
+ // allocate enough storage
+ mat.avSubMaterials.resize(iNumSubMaterials);
+ }
+ // submaterial chunks
+ if (TokenMatch(filePtr,"SUBMATERIAL",11))
+ {
+
+ unsigned int iIndex = 0;
+ ParseLV4MeshLong(iIndex);
+
+ if (iIndex >= iNumSubMaterials)
+ {
+ LogWarning("Out of range: submaterial index is too large");
+ iIndex = iNumSubMaterials-1;
+ }
+
+ // get a reference to the material
+ Material& sMat = mat.avSubMaterials[iIndex];
+
+ // parse the material block
+ ParseLV2MaterialBlock(sMat);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","*MATERIAL");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MapBlock(Texture& map)
{
- AI_ASE_PARSER_INIT();
-
- // ***********************************************************
- // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
- // but we need to expect that case ... if the path is
- // empty the texture won't be used later.
- // ***********************************************************
- bool parsePath = true;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- // type of map
- if (TokenMatch(filePtr,"MAP_CLASS" ,9))
- {
- std::string temp;
- if(!ParseString(temp,"*MAP_CLASS"))
- SkipToNextToken();
- if (temp != "Bitmap" && temp != "Normal Bump")
- {
- DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
- parsePath = false;
- }
- continue;
- }
- // path to the texture
- if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
- {
- if(!ParseString(map.mMapName,"*BITMAP"))
- SkipToNextToken();
-
- if (map.mMapName == "None")
- {
- // Files with 'None' as map name are produced by
- // an Maja to ASE exporter which name I forgot ..
- DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
- map.mMapName = "";
- }
-
- continue;
- }
- // offset on the u axis
- if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
- {
- ParseLV4MeshFloat(map.mOffsetU);
- continue;
- }
- // offset on the v axis
- if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
- {
- ParseLV4MeshFloat(map.mOffsetV);
- continue;
- }
- // tiling on the u axis
- if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
- {
- ParseLV4MeshFloat(map.mScaleU);
- continue;
- }
- // tiling on the v axis
- if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
- {
- ParseLV4MeshFloat(map.mScaleV);
- continue;
- }
- // rotation around the z-axis
- if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
- {
- ParseLV4MeshFloat(map.mRotation);
- continue;
- }
- // map blending factor
- if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
- {
- ParseLV4MeshFloat(map.mTextureBlend);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // ***********************************************************
+ // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
+ // but we need to expect that case ... if the path is
+ // empty the texture won't be used later.
+ // ***********************************************************
+ bool parsePath = true;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ // type of map
+ if (TokenMatch(filePtr,"MAP_CLASS" ,9))
+ {
+ std::string temp;
+ if(!ParseString(temp,"*MAP_CLASS"))
+ SkipToNextToken();
+ if (temp != "Bitmap" && temp != "Normal Bump")
+ {
+ DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
+ parsePath = false;
+ }
+ continue;
+ }
+ // path to the texture
+ if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
+ {
+ if(!ParseString(map.mMapName,"*BITMAP"))
+ SkipToNextToken();
+
+ if (map.mMapName == "None")
+ {
+ // Files with 'None' as map name are produced by
+ // an Maja to ASE exporter which name I forgot ..
+ DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
+ map.mMapName = "";
+ }
+
+ continue;
+ }
+ // offset on the u axis
+ if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
+ {
+ ParseLV4MeshFloat(map.mOffsetU);
+ continue;
+ }
+ // offset on the v axis
+ if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
+ {
+ ParseLV4MeshFloat(map.mOffsetV);
+ continue;
+ }
+ // tiling on the u axis
+ if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
+ {
+ ParseLV4MeshFloat(map.mScaleU);
+ continue;
+ }
+ // tiling on the v axis
+ if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
+ {
+ ParseLV4MeshFloat(map.mScaleV);
+ continue;
+ }
+ // rotation around the z-axis
+ if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
+ {
+ ParseLV4MeshFloat(map.mRotation);
+ continue;
+ }
+ // map blending factor
+ if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
+ {
+ ParseLV4MeshFloat(map.mTextureBlend);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
bool Parser::ParseString(std::string& out,const char* szName)
{
- char szBuffer[1024];
- if (!SkipSpaces(&filePtr))
- {
-
- sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
- LogWarning(szBuffer);
- return false;
- }
- // there must be '"'
- if ('\"' != *filePtr)
- {
-
- sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
- "to be enclosed in double quotation marks",szName);
- LogWarning(szBuffer);
- return false;
- }
- ++filePtr;
- const char* sz = filePtr;
- while (true)
- {
- if ('\"' == *sz)break;
- else if ('\0' == *sz)
- {
- sprintf(szBuffer,"Unable to parse %s block: Strings are expected to "
- "be enclosed in double quotation marks but EOF was reached before "
- "a closing quotation mark was encountered",szName);
- LogWarning(szBuffer);
- return false;
- }
- sz++;
- }
- out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
- filePtr = sz+1;
- return true;
+ char szBuffer[1024];
+ if (!SkipSpaces(&filePtr))
+ {
+
+ ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL",szName);
+ LogWarning(szBuffer);
+ return false;
+ }
+ // there must be '"'
+ if ('\"' != *filePtr)
+ {
+
+ ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected "
+ "to be enclosed in double quotation marks",szName);
+ LogWarning(szBuffer);
+ return false;
+ }
+ ++filePtr;
+ const char* sz = filePtr;
+ while (true)
+ {
+ if ('\"' == *sz)break;
+ else if ('\0' == *sz)
+ {
+ ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected to "
+ "be enclosed in double quotation marks but EOF was reached before "
+ "a closing quotation mark was encountered",szName);
+ LogWarning(szBuffer);
+ return false;
+ }
+ sz++;
+ }
+ out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
+ filePtr = sz+1;
+ return true;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node)
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // first process common tokens such as node name and transform
- // name of the mesh/node
- if (TokenMatch(filePtr,"NODE_NAME" ,9))
- {
- if(!ParseString(node.mName,"*NODE_NAME"))
- SkipToNextToken();
- continue;
- }
- // name of the parent of the node
- if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
- {
- if(!ParseString(node.mParent,"*NODE_PARENT"))
- SkipToNextToken();
- continue;
- }
- // transformation matrix of the node
- if (TokenMatch(filePtr,"NODE_TM" ,7))
- {
- ParseLV2NodeTransformBlock(node);
- continue;
- }
- // animation data of the node
- if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
- {
- ParseLV2AnimationBlock(node);
- continue;
- }
-
- if (node.mType == BaseNode::Light)
- {
- // light settings
- if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
- {
- ParseLV2LightSettingsBlock((ASE::Light&)node);
- continue;
- }
- // type of the light source
- if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
- {
- if (!ASSIMP_strincmp("omni",filePtr,4))
- {
- ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
- }
- else if (!ASSIMP_strincmp("target",filePtr,6))
- {
- ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
- }
- else if (!ASSIMP_strincmp("free",filePtr,4))
- {
- ((ASE::Light&)node).mLightType = ASE::Light::FREE;
- }
- else if (!ASSIMP_strincmp("directional",filePtr,11))
- {
- ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
- }
- else
- {
- LogWarning("Unknown kind of light source");
- }
- continue;
- }
- }
- else if (node.mType == BaseNode::Camera)
- {
- // Camera settings
- if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
- {
- ParseLV2CameraSettingsBlock((ASE::Camera&)node);
- continue;
- }
- else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
- {
- if (!ASSIMP_strincmp("target",filePtr,6))
- {
- ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
- }
- else if (!ASSIMP_strincmp("free",filePtr,4))
- {
- ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
- }
- else
- {
- LogWarning("Unknown kind of camera");
- }
- continue;
- }
- }
- else if (node.mType == BaseNode::Mesh)
- {
- // mesh data
- // FIX: Older files use MESH_SOFTSKIN
- if (TokenMatch(filePtr,"MESH" ,4) ||
- TokenMatch(filePtr,"MESH_SOFTSKIN",13))
- {
- ParseLV2MeshBlock((ASE::Mesh&)node);
- continue;
- }
- // mesh material index
- if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
- {
- ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
- continue;
- }
- }
- }
- AI_ASE_HANDLE_TOP_LEVEL_SECTION();
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // first process common tokens such as node name and transform
+ // name of the mesh/node
+ if (TokenMatch(filePtr,"NODE_NAME" ,9))
+ {
+ if(!ParseString(node.mName,"*NODE_NAME"))
+ SkipToNextToken();
+ continue;
+ }
+ // name of the parent of the node
+ if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
+ {
+ if(!ParseString(node.mParent,"*NODE_PARENT"))
+ SkipToNextToken();
+ continue;
+ }
+ // transformation matrix of the node
+ if (TokenMatch(filePtr,"NODE_TM" ,7))
+ {
+ ParseLV2NodeTransformBlock(node);
+ continue;
+ }
+ // animation data of the node
+ if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
+ {
+ ParseLV2AnimationBlock(node);
+ continue;
+ }
+
+ if (node.mType == BaseNode::Light)
+ {
+ // light settings
+ if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
+ {
+ ParseLV2LightSettingsBlock((ASE::Light&)node);
+ continue;
+ }
+ // type of the light source
+ if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
+ {
+ if (!ASSIMP_strincmp("omni",filePtr,4))
+ {
+ ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
+ }
+ else if (!ASSIMP_strincmp("target",filePtr,6))
+ {
+ ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
+ }
+ else if (!ASSIMP_strincmp("free",filePtr,4))
+ {
+ ((ASE::Light&)node).mLightType = ASE::Light::FREE;
+ }
+ else if (!ASSIMP_strincmp("directional",filePtr,11))
+ {
+ ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
+ }
+ else
+ {
+ LogWarning("Unknown kind of light source");
+ }
+ continue;
+ }
+ }
+ else if (node.mType == BaseNode::Camera)
+ {
+ // Camera settings
+ if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
+ {
+ ParseLV2CameraSettingsBlock((ASE::Camera&)node);
+ continue;
+ }
+ else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
+ {
+ if (!ASSIMP_strincmp("target",filePtr,6))
+ {
+ ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
+ }
+ else if (!ASSIMP_strincmp("free",filePtr,4))
+ {
+ ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
+ }
+ else
+ {
+ LogWarning("Unknown kind of camera");
+ }
+ continue;
+ }
+ }
+ else if (node.mType == BaseNode::Mesh)
+ {
+ // mesh data
+ // FIX: Older files use MESH_SOFTSKIN
+ if (TokenMatch(filePtr,"MESH" ,4) ||
+ TokenMatch(filePtr,"MESH_SOFTSKIN",13))
+ {
+ ParseLV2MeshBlock((ASE::Mesh&)node);
+ continue;
+ }
+ // mesh material index
+ if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
+ {
+ ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
+ continue;
+ }
+ }
+ }
+ AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera)
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
- {
- ParseLV4MeshFloat(camera.mNear);
- continue;
- }
- if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
- {
- ParseLV4MeshFloat(camera.mFar);
- continue;
- }
- if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
- {
- ParseLV4MeshFloat(camera.mFOV);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
+ {
+ ParseLV4MeshFloat(camera.mNear);
+ continue;
+ }
+ if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
+ {
+ ParseLV4MeshFloat(camera.mFar);
+ continue;
+ }
+ if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
+ {
+ ParseLV4MeshFloat(camera.mFOV);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2LightSettingsBlock(ASE::Light& light)
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
- {
- ParseLV4MeshFloatTriple(&light.mColor.r);
- continue;
- }
- if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
- {
- ParseLV4MeshFloat(light.mIntensity);
- continue;
- }
- if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
- {
- ParseLV4MeshFloat(light.mAngle);
- continue;
- }
- if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
- {
- ParseLV4MeshFloat(light.mFalloff);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
+ {
+ ParseLV4MeshFloatTriple(&light.mColor.r);
+ continue;
+ }
+ if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
+ {
+ ParseLV4MeshFloat(light.mIntensity);
+ continue;
+ }
+ if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
+ {
+ ParseLV4MeshFloat(light.mAngle);
+ continue;
+ }
+ if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
+ {
+ ParseLV4MeshFloat(light.mFalloff);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
{
- AI_ASE_PARSER_INIT();
-
- ASE::Animation* anim = &mesh.mAnim;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- if (TokenMatch(filePtr,"NODE_NAME" ,9))
- {
- std::string temp;
- if(!ParseString(temp,"*NODE_NAME"))
- SkipToNextToken();
-
- // If the name of the node contains .target it
- // represents an animated camera or spot light
- // target.
- if (std::string::npos != temp.find(".Target"))
- {
- if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) &&
- ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
- {
-
- DefaultLogger::get()->error("ASE: Found target animation channel "
- "but the node is neither a camera nor a spot light");
- anim = NULL;
- }
- else anim = &mesh.mTargetAnim;
- }
- continue;
- }
-
- // position keyframes
- if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) ||
- TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) ||
- TokenMatch(filePtr,"CONTROL_POS_TCB" ,15))
- {
- if (!anim)SkipSection();
- else ParseLV3PosAnimationBlock(*anim);
- continue;
- }
- // scaling keyframes
- if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) ||
- TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
- TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17))
- {
- if (!anim || anim == &mesh.mTargetAnim)
- {
- // Target animation channels may have no rotation channels
- DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
- SkipSection();
- }
- else ParseLV3ScaleAnimationBlock(*anim);
- continue;
- }
- // rotation keyframes
- if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) ||
- TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
- TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15))
- {
- if (!anim || anim == &mesh.mTargetAnim)
- {
- // Target animation channels may have no rotation channels
- DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
- SkipSection();
- }
- else ParseLV3RotAnimationBlock(*anim);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
- }
+ AI_ASE_PARSER_INIT();
+
+ ASE::Animation* anim = &mesh.mAnim;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ if (TokenMatch(filePtr,"NODE_NAME" ,9))
+ {
+ std::string temp;
+ if(!ParseString(temp,"*NODE_NAME"))
+ SkipToNextToken();
+
+ // If the name of the node contains .target it
+ // represents an animated camera or spot light
+ // target.
+ if (std::string::npos != temp.find(".Target"))
+ {
+ if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) &&
+ ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET))
+ {
+
+ DefaultLogger::get()->error("ASE: Found target animation channel "
+ "but the node is neither a camera nor a spot light");
+ anim = NULL;
+ }
+ else anim = &mesh.mTargetAnim;
+ }
+ continue;
+ }
+
+ // position keyframes
+ if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) ||
+ TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) ||
+ TokenMatch(filePtr,"CONTROL_POS_TCB" ,15))
+ {
+ if (!anim)SkipSection();
+ else ParseLV3PosAnimationBlock(*anim);
+ continue;
+ }
+ // scaling keyframes
+ if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) ||
+ TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
+ TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17))
+ {
+ if (!anim || anim == &mesh.mTargetAnim)
+ {
+ // Target animation channels may have no rotation channels
+ DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
+ SkipSection();
+ }
+ else ParseLV3ScaleAnimationBlock(*anim);
+ continue;
+ }
+ // rotation keyframes
+ if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) ||
+ TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
+ TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15))
+ {
+ if (!anim || anim == &mesh.mTargetAnim)
+ {
+ // Target animation channels may have no rotation channels
+ DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
+ SkipSection();
+ }
+ else ParseLV3RotAnimationBlock(*anim);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
{
- AI_ASE_PARSER_INIT();
- unsigned int iIndex;
-
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- bool b = false;
-
- // For the moment we're just reading the three floats -
- // we ignore the ádditional information for bezier's and TCBs
-
- // simple scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
- {
- b = true;
- anim.mScalingType = ASE::Animation::TRACK;
- }
-
- // Bezier scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
- {
- b = true;
- anim.mScalingType = ASE::Animation::BEZIER;
- }
- // TCB scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
- {
- b = true;
- anim.mScalingType = ASE::Animation::TCB;
- }
- if (b)
- {
- anim.akeyScaling.push_back(aiVectorKey());
- aiVectorKey& key = anim.akeyScaling.back();
- ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
- key.mTime = (double)iIndex;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
- }
+ AI_ASE_PARSER_INIT();
+ unsigned int iIndex;
+
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ bool b = false;
+
+ // For the moment we're just reading the three floats -
+ // we ignore the �dditional information for bezier's and TCBs
+
+ // simple scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
+ {
+ b = true;
+ anim.mScalingType = ASE::Animation::TRACK;
+ }
+
+ // Bezier scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
+ {
+ b = true;
+ anim.mScalingType = ASE::Animation::BEZIER;
+ }
+ // TCB scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
+ {
+ b = true;
+ anim.mScalingType = ASE::Animation::TCB;
+ }
+ if (b)
+ {
+ anim.akeyScaling.push_back(aiVectorKey());
+ aiVectorKey& key = anim.akeyScaling.back();
+ ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
+ key.mTime = (double)iIndex;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
{
- AI_ASE_PARSER_INIT();
- unsigned int iIndex;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- bool b = false;
-
- // For the moment we're just reading the three floats -
- // we ignore the ádditional information for bezier's and TCBs
-
- // simple scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
- {
- b = true;
- anim.mPositionType = ASE::Animation::TRACK;
- }
-
- // Bezier scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
- {
- b = true;
- anim.mPositionType = ASE::Animation::BEZIER;
- }
- // TCB scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
- {
- b = true;
- anim.mPositionType = ASE::Animation::TCB;
- }
- if (b)
- {
- anim.akeyPositions.push_back(aiVectorKey());
- aiVectorKey& key = anim.akeyPositions.back();
- ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
- key.mTime = (double)iIndex;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
- }
+ AI_ASE_PARSER_INIT();
+ unsigned int iIndex;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ bool b = false;
+
+ // For the moment we're just reading the three floats -
+ // we ignore the �dditional information for bezier's and TCBs
+
+ // simple scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
+ {
+ b = true;
+ anim.mPositionType = ASE::Animation::TRACK;
+ }
+
+ // Bezier scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
+ {
+ b = true;
+ anim.mPositionType = ASE::Animation::BEZIER;
+ }
+ // TCB scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
+ {
+ b = true;
+ anim.mPositionType = ASE::Animation::TCB;
+ }
+ if (b)
+ {
+ anim.akeyPositions.push_back(aiVectorKey());
+ aiVectorKey& key = anim.akeyPositions.back();
+ ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
+ key.mTime = (double)iIndex;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
{
- AI_ASE_PARSER_INIT();
- unsigned int iIndex;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- bool b = false;
-
- // For the moment we're just reading the floats -
- // we ignore the ádditional information for bezier's and TCBs
-
- // simple scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
- {
- b = true;
- anim.mRotationType = ASE::Animation::TRACK;
- }
-
- // Bezier scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
- {
- b = true;
- anim.mRotationType = ASE::Animation::BEZIER;
- }
- // TCB scaling keyframe
- if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
- {
- b = true;
- anim.mRotationType = ASE::Animation::TCB;
- }
- if (b)
- {
- anim.akeyRotations.push_back(aiQuatKey());
- aiQuatKey& key = anim.akeyRotations.back();
- aiVector3D v;float f;
- ParseLV4MeshFloatTriple(&v.x,iIndex);
- ParseLV4MeshFloat(f);
- key.mTime = (double)iIndex;
- key.mValue = aiQuaternion(v,f);
- }
- }
- AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
- }
+ AI_ASE_PARSER_INIT();
+ unsigned int iIndex;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ bool b = false;
+
+ // For the moment we're just reading the floats -
+ // we ignore the �dditional information for bezier's and TCBs
+
+ // simple scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
+ {
+ b = true;
+ anim.mRotationType = ASE::Animation::TRACK;
+ }
+
+ // Bezier scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
+ {
+ b = true;
+ anim.mRotationType = ASE::Animation::BEZIER;
+ }
+ // TCB scaling keyframe
+ if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
+ {
+ b = true;
+ anim.mRotationType = ASE::Animation::TCB;
+ }
+ if (b)
+ {
+ anim.akeyRotations.push_back(aiQuatKey());
+ aiQuatKey& key = anim.akeyRotations.back();
+ aiVector3D v;float f;
+ ParseLV4MeshFloatTriple(&v.x,iIndex);
+ ParseLV4MeshFloat(f);
+ key.mTime = (double)iIndex;
+ key.mValue = aiQuaternion(v,f);
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
{
- AI_ASE_PARSER_INIT();
- int mode = 0;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- // name of the node
- if (TokenMatch(filePtr,"NODE_NAME" ,9))
- {
- std::string temp;
- if(!ParseString(temp,"*NODE_NAME"))
- SkipToNextToken();
-
- std::string::size_type s;
- if (temp == mesh.mName)
- {
- mode = 1;
- }
- else if (std::string::npos != (s = temp.find(".Target")) &&
- mesh.mName == temp.substr(0,s))
- {
- // This should be either a target light or a target camera
- if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) ||
- (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
- {
- mode = 2;
- }
- else DefaultLogger::get()->error("ASE: Ignoring target transform, "
- "this is no spot light or target camera");
- }
- else
- {
- DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
- // mode = 0
- }
- continue;
- }
- if (mode)
- {
- // fourth row of the transformation matrix - and also the
- // only information here that is interesting for targets
- if (TokenMatch(filePtr,"TM_ROW3" ,7))
- {
- ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
- continue;
- }
- if (mode == 1)
- {
- // first row of the transformation matrix
- if (TokenMatch(filePtr,"TM_ROW0" ,7))
- {
- ParseLV4MeshFloatTriple(mesh.mTransform[0]);
- continue;
- }
- // second row of the transformation matrix
- if (TokenMatch(filePtr,"TM_ROW1" ,7))
- {
- ParseLV4MeshFloatTriple(mesh.mTransform[1]);
- continue;
- }
- // third row of the transformation matrix
- if (TokenMatch(filePtr,"TM_ROW2" ,7))
- {
- ParseLV4MeshFloatTriple(mesh.mTransform[2]);
- continue;
- }
- // inherited position axes
- if (TokenMatch(filePtr,"INHERIT_POS" ,11))
- {
- unsigned int aiVal[3];
- ParseLV4MeshLongTriple(aiVal);
-
- for (unsigned int i = 0; i < 3;++i)
- mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
- continue;
- }
- // inherited rotation axes
- if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
- {
- unsigned int aiVal[3];
- ParseLV4MeshLongTriple(aiVal);
-
- for (unsigned int i = 0; i < 3;++i)
- mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
- continue;
- }
- // inherited scaling axes
- if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
- {
- unsigned int aiVal[3];
- ParseLV4MeshLongTriple(aiVal);
-
- for (unsigned int i = 0; i < 3;++i)
- mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
- continue;
- }
- }
- }
- }
- AI_ASE_HANDLE_SECTION("2","*NODE_TM");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ int mode = 0;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ // name of the node
+ if (TokenMatch(filePtr,"NODE_NAME" ,9))
+ {
+ std::string temp;
+ if(!ParseString(temp,"*NODE_NAME"))
+ SkipToNextToken();
+
+ std::string::size_type s;
+ if (temp == mesh.mName)
+ {
+ mode = 1;
+ }
+ else if (std::string::npos != (s = temp.find(".Target")) &&
+ mesh.mName == temp.substr(0,s))
+ {
+ // This should be either a target light or a target camera
+ if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) ||
+ (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
+ {
+ mode = 2;
+ }
+ else DefaultLogger::get()->error("ASE: Ignoring target transform, "
+ "this is no spot light or target camera");
+ }
+ else
+ {
+ DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
+ // mode = 0
+ }
+ continue;
+ }
+ if (mode)
+ {
+ // fourth row of the transformation matrix - and also the
+ // only information here that is interesting for targets
+ if (TokenMatch(filePtr,"TM_ROW3" ,7))
+ {
+ ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
+ continue;
+ }
+ if (mode == 1)
+ {
+ // first row of the transformation matrix
+ if (TokenMatch(filePtr,"TM_ROW0" ,7))
+ {
+ ParseLV4MeshFloatTriple(mesh.mTransform[0]);
+ continue;
+ }
+ // second row of the transformation matrix
+ if (TokenMatch(filePtr,"TM_ROW1" ,7))
+ {
+ ParseLV4MeshFloatTriple(mesh.mTransform[1]);
+ continue;
+ }
+ // third row of the transformation matrix
+ if (TokenMatch(filePtr,"TM_ROW2" ,7))
+ {
+ ParseLV4MeshFloatTriple(mesh.mTransform[2]);
+ continue;
+ }
+ // inherited position axes
+ if (TokenMatch(filePtr,"INHERIT_POS" ,11))
+ {
+ unsigned int aiVal[3];
+ ParseLV4MeshLongTriple(aiVal);
+
+ for (unsigned int i = 0; i < 3;++i)
+ mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
+ continue;
+ }
+ // inherited rotation axes
+ if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
+ {
+ unsigned int aiVal[3];
+ ParseLV4MeshLongTriple(aiVal);
+
+ for (unsigned int i = 0; i < 3;++i)
+ mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
+ continue;
+ }
+ // inherited scaling axes
+ if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
+ {
+ unsigned int aiVal[3];
+ ParseLV4MeshLongTriple(aiVal);
+
+ for (unsigned int i = 0; i < 3;++i)
+ mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
+ continue;
+ }
+ }
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","*NODE_TM");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- unsigned int iNumVertices = 0;
- unsigned int iNumFaces = 0;
- unsigned int iNumTVertices = 0;
- unsigned int iNumTFaces = 0;
- unsigned int iNumCVertices = 0;
- unsigned int iNumCFaces = 0;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
- // Number of vertices in the mesh
- if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
- {
- ParseLV4MeshLong(iNumVertices);
- continue;
- }
- // Number of texture coordinates in the mesh
- if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
- {
- ParseLV4MeshLong(iNumTVertices);
- continue;
- }
- // Number of vertex colors in the mesh
- if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
- {
- ParseLV4MeshLong(iNumCVertices);
- continue;
- }
- // Number of regular faces in the mesh
- if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
- {
- ParseLV4MeshLong(iNumFaces);
- continue;
- }
- // Number of UVWed faces in the mesh
- if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
- {
- ParseLV4MeshLong(iNumTFaces);
- continue;
- }
- // Number of colored faces in the mesh
- if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
- {
- ParseLV4MeshLong(iNumCFaces);
- continue;
- }
- // mesh vertex list block
- if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
- {
- ParseLV3MeshVertexListBlock(iNumVertices,mesh);
- continue;
- }
- // mesh face list block
- if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
- {
- ParseLV3MeshFaceListBlock(iNumFaces,mesh);
- continue;
- }
- // mesh texture vertex list block
- if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
- {
- ParseLV3MeshTListBlock(iNumTVertices,mesh);
- continue;
- }
- // mesh texture face block
- if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
- {
- ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
- continue;
- }
- // mesh color vertex list block
- if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
- {
- ParseLV3MeshCListBlock(iNumCVertices,mesh);
- continue;
- }
- // mesh color face block
- if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
- {
- ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
- continue;
- }
- // mesh normals
- if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
- {
- ParseLV3MeshNormalListBlock(mesh);
- continue;
- }
- // another mesh UV channel ...
- if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
- {
-
- unsigned int iIndex = 0;
- ParseLV4MeshLong(iIndex);
-
- if (iIndex < 2)
- {
- LogWarning("Mapping channel has an invalid index. Skipping UV channel");
- // skip it ...
- SkipSection();
- }
- if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
- {
- LogWarning("Too many UV channels specified. Skipping channel ..");
- // skip it ...
- SkipSection();
- }
- else
- {
- // parse the mapping channel
- ParseLV3MappingChannel(iIndex-1,mesh);
- }
- continue;
- }
- // mesh animation keyframe. Not supported
- if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
- {
-
- LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
- "Keyframe animation is not supported by Assimp, this element "
- "will be ignored");
- //SkipSection();
- continue;
- }
- if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
- {
- ParseLV3MeshWeightsBlock(mesh);continue;
- }
- }
- AI_ASE_HANDLE_SECTION("2","*MESH");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ unsigned int iNumVertices = 0;
+ unsigned int iNumFaces = 0;
+ unsigned int iNumTVertices = 0;
+ unsigned int iNumTFaces = 0;
+ unsigned int iNumCVertices = 0;
+ unsigned int iNumCFaces = 0;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+ // Number of vertices in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
+ {
+ ParseLV4MeshLong(iNumVertices);
+ continue;
+ }
+ // Number of texture coordinates in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
+ {
+ ParseLV4MeshLong(iNumTVertices);
+ continue;
+ }
+ // Number of vertex colors in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
+ {
+ ParseLV4MeshLong(iNumCVertices);
+ continue;
+ }
+ // Number of regular faces in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
+ {
+ ParseLV4MeshLong(iNumFaces);
+ continue;
+ }
+ // Number of UVWed faces in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
+ {
+ ParseLV4MeshLong(iNumTFaces);
+ continue;
+ }
+ // Number of colored faces in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
+ {
+ ParseLV4MeshLong(iNumCFaces);
+ continue;
+ }
+ // mesh vertex list block
+ if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
+ {
+ ParseLV3MeshVertexListBlock(iNumVertices,mesh);
+ continue;
+ }
+ // mesh face list block
+ if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
+ {
+ ParseLV3MeshFaceListBlock(iNumFaces,mesh);
+ continue;
+ }
+ // mesh texture vertex list block
+ if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
+ {
+ ParseLV3MeshTListBlock(iNumTVertices,mesh);
+ continue;
+ }
+ // mesh texture face block
+ if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
+ {
+ ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
+ continue;
+ }
+ // mesh color vertex list block
+ if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
+ {
+ ParseLV3MeshCListBlock(iNumCVertices,mesh);
+ continue;
+ }
+ // mesh color face block
+ if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
+ {
+ ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
+ continue;
+ }
+ // mesh normals
+ if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
+ {
+ ParseLV3MeshNormalListBlock(mesh);
+ continue;
+ }
+ // another mesh UV channel ...
+ if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
+ {
+
+ unsigned int iIndex = 0;
+ ParseLV4MeshLong(iIndex);
+
+ if (iIndex < 2)
+ {
+ LogWarning("Mapping channel has an invalid index. Skipping UV channel");
+ // skip it ...
+ SkipSection();
+ }
+ if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
+ {
+ LogWarning("Too many UV channels specified. Skipping channel ..");
+ // skip it ...
+ SkipSection();
+ }
+ else
+ {
+ // parse the mapping channel
+ ParseLV3MappingChannel(iIndex-1,mesh);
+ }
+ continue;
+ }
+ // mesh animation keyframe. Not supported
+ if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
+ {
+
+ LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
+ "Keyframe animation is not supported by Assimp, this element "
+ "will be ignored");
+ //SkipSection();
+ continue;
+ }
+ if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
+ {
+ ParseLV3MeshWeightsBlock(mesh);continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("2","*MESH");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- unsigned int iNumVertices = 0, iNumBones = 0;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Number of bone vertices ...
- if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
- {
- ParseLV4MeshLong(iNumVertices);
- continue;
- }
- // Number of bones
- if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
- {
- ParseLV4MeshLong(iNumBones);
- continue;
- }
- // parse the list of bones
- if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
- {
- ParseLV4MeshBones(iNumBones,mesh);
- continue;
- }
- // parse the list of bones vertices
- if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
- {
- ParseLV4MeshBonesVertices(iNumVertices,mesh);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ unsigned int iNumVertices = 0, iNumBones = 0;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Number of bone vertices ...
+ if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
+ {
+ ParseLV4MeshLong(iNumVertices);
+ continue;
+ }
+ // Number of bones
+ if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
+ {
+ ParseLV4MeshLong(iNumBones);
+ continue;
+ }
+ // parse the list of bones
+ if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
+ {
+ ParseLV4MeshBones(iNumBones,mesh);
+ continue;
+ }
+ // parse the list of bones vertices
+ if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
+ {
+ ParseLV4MeshBonesVertices(iNumVertices,mesh);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
- mesh.mBones.resize(iNumBones);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Mesh bone with name ...
- if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
- {
- // parse an index ...
- if(SkipSpaces(&filePtr))
- {
- unsigned int iIndex = strtoul10(filePtr,&filePtr);
- if (iIndex >= iNumBones)
- {
- LogWarning("Bone index is out of bounds");
- continue;
- }
- if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
- SkipToNextToken();
- continue;
- }
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
- }
+ AI_ASE_PARSER_INIT();
+ mesh.mBones.resize(iNumBones);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Mesh bone with name ...
+ if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
+ {
+ // parse an index ...
+ if(SkipSpaces(&filePtr))
+ {
+ unsigned int iIndex = strtoul10(filePtr,&filePtr);
+ if (iIndex >= iNumBones)
+ {
+ LogWarning("Bone index is out of bounds");
+ continue;
+ }
+ if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
+ SkipToNextToken();
+ continue;
+ }
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
+ }
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
- mesh.mBoneVertices.resize(iNumVertices);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Mesh bone vertex
- if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
- {
- // read the vertex index
- unsigned int iIndex = strtoul10(filePtr,&filePtr);
- if (iIndex >= mesh.mPositions.size())
- {
- iIndex = (unsigned int)mesh.mPositions.size()-1;
- LogWarning("Bone vertex index is out of bounds. Using the largest valid "
- "bone vertex index instead");
- }
-
- // --- ignored
- float afVert[3];
- ParseLV4MeshFloatTriple(afVert);
-
- std::pair<int,float> pairOut;
- while (true)
- {
- // first parse the bone index ...
- if (!SkipSpaces(&filePtr))break;
- pairOut.first = strtoul10(filePtr,&filePtr);
-
- // then parse the vertex weight
- if (!SkipSpaces(&filePtr))break;
- filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
-
- // -1 marks unused entries
- if (-1 != pairOut.first)
- {
- mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
- }
- }
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ mesh.mBoneVertices.resize(iNumVertices);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Mesh bone vertex
+ if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
+ {
+ // read the vertex index
+ unsigned int iIndex = strtoul10(filePtr,&filePtr);
+ if (iIndex >= mesh.mPositions.size())
+ {
+ iIndex = (unsigned int)mesh.mPositions.size()-1;
+ LogWarning("Bone vertex index is out of bounds. Using the largest valid "
+ "bone vertex index instead");
+ }
+
+ // --- ignored
+ float afVert[3];
+ ParseLV4MeshFloatTriple(afVert);
+
+ std::pair<int,float> pairOut;
+ while (true)
+ {
+ // first parse the bone index ...
+ if (!SkipSpaces(&filePtr))break;
+ pairOut.first = strtoul10(filePtr,&filePtr);
+
+ // then parse the vertex weight
+ if (!SkipSpaces(&filePtr))break;
+ filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
+
+ // -1 marks unused entries
+ if (-1 != pairOut.first)
+ {
+ mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
+ }
+ }
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshVertexListBlock(
- unsigned int iNumVertices, ASE::Mesh& mesh)
+ unsigned int iNumVertices, ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- // allocate enough storage in the array
- mesh.mPositions.resize(iNumVertices);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Vertex entry
- if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
- {
-
- aiVector3D vTemp;
- unsigned int iIndex;
- ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
-
- if (iIndex >= iNumVertices)
- {
- LogWarning("Invalid vertex index. It will be ignored");
- }
- else mesh.mPositions[iIndex] = vTemp;
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // allocate enough storage in the array
+ mesh.mPositions.resize(iNumVertices);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Vertex entry
+ if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
+ {
+
+ aiVector3D vTemp;
+ unsigned int iIndex;
+ ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+ if (iIndex >= iNumVertices)
+ {
+ LogWarning("Invalid vertex index. It will be ignored");
+ }
+ else mesh.mPositions[iIndex] = vTemp;
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- // allocate enough storage in the face array
- mesh.mFaces.resize(iNumFaces);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Face entry
- if (TokenMatch(filePtr,"MESH_FACE" ,9))
- {
-
- ASE::Face mFace;
- ParseLV4MeshFace(mFace);
-
- if (mFace.iFace >= iNumFaces)
- {
- LogWarning("Face has an invalid index. It will be ignored");
- }
- else mesh.mFaces[mFace.iFace] = mFace;
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // allocate enough storage in the face array
+ mesh.mFaces.resize(iNumFaces);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Face entry
+ if (TokenMatch(filePtr,"MESH_FACE" ,9))
+ {
+
+ ASE::Face mFace;
+ ParseLV4MeshFace(mFace);
+
+ if (mFace.iFace >= iNumFaces)
+ {
+ LogWarning("Face has an invalid index. It will be ignored");
+ }
+ else mesh.mFaces[mFace.iFace] = mFace;
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
- ASE::Mesh& mesh, unsigned int iChannel)
+ ASE::Mesh& mesh, unsigned int iChannel)
{
- AI_ASE_PARSER_INIT();
-
- // allocate enough storage in the array
- mesh.amTexCoords[iChannel].resize(iNumVertices);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Vertex entry
- if (TokenMatch(filePtr,"MESH_TVERT" ,10))
- {
- aiVector3D vTemp;
- unsigned int iIndex;
- ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
-
- if (iIndex >= iNumVertices)
- {
- LogWarning("Tvertex has an invalid index. It will be ignored");
- }
- else mesh.amTexCoords[iChannel][iIndex] = vTemp;
-
- if (0.0f != vTemp.z)
- {
- // we need 3 coordinate channels
- mesh.mNumUVComponents[iChannel] = 3;
- }
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // allocate enough storage in the array
+ mesh.amTexCoords[iChannel].resize(iNumVertices);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Vertex entry
+ if (TokenMatch(filePtr,"MESH_TVERT" ,10))
+ {
+ aiVector3D vTemp;
+ unsigned int iIndex;
+ ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+ if (iIndex >= iNumVertices)
+ {
+ LogWarning("Tvertex has an invalid index. It will be ignored");
+ }
+ else mesh.amTexCoords[iChannel][iIndex] = vTemp;
+
+ if (0.0f != vTemp.z)
+ {
+ // we need 3 coordinate channels
+ mesh.mNumUVComponents[iChannel] = 3;
+ }
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
- ASE::Mesh& mesh, unsigned int iChannel)
+ ASE::Mesh& mesh, unsigned int iChannel)
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Face entry
- if (TokenMatch(filePtr,"MESH_TFACE" ,10))
- {
- unsigned int aiValues[3];
- unsigned int iIndex = 0;
-
- ParseLV4MeshLongTriple(aiValues,iIndex);
- if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
- {
- LogWarning("UV-Face has an invalid index. It will be ignored");
- }
- else
- {
- // copy UV indices
- mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
- mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
- mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
- }
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Face entry
+ if (TokenMatch(filePtr,"MESH_TFACE" ,10))
+ {
+ unsigned int aiValues[3];
+ unsigned int iIndex = 0;
+
+ ParseLV4MeshLongTriple(aiValues,iIndex);
+ if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+ {
+ LogWarning("UV-Face has an invalid index. It will be ignored");
+ }
+ else
+ {
+ // copy UV indices
+ mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
+ mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
+ mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
+ }
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- unsigned int iNumTVertices = 0;
- unsigned int iNumTFaces = 0;
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Number of texture coordinates in the mesh
- if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
- {
- ParseLV4MeshLong(iNumTVertices);
- continue;
- }
- // Number of UVWed faces in the mesh
- if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
- {
- ParseLV4MeshLong(iNumTFaces);
- continue;
- }
- // mesh texture vertex list block
- if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
- {
- ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
- continue;
- }
- // mesh texture face block
- if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
- {
- ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ unsigned int iNumTVertices = 0;
+ unsigned int iNumTFaces = 0;
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Number of texture coordinates in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
+ {
+ ParseLV4MeshLong(iNumTVertices);
+ continue;
+ }
+ // Number of UVWed faces in the mesh
+ if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
+ {
+ ParseLV4MeshLong(iNumTFaces);
+ continue;
+ }
+ // mesh texture vertex list block
+ if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
+ {
+ ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
+ continue;
+ }
+ // mesh texture face block
+ if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
+ {
+ ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
-
- // allocate enough storage in the array
- mesh.mVertexColors.resize(iNumVertices);
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Vertex entry
- if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
- {
- aiColor4D vTemp;
- vTemp.a = 1.0f;
- unsigned int iIndex;
- ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
-
- if (iIndex >= iNumVertices)
- {
- LogWarning("Vertex color has an invalid index. It will be ignored");
- }
- else mesh.mVertexColors[iIndex] = vTemp;
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // allocate enough storage in the array
+ mesh.mVertexColors.resize(iNumVertices);
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Vertex entry
+ if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
+ {
+ aiColor4D vTemp;
+ vTemp.a = 1.0f;
+ unsigned int iIndex;
+ ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
+
+ if (iIndex >= iNumVertices)
+ {
+ LogWarning("Vertex color has an invalid index. It will be ignored");
+ }
+ else mesh.mVertexColors[iIndex] = vTemp;
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
{
- AI_ASE_PARSER_INIT();
- while (true)
- {
- if ('*' == *filePtr)
- {
- ++filePtr;
-
- // Face entry
- if (TokenMatch(filePtr,"MESH_CFACE" ,11))
- {
- unsigned int aiValues[3];
- unsigned int iIndex = 0;
-
- ParseLV4MeshLongTriple(aiValues,iIndex);
- if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
- {
- LogWarning("UV-Face has an invalid index. It will be ignored");
- }
- else
- {
- // copy color indices
- mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
- mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
- mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
- }
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
- }
- return;
+ AI_ASE_PARSER_INIT();
+ while (true)
+ {
+ if ('*' == *filePtr)
+ {
+ ++filePtr;
+
+ // Face entry
+ if (TokenMatch(filePtr,"MESH_CFACE" ,11))
+ {
+ unsigned int aiValues[3];
+ unsigned int iIndex = 0;
+
+ ParseLV4MeshLongTriple(aiValues,iIndex);
+ if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+ {
+ LogWarning("UV-Face has an invalid index. It will be ignored");
+ }
+ else
+ {
+ // copy color indices
+ mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
+ mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
+ mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
+ }
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
{
- AI_ASE_PARSER_INIT();
-
- // Allocate enough storage for the normals
- sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
- unsigned int index, faceIdx = UINT_MAX;
-
- // FIXME: rewrite this and find out how to interpret the normals
- // correctly. This is crap.
-
- // Smooth the vertex and face normals together. The result
- // will be edgy then, but otherwise everything would be soft ...
- while (true) {
- if ('*' == *filePtr) {
- ++filePtr;
- if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) {
- aiVector3D vNormal;
- ParseLV4MeshFloatTriple(&vNormal.x,index);
- if (faceIdx >= sMesh.mFaces.size())
- continue;
-
- // Make sure we assign it to the correct face
- const ASE::Face& face = sMesh.mFaces[faceIdx];
- if (index == face.mIndices[0])
- index = 0;
- else if (index == face.mIndices[1])
- index = 1;
- else if (index == face.mIndices[2])
- index = 2;
- else {
- DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
- continue;
- }
- // We'll renormalize later
- sMesh.mNormals[faceIdx*3+index] += vNormal;
- continue;
- }
- if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) {
- aiVector3D vNormal;
- ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
-
- if (faceIdx >= sMesh.mFaces.size()) {
- DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
- continue;
- }
-
- // We'll renormalize later
- sMesh.mNormals[faceIdx*3] += vNormal;
- sMesh.mNormals[faceIdx*3+1] += vNormal;
- sMesh.mNormals[faceIdx*3+2] += vNormal;
- continue;
- }
- }
- AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
- }
- return;
+ AI_ASE_PARSER_INIT();
+
+ // Allocate enough storage for the normals
+ sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
+ unsigned int index, faceIdx = UINT_MAX;
+
+ // FIXME: rewrite this and find out how to interpret the normals
+ // correctly. This is crap.
+
+ // Smooth the vertex and face normals together. The result
+ // will be edgy then, but otherwise everything would be soft ...
+ while (true) {
+ if ('*' == *filePtr) {
+ ++filePtr;
+ if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) {
+ aiVector3D vNormal;
+ ParseLV4MeshFloatTriple(&vNormal.x,index);
+ if (faceIdx >= sMesh.mFaces.size())
+ continue;
+
+ // Make sure we assign it to the correct face
+ const ASE::Face& face = sMesh.mFaces[faceIdx];
+ if (index == face.mIndices[0])
+ index = 0;
+ else if (index == face.mIndices[1])
+ index = 1;
+ else if (index == face.mIndices[2])
+ index = 2;
+ else {
+ DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
+ continue;
+ }
+ // We'll renormalize later
+ sMesh.mNormals[faceIdx*3+index] += vNormal;
+ continue;
+ }
+ if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) {
+ aiVector3D vNormal;
+ ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
+
+ if (faceIdx >= sMesh.mFaces.size()) {
+ DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
+ continue;
+ }
+
+ // We'll renormalize later
+ sMesh.mNormals[faceIdx*3] += vNormal;
+ sMesh.mNormals[faceIdx*3+1] += vNormal;
+ sMesh.mNormals[faceIdx*3+2] += vNormal;
+ continue;
+ }
+ }
+ AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFace(ASE::Face& out)
-{
- // skip spaces and tabs
- if(!SkipSpaces(&filePtr))
- {
- LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
- SkipToNextToken();
- return;
- }
-
- // parse the face index
- out.iFace = strtoul10(filePtr,&filePtr);
-
- // next character should be ':'
- if(!SkipSpaces(&filePtr))
- {
- // FIX: there are some ASE files which haven't got : here ....
- LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
- SkipToNextToken();
- return;
- }
- // FIX: There are some ASE files which haven't got ':' here
- if(':' == *filePtr)++filePtr;
-
- // Parse all mesh indices
- for (unsigned int i = 0; i < 3;++i)
- {
- unsigned int iIndex = 0;
- if(!SkipSpaces(&filePtr))
- {
- LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
- SkipToNextToken();
- return;
- }
- switch (*filePtr)
- {
- case 'A':
- case 'a':
- break;
- case 'B':
- case 'b':
- iIndex = 1;
- break;
- case 'C':
- case 'c':
- iIndex = 2;
- break;
- default:
- LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
- "A,B or C expected [#3]");
- SkipToNextToken();
- return;
- };
- ++filePtr;
-
- // next character should be ':'
- if(!SkipSpaces(&filePtr) || ':' != *filePtr)
- {
- LogWarning("Unable to parse *MESH_FACE Element: "
- "Unexpected EOL. \':\' expected [#2]");
- SkipToNextToken();
- return;
- }
-
- ++filePtr;
- if(!SkipSpaces(&filePtr))
- {
- LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
- "Vertex index ecpected [#4]");
- SkipToNextToken();
- return;
- }
- out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
- }
-
- // now we need to skip the AB, BC, CA blocks.
- while (true)
- {
- if ('*' == *filePtr)break;
- if (IsLineEnd(*filePtr))
- {
- //iLineNumber++;
- return;
- }
- filePtr++;
- }
-
- // parse the smoothing group of the face
- if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
- {
- if(!SkipSpaces(&filePtr))
- {
- LogWarning("Unable to parse *MESH_SMOOTHING Element: "
- "Unexpected EOL. Smoothing group(s) expected [#5]");
- SkipToNextToken();
- return;
- }
-
- // Parse smoothing groups until we don't anymore see commas
- // FIX: There needn't always be a value, sad but true
- while (true)
- {
- if (*filePtr < '9' && *filePtr >= '0')
- {
- out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
- }
- SkipSpaces(&filePtr);
- if (',' != *filePtr)
- {
- break;
- }
- ++filePtr;
- SkipSpaces(&filePtr);
- }
- }
-
- // *MESH_MTLID is optional, too
- while (true)
- {
- if ('*' == *filePtr)break;
- if (IsLineEnd(*filePtr))
- {
- return;
- }
- filePtr++;
- }
-
- if (TokenMatch(filePtr,"*MESH_MTLID",11))
- {
- if(!SkipSpaces(&filePtr))
- {
- LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
- "Material index expected [#6]");
- SkipToNextToken();
- return;
- }
- out.iMaterial = strtoul10(filePtr,&filePtr);
- }
- return;
+{
+ // skip spaces and tabs
+ if(!SkipSpaces(&filePtr))
+ {
+ LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
+ SkipToNextToken();
+ return;
+ }
+
+ // parse the face index
+ out.iFace = strtoul10(filePtr,&filePtr);
+
+ // next character should be ':'
+ if(!SkipSpaces(&filePtr))
+ {
+ // FIX: there are some ASE files which haven't got : here ....
+ LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
+ SkipToNextToken();
+ return;
+ }
+ // FIX: There are some ASE files which haven't got ':' here
+ if(':' == *filePtr)++filePtr;
+
+ // Parse all mesh indices
+ for (unsigned int i = 0; i < 3;++i)
+ {
+ unsigned int iIndex = 0;
+ if(!SkipSpaces(&filePtr))
+ {
+ LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
+ SkipToNextToken();
+ return;
+ }
+ switch (*filePtr)
+ {
+ case 'A':
+ case 'a':
+ break;
+ case 'B':
+ case 'b':
+ iIndex = 1;
+ break;
+ case 'C':
+ case 'c':
+ iIndex = 2;
+ break;
+ default:
+ LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+ "A,B or C expected [#3]");
+ SkipToNextToken();
+ return;
+ };
+ ++filePtr;
+
+ // next character should be ':'
+ if(!SkipSpaces(&filePtr) || ':' != *filePtr)
+ {
+ LogWarning("Unable to parse *MESH_FACE Element: "
+ "Unexpected EOL. \':\' expected [#2]");
+ SkipToNextToken();
+ return;
+ }
+
+ ++filePtr;
+ if(!SkipSpaces(&filePtr))
+ {
+ LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+ "Vertex index ecpected [#4]");
+ SkipToNextToken();
+ return;
+ }
+ out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
+ }
+
+ // now we need to skip the AB, BC, CA blocks.
+ while (true)
+ {
+ if ('*' == *filePtr)break;
+ if (IsLineEnd(*filePtr))
+ {
+ //iLineNumber++;
+ return;
+ }
+ filePtr++;
+ }
+
+ // parse the smoothing group of the face
+ if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
+ {
+ if(!SkipSpaces(&filePtr))
+ {
+ LogWarning("Unable to parse *MESH_SMOOTHING Element: "
+ "Unexpected EOL. Smoothing group(s) expected [#5]");
+ SkipToNextToken();
+ return;
+ }
+
+ // Parse smoothing groups until we don't anymore see commas
+ // FIX: There needn't always be a value, sad but true
+ while (true)
+ {
+ if (*filePtr < '9' && *filePtr >= '0')
+ {
+ out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
+ }
+ SkipSpaces(&filePtr);
+ if (',' != *filePtr)
+ {
+ break;
+ }
+ ++filePtr;
+ SkipSpaces(&filePtr);
+ }
+ }
+
+ // *MESH_MTLID is optional, too
+ while (true)
+ {
+ if ('*' == *filePtr)break;
+ if (IsLineEnd(*filePtr))
+ {
+ return;
+ }
+ filePtr++;
+ }
+
+ if (TokenMatch(filePtr,"*MESH_MTLID",11))
+ {
+ if(!SkipSpaces(&filePtr))
+ {
+ LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
+ "Material index expected [#6]");
+ SkipToNextToken();
+ return;
+ }
+ out.iMaterial = strtoul10(filePtr,&filePtr);
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
{
- ai_assert(NULL != apOut);
+ ai_assert(NULL != apOut);
- for (unsigned int i = 0; i < 3;++i)
- ParseLV4MeshLong(apOut[i]);
+ for (unsigned int i = 0; i < 3;++i)
+ ParseLV4MeshLong(apOut[i]);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
{
- ai_assert(NULL != apOut);
+ ai_assert(NULL != apOut);
- // parse the index
- ParseLV4MeshLong(rIndexOut);
+ // parse the index
+ ParseLV4MeshLong(rIndexOut);
- // parse the three others
- ParseLV4MeshLongTriple(apOut);
+ // parse the three others
+ ParseLV4MeshLongTriple(apOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
{
- ai_assert(NULL != apOut);
+ ai_assert(NULL != apOut);
+
+ // parse the index
+ ParseLV4MeshLong(rIndexOut);
- // parse the index
- ParseLV4MeshLong(rIndexOut);
-
- // parse the three others
- ParseLV4MeshFloatTriple(apOut);
+ // parse the three others
+ ParseLV4MeshFloatTriple(apOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(float* apOut)
{
- ai_assert(NULL != apOut);
+ ai_assert(NULL != apOut);
- for (unsigned int i = 0; i < 3;++i)
- ParseLV4MeshFloat(apOut[i]);
+ for (unsigned int i = 0; i < 3;++i)
+ ParseLV4MeshFloat(apOut[i]);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloat(float& fOut)
{
- // skip spaces and tabs
- if(!SkipSpaces(&filePtr))
- {
- // LOG
- LogWarning("Unable to parse float: unexpected EOL [#1]");
- fOut = 0.0f;
- ++iLineNumber;
- return;
- }
- // parse the first float
- filePtr = fast_atoreal_move<float>(filePtr,fOut);
+ // skip spaces and tabs
+ if(!SkipSpaces(&filePtr))
+ {
+ // LOG
+ LogWarning("Unable to parse float: unexpected EOL [#1]");
+ fOut = 0.0f;
+ ++iLineNumber;
+ return;
+ }
+ // parse the first float
+ filePtr = fast_atoreal_move<float>(filePtr,fOut);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLong(unsigned int& iOut)
{
- // Skip spaces and tabs
- if(!SkipSpaces(&filePtr))
- {
- // LOG
- LogWarning("Unable to parse long: unexpected EOL [#1]");
- iOut = 0;
- ++iLineNumber;
- return;
- }
- // parse the value
- iOut = strtoul10(filePtr,&filePtr);
+ // Skip spaces and tabs
+ if(!SkipSpaces(&filePtr))
+ {
+ // LOG
+ LogWarning("Unable to parse long: unexpected EOL [#1]");
+ iOut = 0;
+ ++iLineNumber;
+ return;
+ }
+ // parse the value
+ iOut = strtoul10(filePtr,&filePtr);
}
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ASEParser.h b/src/3rdparty/assimp/code/ASEParser.h
index dec53a52c..667c7c5a0 100644
--- a/src/3rdparty/assimp/code/ASEParser.h
+++ b/src/3rdparty/assimp/code/ASEParser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,15 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_ASEFILEHELPER_H_INC
#define AI_ASEFILEHELPER_H_INC
-// STL/CRT headers
-#include <string>
-#include <vector>
-#include <list>
-
// public ASSIMP headers
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/anim.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
// for some helper routines like IsSpace()
#include "ParsingUtils.h"
@@ -60,8 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ASE is quite similar to 3ds. We can reuse some structures
#include "3DSLoader.h"
-namespace Assimp {
-namespace ASE {
+namespace Assimp {
+namespace ASE {
using namespace D3DS;
@@ -69,121 +64,121 @@ using namespace D3DS;
/** Helper structure representing an ASE material */
struct Material : public D3DS::Material
{
- //! Default constructor
- Material() : pcInstance(NULL), bNeed (false)
- {}
+ //! Default constructor
+ Material() : pcInstance(NULL), bNeed (false)
+ {}
- //! Contains all sub materials of this material
- std::vector<Material> avSubMaterials;
+ //! Contains all sub materials of this material
+ std::vector<Material> avSubMaterials;
- //! aiMaterial object
- aiMaterial* pcInstance;
+ //! aiMaterial object
+ aiMaterial* pcInstance;
- //! Can we remove this material?
- bool bNeed;
+ //! Can we remove this material?
+ bool bNeed;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file face */
struct Face : public FaceWithSmoothingGroup
{
- //! Default constructor. Initializes everything with 0
- Face()
- {
- mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
- {
- amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
- }
+ //! Default constructor. Initializes everything with 0
+ Face()
+ {
+ mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ {
+ amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
+ }
- iMaterial = DEFAULT_MATINDEX;
- iFace = 0;
- }
+ iMaterial = DEFAULT_MATINDEX;
+ iFace = 0;
+ }
- //! special value to indicate that no material index has
- //! been assigned to a face. The default material index
- //! will replace this value later.
- static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
+ //! special value to indicate that no material index has
+ //! been assigned to a face. The default material index
+ //! will replace this value later.
+ static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
- //! Indices into each list of texture coordinates
- unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
+ //! Indices into each list of texture coordinates
+ unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
- //! Index into the list of vertex colors
- unsigned int mColorIndices[3];
+ //! Index into the list of vertex colors
+ unsigned int mColorIndices[3];
- //! (Sub)Material index to be assigned to this face
- unsigned int iMaterial;
+ //! (Sub)Material index to be assigned to this face
+ unsigned int iMaterial;
- //! Index of the face. It is not specified whether it is
- //! a requirement of the file format that all faces are
- //! written in sequential order, so we have to expect this case
- unsigned int iFace;
+ //! Index of the face. It is not specified whether it is
+ //! a requirement of the file format that all faces are
+ //! written in sequential order, so we have to expect this case
+ unsigned int iFace;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file bone */
struct Bone
{
- //! Constructor
- Bone()
- {
- static int iCnt = 0;
-
- // Generate a default name for the bone
- char szTemp[128];
- ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
- mName = szTemp;
- }
-
- //! Construction from an existing name
- Bone( const std::string& name)
- : mName (name)
- {}
-
- //! Name of the bone
- std::string mName;
+ //! Constructor
+ Bone()
+ {
+ static int iCnt = 0;
+
+ // Generate a default name for the bone
+ char szTemp[128];
+ ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
+ mName = szTemp;
+ }
+
+ //! Construction from an existing name
+ explicit Bone( const std::string& name)
+ : mName (name)
+ {}
+
+ //! Name of the bone
+ std::string mName;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file bone vertex */
struct BoneVertex
{
- //! Bone and corresponding vertex weight.
- //! -1 for unrequired bones ....
- std::vector<std::pair<int,float> > mBoneWeights;
+ //! Bone and corresponding vertex weight.
+ //! -1 for unrequired bones ....
+ std::vector<std::pair<int,float> > mBoneWeights;
- //! Position of the bone vertex.
- //! MUST be identical to the vertex position
- //aiVector3D mPosition;
+ //! Position of the bone vertex.
+ //! MUST be identical to the vertex position
+ //aiVector3D mPosition;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file animation */
struct Animation
{
- enum Type
- {
- TRACK = 0x0,
- BEZIER = 0x1,
- TCB = 0x2
- } mRotationType, mScalingType, mPositionType;
+ enum Type
+ {
+ TRACK = 0x0,
+ BEZIER = 0x1,
+ TCB = 0x2
+ } mRotationType, mScalingType, mPositionType;
- Animation()
- : mRotationType (TRACK)
- , mScalingType (TRACK)
- , mPositionType (TRACK)
- {}
+ Animation()
+ : mRotationType (TRACK)
+ , mScalingType (TRACK)
+ , mPositionType (TRACK)
+ {}
- //! List of track rotation keyframes
- std::vector< aiQuatKey > akeyRotations;
+ //! List of track rotation keyframes
+ std::vector< aiQuatKey > akeyRotations;
- //! List of track position keyframes
- std::vector< aiVectorKey > akeyPositions;
+ //! List of track position keyframes
+ std::vector< aiVectorKey > akeyPositions;
- //! List of track scaling keyframes
- std::vector< aiVectorKey > akeyScaling;
+ //! List of track scaling keyframes
+ std::vector< aiVectorKey > akeyScaling;
};
@@ -191,175 +186,175 @@ struct Animation
/** Helper structure to represent the inheritance information of an ASE node */
struct InheritanceInfo
{
- //! Default constructor
- InheritanceInfo()
- {
- // set the inheritance flag for all axes by default to true
- for (unsigned int i = 0; i < 3;++i)
- abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
- }
-
- //! Inherit the parent's position?, axis order is x,y,z
- bool abInheritPosition[3];
-
- //! Inherit the parent's rotation?, axis order is x,y,z
- bool abInheritRotation[3];
-
- //! Inherit the parent's scaling?, axis order is x,y,z
- bool abInheritScaling[3];
+ //! Default constructor
+ InheritanceInfo()
+ {
+ // set the inheritance flag for all axes by default to true
+ for (unsigned int i = 0; i < 3;++i)
+ abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
+ }
+
+ //! Inherit the parent's position?, axis order is x,y,z
+ bool abInheritPosition[3];
+
+ //! Inherit the parent's rotation?, axis order is x,y,z
+ bool abInheritRotation[3];
+
+ //! Inherit the parent's scaling?, axis order is x,y,z
+ bool abInheritScaling[3];
};
// ---------------------------------------------------------------------------
/** Represents an ASE file node. Base class for mesh, light and cameras */
struct BaseNode
{
- enum Type {Light, Camera, Mesh, Dummy} mType;
+ enum Type {Light, Camera, Mesh, Dummy} mType;
- //! Constructor. Creates a default name for the node
- BaseNode(Type _mType)
- : mType (_mType)
- , mProcessed (false)
- {
- // generate a default name for the node
- static int iCnt = 0;
- char szTemp[128]; // should be sufficiently large
- ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
- mName = szTemp;
+ //! Constructor. Creates a default name for the node
+ explicit BaseNode(Type _mType)
+ : mType (_mType)
+ , mProcessed (false)
+ {
+ // generate a default name for the node
+ static int iCnt = 0;
+ char szTemp[128]; // should be sufficiently large
+ ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
+ mName = szTemp;
- // Set mTargetPosition to qnan
- const float qnan = get_qnan();
- mTargetPosition.x = qnan;
- }
+ // Set mTargetPosition to qnan
+ const float qnan = get_qnan();
+ mTargetPosition.x = qnan;
+ }
- //! Name of the mesh
- std::string mName;
+ //! Name of the mesh
+ std::string mName;
- //! Name of the parent of the node
- //! "" if there is no parent ...
- std::string mParent;
+ //! Name of the parent of the node
+ //! "" if there is no parent ...
+ std::string mParent;
- //! Transformation matrix of the node
- aiMatrix4x4 mTransform;
+ //! Transformation matrix of the node
+ aiMatrix4x4 mTransform;
- //! Target position (target lights and cameras)
- aiVector3D mTargetPosition;
+ //! Target position (target lights and cameras)
+ aiVector3D mTargetPosition;
- //! Specifies which axes transformations a node inherits
- //! from its parent ...
- InheritanceInfo inherit;
+ //! Specifies which axes transformations a node inherits
+ //! from its parent ...
+ InheritanceInfo inherit;
- //! Animation channels for the node
- Animation mAnim;
+ //! Animation channels for the node
+ Animation mAnim;
- //! Needed for lights and cameras: target animation channel
- //! Should contain position keys only.
- Animation mTargetAnim;
+ //! Needed for lights and cameras: target animation channel
+ //! Should contain position keys only.
+ Animation mTargetAnim;
- bool mProcessed;
+ bool mProcessed;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file mesh */
struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
{
- //! Constructor.
- Mesh()
- : BaseNode (BaseNode::Mesh)
- , bSkip (false)
- {
- // use 2 texture vertex components by default
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
- this->mNumUVComponents[c] = 2;
+ //! Constructor.
+ Mesh()
+ : BaseNode (BaseNode::Mesh)
+ , bSkip (false)
+ {
+ // use 2 texture vertex components by default
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+ this->mNumUVComponents[c] = 2;
- // setup the default material index by default
- iMaterialIndex = Face::DEFAULT_MATINDEX;
- }
+ // setup the default material index by default
+ iMaterialIndex = Face::DEFAULT_MATINDEX;
+ }
- //! List of all texture coordinate sets
- std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ //! List of all texture coordinate sets
+ std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- //! List of all vertex color sets.
- std::vector<aiColor4D> mVertexColors;
+ //! List of all vertex color sets.
+ std::vector<aiColor4D> mVertexColors;
- //! List of all bone vertices
- std::vector<BoneVertex> mBoneVertices;
+ //! List of all bone vertices
+ std::vector<BoneVertex> mBoneVertices;
- //! List of all bones
- std::vector<Bone> mBones;
+ //! List of all bones
+ std::vector<Bone> mBones;
- //! Material index of the mesh
- unsigned int iMaterialIndex;
+ //! Material index of the mesh
+ unsigned int iMaterialIndex;
- //! Number of vertex components for each UVW set
- unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ //! Number of vertex components for each UVW set
+ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- //! used internally
- bool bSkip;
+ //! used internally
+ bool bSkip;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE light source */
struct Light : public BaseNode
{
- enum LightType
- {
- OMNI,
- TARGET,
- FREE,
- DIRECTIONAL
- };
-
- //! Constructor.
- Light()
- : BaseNode (BaseNode::Light)
- , mLightType (OMNI)
- , mColor (1.f,1.f,1.f)
- , mIntensity (1.f) // light is white by default
- , mAngle (45.f)
- , mFalloff (0.f)
- {
- }
-
- LightType mLightType;
- aiColor3D mColor;
- float mIntensity;
- float mAngle; // in degrees
- float mFalloff;
+ enum LightType
+ {
+ OMNI,
+ TARGET,
+ FREE,
+ DIRECTIONAL
+ };
+
+ //! Constructor.
+ Light()
+ : BaseNode (BaseNode::Light)
+ , mLightType (OMNI)
+ , mColor (1.f,1.f,1.f)
+ , mIntensity (1.f) // light is white by default
+ , mAngle (45.f)
+ , mFalloff (0.f)
+ {
+ }
+
+ LightType mLightType;
+ aiColor3D mColor;
+ float mIntensity;
+ float mAngle; // in degrees
+ float mFalloff;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE camera */
struct Camera : public BaseNode
{
- enum CameraType
- {
- FREE,
- TARGET
- };
-
- //! Constructor
- Camera()
- : BaseNode (BaseNode::Camera)
- , mFOV (0.75f) // in radians
- , mNear (0.1f)
- , mFar (1000.f) // could be zero
- , mCameraType (FREE)
- {
- }
-
- float mFOV, mNear, mFar;
- CameraType mCameraType;
+ enum CameraType
+ {
+ FREE,
+ TARGET
+ };
+
+ //! Constructor
+ Camera()
+ : BaseNode (BaseNode::Camera)
+ , mFOV (0.75f) // in radians
+ , mNear (0.1f)
+ , mFar (1000.f) // could be zero
+ , mCameraType (FREE)
+ {
+ }
+
+ float mFOV, mNear, mFar;
+ CameraType mCameraType;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE helper object (dummy) */
struct Dummy : public BaseNode
{
- //! Constructor
- Dummy()
- : BaseNode (BaseNode::Dummy)
- {
- }
+ //! Constructor
+ Dummy()
+ : BaseNode (BaseNode::Dummy)
+ {
+ }
};
// Parameters to Parser::Parse()
@@ -367,8 +362,8 @@ struct Dummy : public BaseNode
#define AI_ASE_OLD_FILE_FORMAT 110
// Internally we're a little bit more tolerant
-#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
-#define AI_ASE_IS_OLD_FILE_FORMAT() (iFileFormat < 200)
+#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
+#define AI_ASE_IS_OLD_FILE_FORMAT() (iFileFormat < 200)
// -------------------------------------------------------------------------------
/** \brief Class to parse ASE files
@@ -378,288 +373,288 @@ class Parser
private:
- Parser() {}
+ Parser() {}
public:
- // -------------------------------------------------------------------
- //! Construct a parser from a given input file which is
- //! guaranted to be terminated with zero.
- //! @param szFile Input file
- //! @param fileFormatDefault Assumed file format version. If the
- //! file format is specified in the file the new value replaces
- //! the default value.
- Parser (const char* szFile, unsigned int fileFormatDefault);
+ // -------------------------------------------------------------------
+ //! Construct a parser from a given input file which is
+ //! guaranted to be terminated with zero.
+ //! @param szFile Input file
+ //! @param fileFormatDefault Assumed file format version. If the
+ //! file format is specified in the file the new value replaces
+ //! the default value.
+ Parser (const char* szFile, unsigned int fileFormatDefault);
- // -------------------------------------------------------------------
- //! Parses the file into the parsers internal representation
- void Parse();
+ // -------------------------------------------------------------------
+ //! Parses the file into the parsers internal representation
+ void Parse();
private:
- // -------------------------------------------------------------------
- //! Parse the *SCENE block in a file
- void ParseLV1SceneBlock();
-
- // -------------------------------------------------------------------
- //! Parse the *MESH_SOFTSKINVERTS block in a file
- void ParseLV1SoftSkinBlock();
-
- // -------------------------------------------------------------------
- //! Parse the *MATERIAL_LIST block in a file
- void ParseLV1MaterialListBlock();
-
- // -------------------------------------------------------------------
- //! Parse a *<xxx>OBJECT block in a file
- //! \param mesh Node to be filled
- void ParseLV1ObjectBlock(BaseNode& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MATERIAL blocks in a material list
- //! \param mat Material structure to be filled
- void ParseLV2MaterialBlock(Material& mat);
-
- // -------------------------------------------------------------------
- //! Parse a *NODE_TM block in a file
- //! \param mesh Node (!) object to be filled
- void ParseLV2NodeTransformBlock(BaseNode& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *TM_ANIMATION block in a file
- //! \param mesh Mesh object to be filled
- void ParseLV2AnimationBlock(BaseNode& mesh);
- void ParseLV3PosAnimationBlock(ASE::Animation& anim);
- void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
- void ParseLV3RotAnimationBlock(ASE::Animation& anim);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH block in a file
- //! \param mesh Mesh object to be filled
- void ParseLV2MeshBlock(Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *LIGHT_SETTINGS block in a file
- //! \param light Light object to be filled
- void ParseLV2LightSettingsBlock(Light& light);
-
- // -------------------------------------------------------------------
- //! Parse a *CAMERA_SETTINGS block in a file
- //! \param cam Camera object to be filled
- void ParseLV2CameraSettingsBlock(Camera& cam);
-
- // -------------------------------------------------------------------
- //! Parse the *MAP_XXXXXX blocks in a material
- //! \param map Texture structure to be filled
- void ParseLV3MapBlock(Texture& map);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_VERTEX_LIST block in a file
- //! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshVertexListBlock(
- unsigned int iNumVertices,Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_FACE_LIST block in a file
- //! \param iNumFaces Value of *MESH_NUMFACES, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshFaceListBlock(
- unsigned int iNumFaces,Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_TVERT_LIST block in a file
- //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- //! \param iChannel Output UVW channel
- void ParseLV3MeshTListBlock(
- unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_TFACELIST block in a file
- //! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- //! \param iChannel Output UVW channel
- void ParseLV3MeshTFaceListBlock(
- unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
-
- // -------------------------------------------------------------------
- //! Parse an additional mapping channel
- //! (specified via *MESH_MAPPINGCHANNEL)
- //! \param iChannel Channel index to be filled
- //! \param mesh Mesh object to be filled
- void ParseLV3MappingChannel(
- unsigned int iChannel, Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_CVERTLIST block in a file
- //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshCListBlock(
- unsigned int iNumVertices, Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_CFACELIST block in a file
- //! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
- //! Otherwise zero. This is used to check the consistency of the file.
- //! A warning is sent to the logger if the validations fails.
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshCFaceListBlock(
- unsigned int iNumFaces, Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_NORMALS block in a file
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshNormalListBlock(Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_WEIGHTSblock in a file
- //! \param mesh Mesh object to be filled
- void ParseLV3MeshWeightsBlock(Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse the bone list of a file
- //! \param mesh Mesh object to be filled
- //! \param iNumBones Number of bones in the mesh
- void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse the bone vertices list of a file
- //! \param mesh Mesh object to be filled
- //! \param iNumVertices Number of vertices to be parsed
- void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_FACE block in a file
- //! \param out receive the face data
- void ParseLV4MeshFace(ASE::Face& out);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_VERT block in a file
- //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
- //! \param apOut Output buffer (3 floats)
- //! \param rIndexOut Output index
- void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_VERT block in a file
- //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
- //! \param apOut Output buffer (3 floats)
- void ParseLV4MeshFloatTriple(float* apOut);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_TFACE block in a file
- //! (also works for MESH_CFACE)
- //! \param apOut Output buffer (3 ints)
- //! \param rIndexOut Output index
- void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
-
- // -------------------------------------------------------------------
- //! Parse a *MESH_TFACE block in a file
- //! (also works for MESH_CFACE)
- //! \param apOut Output buffer (3 ints)
- void ParseLV4MeshLongTriple(unsigned int* apOut);
-
- // -------------------------------------------------------------------
- //! Parse a single float element
- //! \param fOut Output float
- void ParseLV4MeshFloat(float& fOut);
-
- // -------------------------------------------------------------------
- //! Parse a single int element
- //! \param iOut Output integer
- void ParseLV4MeshLong(unsigned int& iOut);
-
- // -------------------------------------------------------------------
- //! Skip everything to the next: '*' or '\0'
- bool SkipToNextToken();
-
- // -------------------------------------------------------------------
- //! Skip the current section until the token after the closing }.
- //! This function handles embedded subsections correctly
- bool SkipSection();
-
- // -------------------------------------------------------------------
- //! Output a warning to the logger
- //! \param szWarn Warn message
- void LogWarning(const char* szWarn);
-
- // -------------------------------------------------------------------
- //! Output a message to the logger
- //! \param szWarn Message
- void LogInfo(const char* szWarn);
-
- // -------------------------------------------------------------------
- //! Output an error to the logger
- //! \param szWarn Error message
- void LogError(const char* szWarn);
-
- // -------------------------------------------------------------------
- //! Parse a string, enclosed in double quotation marks
- //! \param out Output string
- //! \param szName Name of the enclosing element -> used in error
- //! messages.
- //! \return false if an error occured
- bool ParseString(std::string& out,const char* szName);
+ // -------------------------------------------------------------------
+ //! Parse the *SCENE block in a file
+ void ParseLV1SceneBlock();
+
+ // -------------------------------------------------------------------
+ //! Parse the *MESH_SOFTSKINVERTS block in a file
+ void ParseLV1SoftSkinBlock();
+
+ // -------------------------------------------------------------------
+ //! Parse the *MATERIAL_LIST block in a file
+ void ParseLV1MaterialListBlock();
+
+ // -------------------------------------------------------------------
+ //! Parse a *<xxx>OBJECT block in a file
+ //! \param mesh Node to be filled
+ void ParseLV1ObjectBlock(BaseNode& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MATERIAL blocks in a material list
+ //! \param mat Material structure to be filled
+ void ParseLV2MaterialBlock(Material& mat);
+
+ // -------------------------------------------------------------------
+ //! Parse a *NODE_TM block in a file
+ //! \param mesh Node (!) object to be filled
+ void ParseLV2NodeTransformBlock(BaseNode& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *TM_ANIMATION block in a file
+ //! \param mesh Mesh object to be filled
+ void ParseLV2AnimationBlock(BaseNode& mesh);
+ void ParseLV3PosAnimationBlock(ASE::Animation& anim);
+ void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
+ void ParseLV3RotAnimationBlock(ASE::Animation& anim);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH block in a file
+ //! \param mesh Mesh object to be filled
+ void ParseLV2MeshBlock(Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *LIGHT_SETTINGS block in a file
+ //! \param light Light object to be filled
+ void ParseLV2LightSettingsBlock(Light& light);
+
+ // -------------------------------------------------------------------
+ //! Parse a *CAMERA_SETTINGS block in a file
+ //! \param cam Camera object to be filled
+ void ParseLV2CameraSettingsBlock(Camera& cam);
+
+ // -------------------------------------------------------------------
+ //! Parse the *MAP_XXXXXX blocks in a material
+ //! \param map Texture structure to be filled
+ void ParseLV3MapBlock(Texture& map);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_VERTEX_LIST block in a file
+ //! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshVertexListBlock(
+ unsigned int iNumVertices,Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_FACE_LIST block in a file
+ //! \param iNumFaces Value of *MESH_NUMFACES, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshFaceListBlock(
+ unsigned int iNumFaces,Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_TVERT_LIST block in a file
+ //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ //! \param iChannel Output UVW channel
+ void ParseLV3MeshTListBlock(
+ unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_TFACELIST block in a file
+ //! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ //! \param iChannel Output UVW channel
+ void ParseLV3MeshTFaceListBlock(
+ unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
+
+ // -------------------------------------------------------------------
+ //! Parse an additional mapping channel
+ //! (specified via *MESH_MAPPINGCHANNEL)
+ //! \param iChannel Channel index to be filled
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MappingChannel(
+ unsigned int iChannel, Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_CVERTLIST block in a file
+ //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshCListBlock(
+ unsigned int iNumVertices, Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_CFACELIST block in a file
+ //! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
+ //! Otherwise zero. This is used to check the consistency of the file.
+ //! A warning is sent to the logger if the validations fails.
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshCFaceListBlock(
+ unsigned int iNumFaces, Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_NORMALS block in a file
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshNormalListBlock(Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_WEIGHTSblock in a file
+ //! \param mesh Mesh object to be filled
+ void ParseLV3MeshWeightsBlock(Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse the bone list of a file
+ //! \param mesh Mesh object to be filled
+ //! \param iNumBones Number of bones in the mesh
+ void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse the bone vertices list of a file
+ //! \param mesh Mesh object to be filled
+ //! \param iNumVertices Number of vertices to be parsed
+ void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_FACE block in a file
+ //! \param out receive the face data
+ void ParseLV4MeshFace(ASE::Face& out);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_VERT block in a file
+ //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
+ //! \param apOut Output buffer (3 floats)
+ //! \param rIndexOut Output index
+ void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_VERT block in a file
+ //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
+ //! \param apOut Output buffer (3 floats)
+ void ParseLV4MeshFloatTriple(float* apOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_TFACE block in a file
+ //! (also works for MESH_CFACE)
+ //! \param apOut Output buffer (3 ints)
+ //! \param rIndexOut Output index
+ void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a *MESH_TFACE block in a file
+ //! (also works for MESH_CFACE)
+ //! \param apOut Output buffer (3 ints)
+ void ParseLV4MeshLongTriple(unsigned int* apOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a single float element
+ //! \param fOut Output float
+ void ParseLV4MeshFloat(float& fOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a single int element
+ //! \param iOut Output integer
+ void ParseLV4MeshLong(unsigned int& iOut);
+
+ // -------------------------------------------------------------------
+ //! Skip everything to the next: '*' or '\0'
+ bool SkipToNextToken();
+
+ // -------------------------------------------------------------------
+ //! Skip the current section until the token after the closing }.
+ //! This function handles embedded subsections correctly
+ bool SkipSection();
+
+ // -------------------------------------------------------------------
+ //! Output a warning to the logger
+ //! \param szWarn Warn message
+ void LogWarning(const char* szWarn);
+
+ // -------------------------------------------------------------------
+ //! Output a message to the logger
+ //! \param szWarn Message
+ void LogInfo(const char* szWarn);
+
+ // -------------------------------------------------------------------
+ //! Output an error to the logger
+ //! \param szWarn Error message
+ AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
+
+ // -------------------------------------------------------------------
+ //! Parse a string, enclosed in double quotation marks
+ //! \param out Output string
+ //! \param szName Name of the enclosing element -> used in error
+ //! messages.
+ //! \return false if an error occurred
+ bool ParseString(std::string& out,const char* szName);
public:
- //! Pointer to current data
- const char* filePtr;
+ //! Pointer to current data
+ const char* filePtr;
- //! background color to be passed to the viewer
- //! QNAN if none was found
- aiColor3D m_clrBackground;
+ //! background color to be passed to the viewer
+ //! QNAN if none was found
+ aiColor3D m_clrBackground;
- //! Base ambient color to be passed to all materials
- //! QNAN if none was found
- aiColor3D m_clrAmbient;
+ //! Base ambient color to be passed to all materials
+ //! QNAN if none was found
+ aiColor3D m_clrAmbient;
- //! List of all materials found in the file
- std::vector<Material> m_vMaterials;
+ //! List of all materials found in the file
+ std::vector<Material> m_vMaterials;
- //! List of all meshes found in the file
- std::vector<Mesh> m_vMeshes;
+ //! List of all meshes found in the file
+ std::vector<Mesh> m_vMeshes;
- //! List of all dummies found in the file
- std::vector<Dummy> m_vDummies;
+ //! List of all dummies found in the file
+ std::vector<Dummy> m_vDummies;
- //! List of all lights found in the file
- std::vector<Light> m_vLights;
+ //! List of all lights found in the file
+ std::vector<Light> m_vLights;
- //! List of all cameras found in the file
- std::vector<Camera> m_vCameras;
+ //! List of all cameras found in the file
+ std::vector<Camera> m_vCameras;
- //! Current line in the file
- unsigned int iLineNumber;
+ //! Current line in the file
+ unsigned int iLineNumber;
- //! First frame
- unsigned int iFirstFrame;
+ //! First frame
+ unsigned int iFirstFrame;
- //! Last frame
- unsigned int iLastFrame;
+ //! Last frame
+ unsigned int iLastFrame;
- //! Frame speed - frames per second
- unsigned int iFrameSpeed;
+ //! Frame speed - frames per second
+ unsigned int iFrameSpeed;
- //! Ticks per frame
- unsigned int iTicksPerFrame;
+ //! Ticks per frame
+ unsigned int iTicksPerFrame;
- //! true if the last character read was an end-line character
- bool bLastWasEndLine;
+ //! true if the last character read was an end-line character
+ bool bLastWasEndLine;
- //! File format version
- unsigned int iFileFormat;
+ //! File format version
+ unsigned int iFileFormat;
};
diff --git a/src/3rdparty/assimp/code/AssbinExporter.cpp b/src/3rdparty/assimp/code/AssbinExporter.cpp
new file mode 100644
index 000000000..9240d3739
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssbinExporter.cpp
@@ -0,0 +1,768 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+/** @file AssbinExporter.cpp
+ * ASSBIN exporter main code
+ */
+#include "assbin_chunks.h"
+#include <assimp/version.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include "ProcessHelper.h"
+#include "Exceptional.h"
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+#else
+# include "../contrib/zlib/zlib.h"
+#endif
+
+#include <time.h>
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp {
+
+template <typename T>
+size_t Write(IOStream * stream, const T& v)
+{
+ return stream->Write( &v, sizeof(T), 1 );
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiString
+template <>
+inline size_t Write<aiString>(IOStream * stream, const aiString& s)
+{
+ const size_t s2 = (uint32_t)s.length;
+ stream->Write(&s,4,1);
+ stream->Write(s.data,s2,1);
+ return s2+4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint32_t
+template <>
+inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
+{
+ const uint32_t t = (uint32_t)w;
+ if (w > t) {
+ // this shouldn't happen, integers in Assimp data structures never exceed 2^32
+ throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
+ }
+
+ stream->Write(&t,4,1);
+ return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint16_t
+template <>
+inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
+{
+ static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2");
+ stream->Write(&w,2,1);
+ return 2;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a float
+template <>
+inline size_t Write<float>(IOStream * stream, const float& f)
+{
+ static_assert(sizeof(float)==4, "sizeof(float)==4");
+ stream->Write(&f,4,1);
+ return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a double
+template <>
+inline size_t Write<double>(IOStream * stream, const double& f)
+{
+ static_assert(sizeof(double)==8, "sizeof(double)==8");
+ stream->Write(&f,8,1);
+ return 8;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a vec3
+template <>
+inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
+{
+ size_t t = Write<float>(stream,v.x);
+ t += Write<float>(stream,v.y);
+ t += Write<float>(stream,v.z);
+ return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a color value
+template <>
+inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
+{
+ size_t t = Write<float>(stream,v.r);
+ t += Write<float>(stream,v.g);
+ t += Write<float>(stream,v.b);
+ t += Write<float>(stream,v.a);
+ return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a quaternion
+template <>
+inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
+{
+ size_t t = Write<float>(stream,v.w);
+ t += Write<float>(stream,v.x);
+ t += Write<float>(stream,v.y);
+ t += Write<float>(stream,v.z);
+ return 16;
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize a vertex weight
+template <>
+inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
+{
+ size_t t = Write<unsigned int>(stream,v.mVertexId);
+ return t+Write<float>(stream,v.mWeight);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a mat4x4
+template <>
+inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
+{
+ for (unsigned int i = 0; i < 4;++i) {
+ for (unsigned int i2 = 0; i2 < 4;++i2) {
+ Write<float>(stream,m[i][i2]);
+ }
+ }
+ return 64;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiVectorKey
+template <>
+inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
+{
+ const size_t t = Write<double>(stream,v.mTime);
+ return t + Write<aiVector3D>(stream,v.mValue);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiQuatKey
+template <>
+inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
+{
+ const size_t t = Write<double>(stream,v.mTime);
+ return t + Write<aiQuaternion>(stream,v.mValue);
+}
+
+template <typename T>
+inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
+{
+ T minc,maxc;
+ ArrayBounds(in,size,minc,maxc);
+
+ const size_t t = Write<T>(stream,minc);
+ return t + Write<T>(stream,maxc);
+}
+
+// We use this to write out non-byte arrays so that we write using the specializations.
+// This way we avoid writing out extra bytes that potentially come from struct alignment.
+template <typename T>
+inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
+{
+ size_t n = 0;
+ for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
+ return n;
+}
+
+ // ----------------------------------------------------------------------------------
+ /** @class AssbinChunkWriter
+ * @brief Chunk writer mechanism for the .assbin file structure
+ *
+ * This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
+ * the difference being that this takes another IOStream as a "container" in the
+ * constructor, and when it is destroyed, it appends the magic number, the chunk size,
+ * and the chunk contents to the container stream. This allows relatively easy chunk
+ * chunk construction, even recursively.
+ */
+ class AssbinChunkWriter : public IOStream
+ {
+ private:
+
+ uint8_t* buffer;
+ uint32_t magic;
+ IOStream * container;
+ size_t cur_size, cursor, initial;
+
+ private:
+ // -------------------------------------------------------------------
+ void Grow(size_t need = 0)
+ {
+ size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+
+ const uint8_t* const old = buffer;
+ buffer = new uint8_t[new_size];
+
+ if (old) {
+ memcpy(buffer,old,cur_size);
+ delete[] old;
+ }
+
+ cur_size = new_size;
+ }
+
+ public:
+
+ AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096)
+ : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
+ {
+ }
+
+ virtual ~AssbinChunkWriter()
+ {
+ if (container) {
+ container->Write( &magic, sizeof(uint32_t), 1 );
+ container->Write( &cursor, sizeof(uint32_t), 1 );
+ container->Write( buffer, 1, cursor );
+ }
+ if (buffer) delete[] buffer;
+ }
+
+ void * GetBufferPointer() { return buffer; }
+
+ // -------------------------------------------------------------------
+ virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; }
+ virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; }
+ virtual size_t Tell() const { return cursor; }
+ virtual void Flush() { }
+
+ virtual size_t FileSize() const
+ {
+ return cursor;
+ }
+
+ // -------------------------------------------------------------------
+ virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
+ {
+ pSize *= pCount;
+ if (cursor + pSize > cur_size) {
+ Grow(cursor + pSize);
+ }
+
+ memcpy(buffer+cursor, pvBuffer, pSize);
+ cursor += pSize;
+
+ return pCount;
+ }
+
+ };
+
+ // ----------------------------------------------------------------------------------
+ /** @class AssbinExport
+ * @brief Assbin exporter class
+ *
+ * This class performs the .assbin exporting, and is responsible for the file layout.
+ */
+ class AssbinExport
+ {
+ private:
+ bool shortened;
+ bool compressed;
+
+ protected:
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryNode( IOStream * container, const aiNode* node)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
+
+ Write<aiString>(&chunk,node->mName);
+ Write<aiMatrix4x4>(&chunk,node->mTransformation);
+ Write<unsigned int>(&chunk,node->mNumChildren);
+ Write<unsigned int>(&chunk,node->mNumMeshes);
+
+ for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+ Write<unsigned int>(&chunk,node->mMeshes[i]);
+ }
+
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ WriteBinaryNode( &chunk, node->mChildren[i] );
+ }
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
+
+ Write<unsigned int>(&chunk,tex->mWidth);
+ Write<unsigned int>(&chunk,tex->mHeight);
+ chunk.Write( tex->achFormatHint, sizeof(char), 4 );
+
+ if(!shortened) {
+ if (!tex->mHeight) {
+ chunk.Write(tex->pcData,1,tex->mWidth);
+ }
+ else {
+ chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+ }
+ }
+
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryBone(IOStream * container, const aiBone* b)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
+
+ Write<aiString>(&chunk,b->mName);
+ Write<unsigned int>(&chunk,b->mNumWeights);
+ Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
+
+ // for the moment we write dumb min/max values for the bones, too.
+ // maybe I'll add a better, hash-like solution later
+ if (shortened) {
+ WriteBounds(&chunk,b->mWeights,b->mNumWeights);
+ } // else write as usual
+ else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights);
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
+
+ Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
+ Write<unsigned int>(&chunk,mesh->mNumVertices);
+ Write<unsigned int>(&chunk,mesh->mNumFaces);
+ Write<unsigned int>(&chunk,mesh->mNumBones);
+ Write<unsigned int>(&chunk,mesh->mMaterialIndex);
+
+ // first of all, write bits for all existent vertex components
+ unsigned int c = 0;
+ if (mesh->mVertices) {
+ c |= ASSBIN_MESH_HAS_POSITIONS;
+ }
+ if (mesh->mNormals) {
+ c |= ASSBIN_MESH_HAS_NORMALS;
+ }
+ if (mesh->mTangents && mesh->mBitangents) {
+ c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+ if (!mesh->mTextureCoords[n]) {
+ break;
+ }
+ c |= ASSBIN_MESH_HAS_TEXCOORD(n);
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+ if (!mesh->mColors[n]) {
+ break;
+ }
+ c |= ASSBIN_MESH_HAS_COLOR(n);
+ }
+ Write<unsigned int>(&chunk,c);
+
+ aiVector3D minVec, maxVec;
+ if (mesh->mVertices) {
+ if (shortened) {
+ WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
+ } // else write as usual
+ else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices);
+ }
+ if (mesh->mNormals) {
+ if (shortened) {
+ WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
+ } // else write as usual
+ else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices);
+ }
+ if (mesh->mTangents && mesh->mBitangents) {
+ if (shortened) {
+ WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
+ WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
+ } // else write as usual
+ else {
+ WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices);
+ WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices);
+ }
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+ if (!mesh->mColors[n])
+ break;
+
+ if (shortened) {
+ WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
+ } // else write as usual
+ else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices);
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+ if (!mesh->mTextureCoords[n])
+ break;
+
+ // write number of UV components
+ Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
+
+ if (shortened) {
+ WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+ } // else write as usual
+ else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+ }
+
+ // write faces. There are no floating-point calculations involved
+ // in these, so we can write a simple hash over the face data
+ // to the dump file. We generate a single 32 Bit hash for 512 faces
+ // using Assimp's standard hashing function.
+ if (shortened) {
+ unsigned int processed = 0;
+ for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
+
+ uint32_t hash = 0;
+ for (unsigned int a = 0; a < job;++a) {
+
+ const aiFace& f = mesh->mFaces[processed+a];
+ uint32_t tmp = f.mNumIndices;
+ hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+ for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+ static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff");
+ tmp = static_cast<uint32_t>( f.mIndices[i] );
+ hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+ }
+ }
+ Write<unsigned int>(&chunk,hash);
+ }
+ }
+ else // else write as usual
+ {
+ // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+ for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+ const aiFace& f = mesh->mFaces[i];
+
+ static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
+ Write<uint16_t>(&chunk,f.mNumIndices);
+
+ for (unsigned int a = 0; a < f.mNumIndices;++a) {
+ if (mesh->mNumVertices < (1u<<16)) {
+ Write<uint16_t>(&chunk,f.mIndices[a]);
+ }
+ else Write<unsigned int>(&chunk,f.mIndices[a]);
+ }
+ }
+ }
+
+ // write bones
+ if (mesh->mNumBones) {
+ for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+ const aiBone* b = mesh->mBones[a];
+ WriteBinaryBone(&chunk,b);
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
+
+ Write<aiString>(&chunk,prop->mKey);
+ Write<unsigned int>(&chunk,prop->mSemantic);
+ Write<unsigned int>(&chunk,prop->mIndex);
+
+ Write<unsigned int>(&chunk,prop->mDataLength);
+ Write<unsigned int>(&chunk,(unsigned int)prop->mType);
+ chunk.Write(prop->mData,1,prop->mDataLength);
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
+
+ Write<unsigned int>(&chunk,mat->mNumProperties);
+ for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+ WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
+
+ Write<aiString>(&chunk,nd->mNodeName);
+ Write<unsigned int>(&chunk,nd->mNumPositionKeys);
+ Write<unsigned int>(&chunk,nd->mNumRotationKeys);
+ Write<unsigned int>(&chunk,nd->mNumScalingKeys);
+ Write<unsigned int>(&chunk,nd->mPreState);
+ Write<unsigned int>(&chunk,nd->mPostState);
+
+ if (nd->mPositionKeys) {
+ if (shortened) {
+ WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+
+ } // else write as usual
+ else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+ }
+ if (nd->mRotationKeys) {
+ if (shortened) {
+ WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+
+ } // else write as usual
+ else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+ }
+ if (nd->mScalingKeys) {
+ if (shortened) {
+ WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+
+ } // else write as usual
+ else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+ }
+ }
+
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
+
+ Write<aiString>(&chunk,anim->mName);
+ Write<double>(&chunk,anim->mDuration);
+ Write<double>(&chunk,anim->mTicksPerSecond);
+ Write<unsigned int>(&chunk,anim->mNumChannels);
+
+ for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+ const aiNodeAnim* nd = anim->mChannels[a];
+ WriteBinaryNodeAnim(&chunk,nd);
+ }
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryLight( IOStream * container, const aiLight* l )
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
+
+ Write<aiString>(&chunk,l->mName);
+ Write<unsigned int>(&chunk,l->mType);
+
+ if (l->mType != aiLightSource_DIRECTIONAL) {
+ Write<float>(&chunk,l->mAttenuationConstant);
+ Write<float>(&chunk,l->mAttenuationLinear);
+ Write<float>(&chunk,l->mAttenuationQuadratic);
+ }
+
+ Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
+ Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
+ Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
+
+ if (l->mType == aiLightSource_SPOT) {
+ Write<float>(&chunk,l->mAngleInnerCone);
+ Write<float>(&chunk,l->mAngleOuterCone);
+ }
+
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
+
+ Write<aiString>(&chunk,cam->mName);
+ Write<aiVector3D>(&chunk,cam->mPosition);
+ Write<aiVector3D>(&chunk,cam->mLookAt);
+ Write<aiVector3D>(&chunk,cam->mUp);
+ Write<float>(&chunk,cam->mHorizontalFOV);
+ Write<float>(&chunk,cam->mClipPlaneNear);
+ Write<float>(&chunk,cam->mClipPlaneFar);
+ Write<float>(&chunk,cam->mAspect);
+ }
+
+ // -----------------------------------------------------------------------------------
+ void WriteBinaryScene( IOStream * container, const aiScene* scene)
+ {
+ AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
+
+ // basic scene information
+ Write<unsigned int>(&chunk,scene->mFlags);
+ Write<unsigned int>(&chunk,scene->mNumMeshes);
+ Write<unsigned int>(&chunk,scene->mNumMaterials);
+ Write<unsigned int>(&chunk,scene->mNumAnimations);
+ Write<unsigned int>(&chunk,scene->mNumTextures);
+ Write<unsigned int>(&chunk,scene->mNumLights);
+ Write<unsigned int>(&chunk,scene->mNumCameras);
+
+ // write node graph
+ WriteBinaryNode( &chunk, scene->mRootNode );
+
+ // write all meshes
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ const aiMesh* mesh = scene->mMeshes[i];
+ WriteBinaryMesh( &chunk,mesh);
+ }
+
+ // write materials
+ for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+ const aiMaterial* mat = scene->mMaterials[i];
+ WriteBinaryMaterial(&chunk,mat);
+ }
+
+ // write all animations
+ for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+ const aiAnimation* anim = scene->mAnimations[i];
+ WriteBinaryAnim(&chunk,anim);
+ }
+
+
+ // write all textures
+ for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+ const aiTexture* mesh = scene->mTextures[i];
+ WriteBinaryTexture(&chunk,mesh);
+ }
+
+ // write lights
+ for (unsigned int i = 0; i < scene->mNumLights;++i) {
+ const aiLight* l = scene->mLights[i];
+ WriteBinaryLight(&chunk,l);
+ }
+
+ // write cameras
+ for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+ const aiCamera* cam = scene->mCameras[i];
+ WriteBinaryCamera(&chunk,cam);
+ }
+
+ }
+
+ public:
+ AssbinExport()
+ : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
+ {
+ }
+
+ // -----------------------------------------------------------------------------------
+ // Write a binary model dump
+ void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+ {
+ IOStream * out = pIOSystem->Open( pFile, "wb" );
+ if (!out) return;
+
+ time_t tt = time(NULL);
+ tm* p = gmtime(&tt);
+
+ // header
+ char s[64];
+ memset( s, 0, 64 );
+#if _MSC_VER >= 1400
+ sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
+#else
+ ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
+#endif
+ out->Write( s, 44, 1 );
+ // == 44 bytes
+
+ Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
+ Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
+ Write<unsigned int>( out, aiGetVersionRevision() );
+ Write<unsigned int>( out, aiGetCompileFlags() );
+ Write<uint16_t>( out, shortened );
+ Write<uint16_t>( out, compressed );
+ // == 20 bytes
+
+ char buff[256];
+ strncpy(buff,pFile,256);
+ out->Write(buff,sizeof(char),256);
+
+ char cmd[] = "\0";
+ strncpy(buff,cmd,128);
+ out->Write(buff,sizeof(char),128);
+
+ // leave 64 bytes free for future extensions
+ memset(buff,0xcd,64);
+ out->Write(buff,sizeof(char),64);
+ // == 435 bytes
+
+ // ==== total header size: 512 bytes
+ ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
+
+ // Up to here the data is uncompressed. For compressed files, the rest
+ // is compressed using standard DEFLATE from zlib.
+ if (compressed)
+ {
+ AssbinChunkWriter uncompressedStream( NULL, 0 );
+ WriteBinaryScene( &uncompressedStream, pScene );
+
+ uLongf uncompressedSize = uncompressedStream.Tell();
+ uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
+ uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
+
+ compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
+
+ out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
+ out->Write( compressedBuffer, sizeof(char), compressedSize );
+
+ delete[] compressedBuffer;
+ }
+ else
+ {
+ WriteBinaryScene( out, pScene );
+ }
+
+ pIOSystem->Close( out );
+ }
+ };
+
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ AssbinExport exporter;
+ exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
+}
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/AssbinExporter.h b/src/3rdparty/assimp/code/AssbinExporter.h
new file mode 100644
index 000000000..4a0219c04
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssbinExporter.h
@@ -0,0 +1,49 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file AssbinExporter.h
+ * ASSBIN Exporter Main Header
+ */
+#ifndef AI_ASSBINEXPORTER_H_INC
+#define AI_ASSBINEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif
diff --git a/src/3rdparty/assimp/code/AssbinLoader.cpp b/src/3rdparty/assimp/code/AssbinLoader.cpp
new file mode 100644
index 000000000..c4261c4cb
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssbinLoader.cpp
@@ -0,0 +1,686 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+/** @file AssbinLoader.cpp
+ * @brief Implementation of the .assbin importer class
+ *
+ * see assbin_chunks.h
+ */
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+// internal headers
+#include "AssbinLoader.h"
+#include "assbin_chunks.h"
+#include "MemoryIOWrapper.h"
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
+#include <assimp/scene.h>
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+#else
+# include <contrib/zlib/zlib.h>
+#endif
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+ ".assbin Importer",
+ "Gargaj / Conspiracy",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "assbin"
+};
+
+const aiImporterDesc* AssbinImporter::GetInfo() const
+{
+ return &desc;
+}
+
+bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
+{
+ IOStream * in = pIOHandler->Open(pFile);
+ if (!in)
+ return false;
+
+ char s[32];
+ in->Read( s, sizeof(char), 32 );
+
+ pIOHandler->Close(in);
+
+ return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
+}
+
+template <typename T>
+T Read(IOStream * stream)
+{
+ T t;
+ stream->Read( &t, sizeof(T), 1 );
+ return t;
+}
+
+template <>
+aiVector3D Read<aiVector3D>(IOStream * stream)
+{
+ aiVector3D v;
+ v.x = Read<float>(stream);
+ v.y = Read<float>(stream);
+ v.z = Read<float>(stream);
+ return v;
+}
+
+template <>
+aiColor4D Read<aiColor4D>(IOStream * stream)
+{
+ aiColor4D c;
+ c.r = Read<float>(stream);
+ c.g = Read<float>(stream);
+ c.b = Read<float>(stream);
+ c.a = Read<float>(stream);
+ return c;
+}
+
+template <>
+aiQuaternion Read<aiQuaternion>(IOStream * stream)
+{
+ aiQuaternion v;
+ v.w = Read<float>(stream);
+ v.x = Read<float>(stream);
+ v.y = Read<float>(stream);
+ v.z = Read<float>(stream);
+ return v;
+}
+
+template <>
+aiString Read<aiString>(IOStream * stream)
+{
+ aiString s;
+ stream->Read(&s.length,4,1);
+ stream->Read(s.data,s.length,1);
+ s.data[s.length] = 0;
+ return s;
+}
+
+template <>
+aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
+{
+ aiVertexWeight w;
+ w.mVertexId = Read<unsigned int>(stream);
+ w.mWeight = Read<float>(stream);
+ return w;
+}
+
+template <>
+aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
+{
+ aiMatrix4x4 m;
+ for (unsigned int i = 0; i < 4;++i) {
+ for (unsigned int i2 = 0; i2 < 4;++i2) {
+ m[i][i2] = Read<float>(stream);
+ }
+ }
+ return m;
+}
+
+template <>
+aiVectorKey Read<aiVectorKey>(IOStream * stream)
+{
+ aiVectorKey v;
+ v.mTime = Read<double>(stream);
+ v.mValue = Read<aiVector3D>(stream);
+ return v;
+}
+
+template <>
+aiQuatKey Read<aiQuatKey>(IOStream * stream)
+{
+ aiQuatKey v;
+ v.mTime = Read<double>(stream);
+ v.mValue = Read<aiQuaternion>(stream);
+ return v;
+}
+
+template <typename T>
+void ReadArray(IOStream * stream, T * out, unsigned int size)
+{
+ for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
+}
+
+template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n )
+{
+ // not sure what to do here, the data isn't really useful.
+ stream->Seek( sizeof(T) * n, aiOrigin_CUR );
+}
+
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ *node = new aiNode();
+
+ (*node)->mName = Read<aiString>(stream);
+ (*node)->mTransformation = Read<aiMatrix4x4>(stream);
+ (*node)->mNumChildren = Read<unsigned int>(stream);
+ (*node)->mNumMeshes = Read<unsigned int>(stream);
+
+ if ((*node)->mNumMeshes)
+ {
+ (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
+ for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
+ (*node)->mMeshes[i] = Read<unsigned int>(stream);
+ }
+ }
+
+ if ((*node)->mNumChildren)
+ {
+ (*node)->mChildren = new aiNode*[(*node)->mNumChildren];
+ for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
+ ReadBinaryNode( stream, &(*node)->mChildren[i] );
+ }
+ }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ b->mName = Read<aiString>(stream);
+ b->mNumWeights = Read<unsigned int>(stream);
+ b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
+
+ // for the moment we write dumb min/max values for the bones, too.
+ // maybe I'll add a better, hash-like solution later
+ if (shortened)
+ {
+ ReadBounds(stream,b->mWeights,b->mNumWeights);
+ } // else write as usual
+ else
+ {
+ b->mWeights = new aiVertexWeight[b->mNumWeights];
+ ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
+ }
+}
+
+
+void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ mesh->mPrimitiveTypes = Read<unsigned int>(stream);
+ mesh->mNumVertices = Read<unsigned int>(stream);
+ mesh->mNumFaces = Read<unsigned int>(stream);
+ mesh->mNumBones = Read<unsigned int>(stream);
+ mesh->mMaterialIndex = Read<unsigned int>(stream);
+
+ // first of all, write bits for all existent vertex components
+ unsigned int c = Read<unsigned int>(stream);
+
+ if (c & ASSBIN_MESH_HAS_POSITIONS)
+ {
+ if (shortened) {
+ ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
+ } // else write as usual
+ else
+ {
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
+ }
+ }
+ if (c & ASSBIN_MESH_HAS_NORMALS)
+ {
+ if (shortened) {
+ ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
+ } // else write as usual
+ else
+ {
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+ ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
+ }
+ }
+ if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS)
+ {
+ if (shortened) {
+ ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
+ ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
+ } // else write as usual
+ else
+ {
+ mesh->mTangents = new aiVector3D[mesh->mNumVertices];
+ ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
+ mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
+ ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
+ }
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n)
+ {
+ if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
+ break;
+
+ if (shortened)
+ {
+ ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
+ } // else write as usual
+ else
+ {
+ mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
+ ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
+ }
+ }
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+ {
+ if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
+ break;
+
+ // write number of UV components
+ mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
+
+ if (shortened) {
+ ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+ } // else write as usual
+ else
+ {
+ mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+ ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+ }
+ }
+
+ // write faces. There are no floating-point calculations involved
+ // in these, so we can write a simple hash over the face data
+ // to the dump file. We generate a single 32 Bit hash for 512 faces
+ // using Assimp's standard hashing function.
+ if (shortened) {
+ Read<unsigned int>(stream);
+ }
+ else // else write as usual
+ {
+ // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+ for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+ aiFace& f = mesh->mFaces[i];
+
+ static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
+ f.mNumIndices = Read<uint16_t>(stream);
+ f.mIndices = new unsigned int[f.mNumIndices];
+
+ for (unsigned int a = 0; a < f.mNumIndices;++a) {
+ if (mesh->mNumVertices < (1u<<16))
+ {
+ f.mIndices[a] = Read<uint16_t>(stream);
+ }
+ else
+ {
+ f.mIndices[a] = Read<unsigned int>(stream);
+ }
+ }
+ }
+ }
+
+ // write bones
+ if (mesh->mNumBones) {
+ mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
+ for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+ mesh->mBones[a] = new aiBone();
+ ReadBinaryBone(stream,mesh->mBones[a]);
+ }
+ }
+}
+
+void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ prop->mKey = Read<aiString>(stream);
+ prop->mSemantic = Read<unsigned int>(stream);
+ prop->mIndex = Read<unsigned int>(stream);
+
+ prop->mDataLength = Read<unsigned int>(stream);
+ prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
+ prop->mData = new char [ prop->mDataLength ];
+ stream->Read(prop->mData,1,prop->mDataLength);
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
+ if (mat->mNumProperties)
+ {
+ if (mat->mProperties)
+ {
+ delete[] mat->mProperties;
+ }
+ mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
+ for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+ mat->mProperties[i] = new aiMaterialProperty();
+ ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ nd->mNodeName = Read<aiString>(stream);
+ nd->mNumPositionKeys = Read<unsigned int>(stream);
+ nd->mNumRotationKeys = Read<unsigned int>(stream);
+ nd->mNumScalingKeys = Read<unsigned int>(stream);
+ nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
+ nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
+
+ if (nd->mNumPositionKeys) {
+ if (shortened) {
+ ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+
+ } // else write as usual
+ else {
+ nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+ ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+ }
+ }
+ if (nd->mNumRotationKeys) {
+ if (shortened) {
+ ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+
+ } // else write as usual
+ else
+ {
+ nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+ ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+ }
+ }
+ if (nd->mNumScalingKeys) {
+ if (shortened) {
+ ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+
+ } // else write as usual
+ else
+ {
+ nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+ ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ anim->mName = Read<aiString> (stream);
+ anim->mDuration = Read<double> (stream);
+ anim->mTicksPerSecond = Read<double> (stream);
+ anim->mNumChannels = Read<unsigned int>(stream);
+
+ if (anim->mNumChannels)
+ {
+ anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
+ for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+ anim->mChannels[a] = new aiNodeAnim();
+ ReadBinaryNodeAnim(stream,anim->mChannels[a]);
+ }
+ }
+}
+
+void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ tex->mWidth = Read<unsigned int>(stream);
+ tex->mHeight = Read<unsigned int>(stream);
+ stream->Read( tex->achFormatHint, sizeof(char), 4 );
+
+ if(!shortened) {
+ if (!tex->mHeight) {
+ tex->pcData = new aiTexel[ tex->mWidth ];
+ stream->Read(tex->pcData,1,tex->mWidth);
+ }
+ else {
+ tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
+ stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+ }
+ }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ l->mName = Read<aiString>(stream);
+ l->mType = (aiLightSourceType)Read<unsigned int>(stream);
+
+ if (l->mType != aiLightSource_DIRECTIONAL) {
+ l->mAttenuationConstant = Read<float>(stream);
+ l->mAttenuationLinear = Read<float>(stream);
+ l->mAttenuationQuadratic = Read<float>(stream);
+ }
+
+ l->mColorDiffuse = Read<aiColor3D>(stream);
+ l->mColorSpecular = Read<aiColor3D>(stream);
+ l->mColorAmbient = Read<aiColor3D>(stream);
+
+ if (l->mType == aiLightSource_SPOT) {
+ l->mAngleInnerCone = Read<float>(stream);
+ l->mAngleOuterCone = Read<float>(stream);
+ }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ cam->mName = Read<aiString>(stream);
+ cam->mPosition = Read<aiVector3D>(stream);
+ cam->mLookAt = Read<aiVector3D>(stream);
+ cam->mUp = Read<aiVector3D>(stream);
+ cam->mHorizontalFOV = Read<float>(stream);
+ cam->mClipPlaneNear = Read<float>(stream);
+ cam->mClipPlaneFar = Read<float>(stream);
+ cam->mAspect = Read<float>(stream);
+}
+
+void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
+{
+ uint32_t chunkID = Read<uint32_t>(stream);
+ ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
+ /*uint32_t size =*/ Read<uint32_t>(stream);
+
+ scene->mFlags = Read<unsigned int>(stream);
+ scene->mNumMeshes = Read<unsigned int>(stream);
+ scene->mNumMaterials = Read<unsigned int>(stream);
+ scene->mNumAnimations = Read<unsigned int>(stream);
+ scene->mNumTextures = Read<unsigned int>(stream);
+ scene->mNumLights = Read<unsigned int>(stream);
+ scene->mNumCameras = Read<unsigned int>(stream);
+
+ // Read node graph
+ scene->mRootNode = new aiNode[1];
+ ReadBinaryNode( stream, &scene->mRootNode );
+
+ // Read all meshes
+ if (scene->mNumMeshes)
+ {
+ scene->mMeshes = new aiMesh*[scene->mNumMeshes];
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ scene->mMeshes[i] = new aiMesh();
+ ReadBinaryMesh( stream,scene->mMeshes[i]);
+ }
+ }
+
+ // Read materials
+ if (scene->mNumMaterials)
+ {
+ scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
+ for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+ scene->mMaterials[i] = new aiMaterial();
+ ReadBinaryMaterial(stream,scene->mMaterials[i]);
+ }
+ }
+
+ // Read all animations
+ if (scene->mNumAnimations)
+ {
+ scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
+ for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+ scene->mAnimations[i] = new aiAnimation();
+ ReadBinaryAnim(stream,scene->mAnimations[i]);
+ }
+ }
+
+ // Read all textures
+ if (scene->mNumTextures)
+ {
+ scene->mTextures = new aiTexture*[scene->mNumTextures];
+ for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+ scene->mTextures[i] = new aiTexture();
+ ReadBinaryTexture(stream,scene->mTextures[i]);
+ }
+ }
+
+ // Read lights
+ if (scene->mNumLights)
+ {
+ scene->mLights = new aiLight*[scene->mNumLights];
+ for (unsigned int i = 0; i < scene->mNumLights;++i) {
+ scene->mLights[i] = new aiLight();
+ ReadBinaryLight(stream,scene->mLights[i]);
+ }
+ }
+
+ // Read cameras
+ if (scene->mNumCameras)
+ {
+ scene->mCameras = new aiCamera*[scene->mNumCameras];
+ for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+ scene->mCameras[i] = new aiCamera();
+ ReadBinaryCamera(stream,scene->mCameras[i]);
+ }
+ }
+
+}
+
+void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
+{
+ IOStream * stream = pIOHandler->Open(pFile,"rb");
+ if (!stream)
+ return;
+
+ stream->Seek( 44, aiOrigin_CUR ); // signature
+
+ /*unsigned int versionMajor =*/ Read<unsigned int>(stream);
+ /*unsigned int versionMinor =*/ Read<unsigned int>(stream);
+ /*unsigned int versionRevision =*/ Read<unsigned int>(stream);
+ /*unsigned int compileFlags =*/ Read<unsigned int>(stream);
+
+ shortened = Read<uint16_t>(stream) > 0;
+ compressed = Read<uint16_t>(stream) > 0;
+
+ if (shortened)
+ throw DeadlyImportError( "Shortened binaries are not supported!" );
+
+ stream->Seek( 256, aiOrigin_CUR ); // original filename
+ stream->Seek( 128, aiOrigin_CUR ); // options
+ stream->Seek( 64, aiOrigin_CUR ); // padding
+
+ if (compressed)
+ {
+ uLongf uncompressedSize = Read<uint32_t>(stream);
+ uLongf compressedSize = stream->FileSize() - stream->Tell();
+
+ unsigned char * compressedData = new unsigned char[ compressedSize ];
+ stream->Read( compressedData, 1, compressedSize );
+
+ unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
+
+ uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
+
+ MemoryIOStream io( uncompressedData, uncompressedSize );
+
+ ReadBinaryScene(&io,pScene);
+
+ delete[] uncompressedData;
+ delete[] compressedData;
+ }
+ else
+ {
+ ReadBinaryScene(stream,pScene);
+ }
+
+ pIOHandler->Close(stream);
+}
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
diff --git a/src/3rdparty/assimp/code/AssbinLoader.h b/src/3rdparty/assimp/code/AssbinLoader.h
new file mode 100644
index 000000000..e8c8dd0cb
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssbinLoader.h
@@ -0,0 +1,105 @@
+
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file AssbinLoader.h
+ * @brief .assbin File format loader
+ */
+#ifndef AI_ASSBINIMPORTER_H_INC
+#define AI_ASSBINIMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include <assimp/types.h>
+
+struct aiMesh;
+struct aiNode;
+struct aiBone;
+struct aiMaterial;
+struct aiMaterialProperty;
+struct aiNodeAnim;
+struct aiAnimation;
+struct aiTexture;
+struct aiLight;
+struct aiCamera;
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------------
+/** Importer class for 3D Studio r3 and r4 3DS files
+ */
+class AssbinImporter : public BaseImporter
+{
+private:
+ bool shortened;
+ bool compressed;
+protected:
+
+public:
+ virtual bool CanRead(
+ const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const;
+ virtual const aiImporterDesc* GetInfo() const;
+ virtual void InternReadFile(
+ const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ );
+ void ReadBinaryScene( IOStream * stream, aiScene* pScene );
+ void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+ void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
+ void ReadBinaryBone( IOStream * stream, aiBone* bone );
+ void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
+ void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
+ void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
+ void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
+ void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
+ void ReadBinaryLight( IOStream * stream, aiLight* l );
+ void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
+};
+
+} // end of namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+#endif // AI_ASSBINIMPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/Assimp.cpp b/src/3rdparty/assimp/code/Assimp.cpp
index e5e696098..8507c8641 100644
--- a/src/3rdparty/assimp/code/Assimp.cpp
+++ b/src/3rdparty/assimp/code/Assimp.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -42,54 +42,68 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Plain-C API
*/
-#include "AssimpPCH.h"
-#include "../include/assimp/cimport.h"
+#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 "GenericProperty.h"
#include "CInterfaceIOWrapper.h"
#include "Importer.h"
+#include "Exceptional.h"
+#include "ScenePrivate.h"
+#include "BaseImporter.h"
+#include <list>
// ------------------------------------------------------------------------------------------------
#ifndef ASSIMP_BUILD_SINGLETHREADED
-# include <boost/thread/thread.hpp>
-# include <boost/thread/mutex.hpp>
+# include <thread>
+# include <mutex>
#endif
// ------------------------------------------------------------------------------------------------
using namespace Assimp;
namespace Assimp
{
- // underlying structure for aiPropertyStore
- typedef BatchLoader::PropertyMap PropertyMap;
+ // 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 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;
+ /** 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 all active log streams */
+ static LogStreamMap gActiveLogStreams;
- /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
- static PredefLogStreamMap gPredefinedStreams;
+ /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
+ static PredefLogStreamMap gPredefinedStreams;
- /** Error message of the last failed import process */
- static std::string gLastErrorString;
+ /** Error message of the last failed import process */
+ static std::string gLastErrorString;
- /** Verbose logging active or not? */
- static aiBool gVerboseLogging = false;
-}
+ /** 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 logstream map */
-static boost::mutex gLogStreamMutex;
+/** Global mutex to manage the access to the log-stream map */
+static std::mutex gLogStreamMutex;
#endif
@@ -98,512 +112,589 @@ static boost::mutex gLogStreamMutex;
class LogToCallbackRedirector : public LogStream
{
public:
- LogToCallbackRedirector(const aiLogStream& s)
- : stream (s) {
- ai_assert(NULL != s.callback);
- }
+ explicit LogToCallbackRedirector(const aiLogStream& s)
+ : stream (s) {
+ ai_assert(NULL != s.callback);
+ }
- ~LogToCallbackRedirector() {
+ ~LogToCallbackRedirector() {
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(gLogStreamMutex);
+ 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.
+ // (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);
+ PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
+ gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
- if (it != gPredefinedStreams.end()) {
- delete *it;
- gPredefinedStreams.erase(it);
- }
- }
+ if (it != gPredefinedStreams.end()) {
+ delete *it;
+ gPredefinedStreams.erase(it);
+ }
+ }
- /** @copydoc LogStream::write */
- void write(const char* message) {
- stream.callback(message,stream.user);
- }
+ /** @copydoc LogStream::write */
+ void write(const char* message) {
+ stream.callback(message,stream.user);
+ }
private:
- aiLogStream stream;
+ aiLogStream stream;
};
// ------------------------------------------------------------------------------------------------
void ReportSceneNotFoundError()
{
- DefaultLogger::get()->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");
+ DefaultLogger::get()->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");
- assert(false);
+ assert(false);
}
// ------------------------------------------------------------------------------------------------
-// Reads the given file and returns its content.
+// Reads the given file and returns its content.
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
{
- return aiImportFileEx(pFile,pFlags,NULL);
+ return aiImportFileEx(pFile,pFlags,NULL);
}
// ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS)
{
- return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
-}
-
+ return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
+}
+
// ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
- aiFileIO* pFS,
- const aiPropertyStore* props)
+const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
+ aiFileIO* pFS,
+ const aiPropertyStore* props)
{
- ai_assert(NULL != pFile);
+ ai_assert(NULL != pFile);
- const aiScene* scene = NULL;
- ASSIMP_BEGIN_EXCEPTION_REGION();
+ const aiScene* scene = NULL;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
- // create an Importer for this file
- Assimp::Importer* imp = new Assimp::Importer();
+ // 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) );
- }
+ // 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);
+ // 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;
- }
+ // 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;
+ // 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)
+const aiScene* aiImportFileFromMemory(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint)
{
- return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
+ 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)
+const aiScene* aiImportFileFromMemoryWithProperties(
+ const char* pBuffer,
+ unsigned int pLength,
+ unsigned int pFlags,
+ const char* pHint,
+ const aiPropertyStore* props)
{
- ai_assert(NULL != pBuffer && 0 != pLength);
+ ai_assert( NULL != pBuffer );
+ ai_assert( 0 != pLength );
- const aiScene* scene = NULL;
- ASSIMP_BEGIN_EXCEPTION_REGION();
+ const aiScene* scene = NULL;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
- // create an Importer for this file
- Assimp::Importer* imp = new Assimp::Importer();
+ // 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;
- }
+ // 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);
+ // 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.
+ // 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);
+ 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)
+ unsigned int pFlags)
{
- const aiScene* sc = NULL;
-
+ const aiScene* sc = NULL;
+
- ASSIMP_BEGIN_EXCEPTION_REGION();
+ ASSIMP_BEGIN_EXCEPTION_REGION();
- // find the importer associated with this data
- const ScenePrivateData* priv = ScenePriv(pScene);
- if( !priv || !priv->mOrigImporter) {
- ReportSceneNotFoundError();
- return NULL;
- }
+ // find the importer associated with this data
+ const ScenePrivateData* priv = ScenePriv(pScene);
+ if( !priv || !priv->mOrigImporter) {
+ ReportSceneNotFoundError();
+ return NULL;
+ }
- sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
+ sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
- if (!sc) {
- aiReleaseImport(pScene);
- return NULL;
- }
+ if (!sc) {
+ aiReleaseImport(pScene);
+ return NULL;
+ }
- ASSIMP_END_EXCEPTION_REGION(const aiScene*);
- return sc;
+ 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 && NULL != dt);
- LogStream* s = (LogStream*)dt;
+ ai_assert( NULL != msg );
+ ai_assert( NULL != dt );
+ LogStream* s = (LogStream*)dt;
- s->write(msg);
+ s->write(msg);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
{
- aiLogStream sout;
+ 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_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();
+ ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(gLogStreamMutex);
+ std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif
- LogStream* lg = new LogToCallbackRedirector(*stream);
- gActiveLogStreams[*stream] = lg;
+ 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);
+ 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();
+ ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(gLogStreamMutex);
+ std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif
- // find the logstream 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;
+ // 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);
+ gActiveLogStreams.erase( it);
- if (gActiveLogStreams.empty()) {
- DefaultLogger::kill();
- }
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_SUCCESS;
+ if (gActiveLogStreams.empty()) {
+ DefaultLogger::kill();
+ }
+ ASSIMP_END_EXCEPTION_REGION(aiReturn);
+ return AI_SUCCESS;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiDetachAllLogStreams(void)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
+ ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(gLogStreamMutex);
+ std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif
- for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
- DefaultLogger::get()->detatchStream( it->second );
- delete it->second;
- }
- gActiveLogStreams.clear();
- DefaultLogger::kill();
- ASSIMP_END_EXCEPTION_REGION(void);
+ 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;
+ 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.
+// Returns the error text of the last failed import process.
const char* aiGetErrorString()
{
- return gLastErrorString.c_str();
+ 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.
+// 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();
+ 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;
+ // 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;
+ 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();
+ 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);
+ // FIXME: no need to create a temporary Importer instance just for that ..
+ Assimp::Importer tmp;
+ tmp.GetExtensionList(*szOut);
- ASSIMP_END_EXCEPTION_REGION(void);
+ ASSIMP_END_EXCEPTION_REGION(void);
}
// ------------------------------------------------------------------------------------------------
// Get the memory requirements for a particular import.
void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
- C_STRUCT aiMemoryInfo* in)
+ C_STRUCT aiMemoryInfo* in)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
+ ASSIMP_BEGIN_EXCEPTION_REGION();
- // find the importer associated with this data
- const ScenePrivateData* priv = ScenePriv(pIn);
- if( !priv || !priv->mOrigImporter) {
- ReportSceneNotFoundError();
- return;
- }
+ // 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);
+ return priv->mOrigImporter->GetMemoryRequirements(*in);
+ ASSIMP_END_EXCEPTION_REGION(void);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
{
- return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
+ return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
}
-
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
{
- delete reinterpret_cast<PropertyMap*>(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,NULL);
- ASSIMP_END_EXCEPTION_REGION(void);
+ 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, float value)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
- SetGenericProperty<float>(pp->floats,szName,value,NULL);
- ASSIMP_END_EXCEPTION_REGION(void);
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
+ SetGenericProperty<float>(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)
+ 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()),NULL);
- ASSIMP_END_EXCEPTION_REGION(void);
+ 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)
+ const C_STRUCT aiMatrix4x4* mat)
{
- if (!mat) {
- return;
- }
- ASSIMP_BEGIN_EXCEPTION_REGION();
- PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
- SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat,NULL);
- ASSIMP_END_EXCEPTION_REGION(void);
+ 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 && NULL != mat);
- *quat = aiQuaternion(*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)
+ aiQuaternion* rotation,
+ aiVector3D* position)
{
- ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat);
- mat->Decompose(*scaling,*rotation,*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();
+ ai_assert(NULL != mat);
+ mat->Transpose();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
{
- ai_assert(NULL != mat);
- mat->Transpose();
+ ai_assert(NULL != mat);
+ mat->Transpose();
}
// ------------------------------------------------------------------------------------------------
// Vector transformation
-ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
- const aiMatrix3x3* mat)
+ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
+ const aiMatrix3x3* mat)
{
- ai_assert(NULL != mat && NULL != vec);
- *vec *= (*mat);
+ ai_assert( NULL != mat );
+ ai_assert( NULL != vec);
+ *vec *= (*mat);
}
// ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
- const aiMatrix4x4* mat)
+ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
+ const aiMatrix4x4* mat)
{
- ai_assert(NULL != mat && NULL != vec);
- *vec *= (*mat);
+ ai_assert( NULL != mat );
+ ai_assert( NULL != vec );
+
+ *vec *= (*mat);
}
// ------------------------------------------------------------------------------------------------
// Matrix multiplication
ASSIMP_API void aiMultiplyMatrix4(
- aiMatrix4x4* dst,
- const aiMatrix4x4* src)
+ aiMatrix4x4* dst,
+ const aiMatrix4x4* src)
{
- ai_assert(NULL != dst && NULL != src);
- *dst = (*dst) * (*src);
+ ai_assert( NULL != dst );
+ ai_assert( NULL != src );
+ *dst = (*dst) * (*src);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMultiplyMatrix3(
- aiMatrix3x3* dst,
- const aiMatrix3x3* src)
+ aiMatrix3x3* dst,
+ const aiMatrix3x3* src)
{
- ai_assert(NULL != dst && NULL != src);
- *dst = (*dst) * (*src);
+ ai_assert( NULL != dst );
+ ai_assert( NULL != src );
+ *dst = (*dst) * (*src);
}
// ------------------------------------------------------------------------------------------------
// Matrix identity
ASSIMP_API void aiIdentityMatrix3(
- aiMatrix3x3* mat)
+ aiMatrix3x3* mat)
{
- ai_assert(NULL != mat);
- *mat = aiMatrix3x3();
+ ai_assert(NULL != mat);
+ *mat = aiMatrix3x3();
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiIdentityMatrix4(
- aiMatrix4x4* mat)
+ aiMatrix4x4* mat)
{
- ai_assert(NULL != mat);
- *mat = aiMatrix4x4();
+ 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;
+}
+// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/AssimpCExport.cpp b/src/3rdparty/assimp/code/AssimpCExport.cpp
index 1f806f133..c5f26fc47 100644
--- a/src/3rdparty/assimp/code/AssimpCExport.cpp
+++ b/src/3rdparty/assimp/code/AssimpCExport.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,85 +43,112 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Assimp C export interface. See Exporter.cpp for some notes.
*/
-#include "AssimpPCH.h"
-
#ifndef ASSIMP_BUILD_NO_EXPORT
-#include "CInterfaceIOWrapper.h"
+#include "CInterfaceIOWrapper.h"
#include "SceneCombiner.h"
+#include "ScenePrivate.h"
+#include <assimp/Exporter.hpp>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
ASSIMP_API size_t aiGetExportFormatCount(void)
{
- return Exporter().GetExportFormatCount();
+ return Exporter().GetExportFormatCount();
}
// ------------------------------------------------------------------------------------------------
-ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
+ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
{
- return Exporter().GetExportFormatDescription(pIndex);
+ // 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;
- }
+ if (!pOut || !pIn) {
+ return;
+ }
- SceneCombiner::CopyScene(pOut,pIn,true);
- ScenePriv(*pOut)->mIsCopy = true;
+ 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;
+ // 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);
+ 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;
+ Exporter exp;
- if (pIO) {
- exp.SetIOHandler(new CIOSystemWrapper(pIO));
- }
- return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
+ 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;
+ 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;
+ delete pData;
}
#endif // !ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/AssimpPCH.cpp b/src/3rdparty/assimp/code/AssimpPCH.cpp
deleted file mode 100644
index 1f61feb2c..000000000
--- a/src/3rdparty/assimp/code/AssimpPCH.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-
-// Actually just a dummy, used by the compiler to build the precompiled header.
-
-#include "AssimpPCH.h"
-#include "./../include/assimp/version.h"
-
-static const unsigned int MajorVersion = 3;
-static const unsigned int MinorVersion = 1;
-
-// --------------------------------------------------------------------------------
-// Legal information string - dont'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) 2008-2010, assimp team\n"
-"License under the terms and conditions of the 3-clause BSD license\n"
-"http://assimp.sourceforge.net\n"
-;
-
-// ------------------------------------------------------------------------------------------------
-// Get legal string
-ASSIMP_API const char* aiGetLegalString () {
- return LEGAL_INFORMATION;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp minor version
-ASSIMP_API unsigned int aiGetVersionMinor () {
- return MinorVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp major version
-ASSIMP_API unsigned int aiGetVersionMajor () {
- return MajorVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-// 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;
-}
-
-// include current build revision, which is even updated from time to time -- :-)
-#include "revision.h"
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API unsigned int aiGetVersionRevision ()
-{
- return GitVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::aiScene()
- : mFlags(0)
- , mRootNode(NULL)
- , mNumMeshes(0)
- , mMeshes(NULL)
- , mNumMaterials(0)
- , mMaterials(NULL)
- , mNumAnimations(0)
- , mAnimations(NULL)
- , mNumTextures(0)
- , mTextures(NULL)
- , mNumLights(0)
- , mLights(NULL)
- , mNumCameras(0)
- , mCameras(NULL)
- , mPrivate(new Assimp::ScenePrivateData())
- {
- }
-
-// ------------------------------------------------------------------------------------------------
-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;
-
- delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
-}
-
diff --git a/src/3rdparty/assimp/code/AssimpPCH.h b/src/3rdparty/assimp/code/AssimpPCH.h
deleted file mode 100644
index 8fe30f31b..000000000
--- a/src/3rdparty/assimp/code/AssimpPCH.h
+++ /dev/null
@@ -1,166 +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 AssimpPCH.h
- * PCH master include. Every unit in Assimp has to include it.
- */
-
-#ifndef ASSIMP_PCH_INCLUDED
-#define ASSIMP_PCH_INCLUDED
-#define ASSIMP_INTERNAL_BUILD
-
-// ----------------------------------------------------------------------------------------
-/* General compile config taken from defs.h. It is important that the user compiles
- * using exactly the same settings in defs.h. Settings in AssimpPCH.h may differ,
- * they won't affect the public API.
- */
-#include "../include/assimp/defs.h"
-
-// Include our stdint.h replacement header for MSVC, take the global header for gcc/mingw
-#if defined( _MSC_VER) && (_MSC_VER < 1600)
-# include "../include/assimp/Compiler/pstdint.h"
-#else
-# include <stdint.h>
-#endif
-
-/* Undefine the min/max macros defined by some platform headers (namely Windows.h) to
- * avoid obvious conflicts with std::min() and std::max().
- */
-#undef min
-#undef max
-
-/* Concatenate two tokens after evaluating them
- */
-#define _AI_CONCAT(a,b) a ## b
-#define AI_CONCAT(a,b) _AI_CONCAT(a,b)
-
-/* Helper macro to set a pointer to NULL in debug builds
- */
-#if (defined ASSIMP_BUILD_DEBUG)
-# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
-#else
-# define AI_DEBUG_INVALIDATE_PTR(x)
-#endif
-
-/* Beginning with MSVC8 some C string manipulation functions are mapped to their _safe_
- * counterparts (e.g. _itoa_s). This avoids a lot of trouble with deprecation warnings.
- */
-#if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
-# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
-#endif
-
-/* size_t to unsigned int, possible loss of data. The compiler is right with his warning
- * but this loss of data won't be a problem for us. So shut up, little boy.
- */
-#ifdef _MSC_VER
-# pragma warning (disable : 4267)
-#endif
-
-// ----------------------------------------------------------------------------------------
-/* Actually that's not required for MSVC. It is included somewhere in the deeper parts of
- * the MSVC STL but it's necessary for proper build with STLport.
- */
-#include <ctype.h>
-
-#ifdef Q_OS_QNX
-#include <stdio.h>
-#endif
-
-// Runtime/STL headers
-#include <vector>
-#include <list>
-#include <map>
-#include <set>
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <stack>
-#include <queue>
-#include <iostream>
-#include <algorithm>
-#include <numeric>
-#include <new>
-#include <cstdio>
-#include <limits.h>
-#include <memory>
-
-// Boost headers
-#include <boost/pointer_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/shared_array.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/format.hpp>
-#include <boost/foreach.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/lexical_cast.hpp>
-
-// Public ASSIMP headers
-#include "../include/assimp/DefaultLogger.hpp"
-#include "../include/assimp/IOStream.hpp"
-#include "../include/assimp/IOSystem.hpp"
-#include "../include/assimp/scene.h"
-#include "../include/assimp/importerdesc.h"
-#include "../include/assimp/postprocess.h"
-#include "../include/assimp/Importer.hpp"
-#include "../include/assimp/Exporter.hpp"
-
-// Internal utility headers
-#include "BaseImporter.h"
-#include "StringComparison.h"
-#include "StreamReader.h"
-#include "qnan.h"
-#include "ScenePrivate.h"
-
-
-// We need those constants, workaround for any platforms where nobody defined them yet
-#if (!defined SIZE_MAX)
-# define SIZE_MAX (~((size_t)0))
-#endif
-
-#if (!defined UINT_MAX)
-# define UINT_MAX (~((unsigned int)0))
-#endif
-
-
-#endif // !! ASSIMP_PCH_INCLUDED
diff --git a/src/3rdparty/assimp/code/AssxmlExporter.cpp b/src/3rdparty/assimp/code/AssxmlExporter.cpp
new file mode 100644
index 000000000..cf18837f5
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssxmlExporter.cpp
@@ -0,0 +1,648 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+/** @file AssxmlExporter.cpp
+ * ASSXML exporter main code
+ */
+#include <stdarg.h>
+#include "./../include/assimp/version.h"
+#include "ProcessHelper.h"
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+#else
+# include <contrib/zlib/zlib.h>
+#endif
+
+#include <time.h>
+#include <stdio.h>
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp {
+
+namespace AssxmlExport {
+
+// -----------------------------------------------------------------------------------
+static int ioprintf( IOStream * io, const char *format, ... ) {
+ using namespace std;
+ if ( nullptr == io ) {
+ return -1;
+ }
+
+ static const int Size = 4096;
+ char sz[ Size ];
+ size_t len( strlen( format ) );
+ ::memset( sz, '\0', Size );
+ va_list va;
+ va_start( va, format );
+ int nSize = vsnprintf( sz, Size-1, format, va );
+ ai_assert( nSize < Size );
+ va_end( va );
+
+ io->Write( sz, sizeof(char), nSize );
+
+ return nSize;
+}
+
+// -----------------------------------------------------------------------------------
+// Convert a name to standard XML format
+static void ConvertName(aiString& out, const aiString& in) {
+ out.length = 0;
+ for (unsigned int i = 0; i < in.length; ++i) {
+ switch (in.data[i]) {
+ case '<':
+ out.Append("&lt;");break;
+ case '>':
+ out.Append("&gt;");break;
+ case '&':
+ out.Append("&amp;");break;
+ case '\"':
+ out.Append("&quot;");break;
+ case '\'':
+ out.Append("&apos;");break;
+ default:
+ out.data[out.length++] = in.data[i];
+ }
+ }
+ out.data[out.length] = 0;
+}
+
+// -----------------------------------------------------------------------------------
+// Write a single node as text dump
+static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) {
+ char prefix[512];
+ for (unsigned int i = 0; i < depth;++i)
+ prefix[i] = '\t';
+ prefix[depth] = '\0';
+
+ const aiMatrix4x4& m = node->mTransformation;
+
+ aiString name;
+ ConvertName(name,node->mName);
+ ioprintf(io,"%s<Node name=\"%s\"> \n"
+ "%s\t<Matrix4> \n"
+ "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "%s\t</Matrix4> \n",
+ prefix,name.data,prefix,
+ prefix,m.a1,m.a2,m.a3,m.a4,
+ prefix,m.b1,m.b2,m.b3,m.b4,
+ prefix,m.c1,m.c2,m.c3,m.c4,
+ prefix,m.d1,m.d2,m.d3,m.d4,prefix);
+
+ if (node->mNumMeshes) {
+ ioprintf(io, "%s\t<MeshRefs num=\"%i\">\n%s\t",
+ prefix,node->mNumMeshes,prefix);
+
+ for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+ ioprintf(io,"%i ",node->mMeshes[i]);
+ }
+ ioprintf(io,"\n%s\t</MeshRefs>\n",prefix);
+ }
+
+ if (node->mNumChildren) {
+ ioprintf(io,"%s\t<NodeList num=\"%i\">\n",
+ prefix,node->mNumChildren);
+
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ WriteNode(node->mChildren[i],io,depth+2);
+ }
+ ioprintf(io,"%s\t</NodeList>\n",prefix);
+ }
+ ioprintf(io,"%s</Node>\n",prefix);
+}
+
+
+// -----------------------------------------------------------------------------------
+// Some chuncks of text will need to be encoded for XML
+// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
+static std::string encodeXML(const std::string& data) {
+ std::string buffer;
+ buffer.reserve(data.size());
+ for(size_t pos = 0; pos != data.size(); ++pos) {
+ switch(data[pos]) {
+ case '&': buffer.append("&amp;"); break;
+ case '\"': buffer.append("&quot;"); break;
+ case '\'': buffer.append("&apos;"); break;
+ case '<': buffer.append("&lt;"); break;
+ case '>': buffer.append("&gt;"); break;
+ default: buffer.append(&data[pos], 1); break;
+ }
+ }
+ return buffer;
+}
+
+// -----------------------------------------------------------------------------------
+// Write a text model dump
+static
+void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
+ time_t tt = ::time( NULL );
+ tm* p = ::gmtime( &tt );
+ ai_assert( nullptr != p );
+
+ // write header
+ std::string header(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<ASSIMP format_id=\"1\">\n\n"
+ "<!-- XML Model dump produced by assimp dump\n"
+ " Library version: %i.%i.%i\n"
+ " %s\n"
+ "-->"
+ " \n\n"
+ "<Scene flags=\"%d\" postprocessing=\"%i\">\n"
+ );
+
+ const unsigned int majorVersion( aiGetVersionMajor() );
+ const unsigned int minorVersion( aiGetVersionMinor() );
+ const unsigned int rev( aiGetVersionRevision() );
+ const char *curtime( asctime( p ) );
+ ioprintf( io, header.c_str(), majorVersion, minorVersion, rev, curtime, scene->mFlags, 0 );
+
+ // write the node graph
+ WriteNode(scene->mRootNode, io, 0);
+
+#if 0
+ // write cameras
+ for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+ aiCamera* cam = scene->mCameras[i];
+ ConvertName(name,cam->mName);
+
+ // camera header
+ ioprintf(io,"\t<Camera parent=\"%s\">\n"
+ "\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Float name=\"fov\" > %f </Float>\n"
+ "\t\t<Float name=\"aspect\" > %f </Float>\n"
+ "\t\t<Float name=\"near_clip\" > %f </Float>\n"
+ "\t\t<Float name=\"far_clip\" > %f </Float>\n"
+ "\t</Camera>\n",
+ name.data,
+ cam->mUp.x,cam->mUp.y,cam->mUp.z,
+ cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
+ cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
+ cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
+ }
+
+ // write lights
+ for (unsigned int i = 0; i < scene->mNumLights;++i) {
+ aiLight* l = scene->mLights[i];
+ ConvertName(name,l->mName);
+
+ // light header
+ ioprintf(io,"\t<Light parent=\"%s\"> type=\"%s\"\n"
+ "\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n",
+ name.data,
+ (l->mType == aiLightSource_DIRECTIONAL ? "directional" :
+ (l->mType == aiLightSource_POINT ? "point" : "spot" )),
+ l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
+ l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
+ l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
+
+ if (l->mType != aiLightSource_DIRECTIONAL) {
+ ioprintf(io,
+ "\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
+ "\t\t<Float name=\"atten_cst\" > %f </Float>\n"
+ "\t\t<Float name=\"atten_lin\" > %f </Float>\n"
+ "\t\t<Float name=\"atten_sqr\" > %f </Float>\n",
+ l->mPosition.x,l->mPosition.y,l->mPosition.z,
+ l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
+ }
+
+ if (l->mType != aiLightSource_POINT) {
+ ioprintf(io,
+ "\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n",
+ l->mDirection.x,l->mDirection.y,l->mDirection.z);
+ }
+
+ if (l->mType == aiLightSource_SPOT) {
+ ioprintf(io,
+ "\t\t<Float name=\"cone_out\" > %f </Float>\n"
+ "\t\t<Float name=\"cone_inn\" > %f </Float>\n",
+ l->mAngleOuterCone,l->mAngleInnerCone);
+ }
+ ioprintf(io,"\t</Light>\n");
+ }
+#endif
+ aiString name;
+
+ // write textures
+ if (scene->mNumTextures) {
+ ioprintf(io,"<TextureList num=\"%i\">\n",scene->mNumTextures);
+ for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+ aiTexture* tex = scene->mTextures[i];
+ bool compressed = (tex->mHeight == 0);
+
+ // mesh header
+ ioprintf(io,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n",
+ (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight),
+ (compressed ? "true" : "false"));
+
+ if (compressed) {
+ ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth);
+
+ if (!shortened) {
+ for (unsigned int n = 0; n < tex->mWidth;++n) {
+ ioprintf(io,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]);
+ if (n && !(n % 50)) {
+ ioprintf(io,"\n");
+ }
+ }
+ }
+ }
+ else if (!shortened){
+ ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4);
+
+ // const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1;
+ for (unsigned int y = 0; y < tex->mHeight;++y) {
+ for (unsigned int x = 0; x < tex->mWidth;++x) {
+ aiTexel* tx = tex->pcData + y*tex->mWidth+x;
+ unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a;
+ ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
+
+ // group by four for readability
+ if ( 0 == ( x + y*tex->mWidth ) % 4 ) {
+ ioprintf( io, "\n" );
+ }
+ }
+ }
+ }
+ ioprintf(io,"\t\t</Data>\n\t</Texture>\n");
+ }
+ ioprintf(io,"</TextureList>\n");
+ }
+
+ // write materials
+ if (scene->mNumMaterials) {
+ ioprintf(io,"<MaterialList num=\"%i\">\n",scene->mNumMaterials);
+ for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+ const aiMaterial* mat = scene->mMaterials[i];
+
+ ioprintf(io,"\t<Material>\n");
+ ioprintf(io,"\t\t<MatPropertyList num=\"%i\">\n",mat->mNumProperties);
+ for (unsigned int n = 0; n < mat->mNumProperties;++n) {
+
+ const aiMaterialProperty* prop = mat->mProperties[n];
+ const char* sz = "";
+ if (prop->mType == aiPTI_Float) {
+ sz = "float";
+ }
+ else if (prop->mType == aiPTI_Integer) {
+ sz = "integer";
+ }
+ else if (prop->mType == aiPTI_String) {
+ sz = "string";
+ }
+ else if (prop->mType == aiPTI_Buffer) {
+ sz = "binary_buffer";
+ }
+
+ ioprintf(io,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"",
+ prop->mKey.data, sz,
+ ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex);
+
+ if (prop->mType == aiPTI_Float) {
+ ioprintf(io," size=\"%i\">\n\t\t\t\t",
+ static_cast<int>(prop->mDataLength/sizeof(float)));
+
+ for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
+ ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float))));
+ }
+ }
+ else if (prop->mType == aiPTI_Integer) {
+ ioprintf(io," size=\"%i\">\n\t\t\t\t",
+ static_cast<int>(prop->mDataLength/sizeof(int)));
+
+ for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
+ ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int))));
+ }
+ }
+ else if (prop->mType == aiPTI_Buffer) {
+ ioprintf(io," size=\"%i\">\n\t\t\t\t",
+ static_cast<int>(prop->mDataLength));
+
+ for (unsigned int p = 0; p < prop->mDataLength;++p) {
+ ioprintf(io,"%2x ",prop->mData[p]);
+ if (p && 0 == p%30) {
+ ioprintf(io,"\n\t\t\t\t");
+ }
+ }
+ }
+ else if (prop->mType == aiPTI_String) {
+ ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */);
+ }
+ ioprintf(io,"\n\t\t\t</MatProperty>\n");
+ }
+ ioprintf(io,"\t\t</MatPropertyList>\n");
+ ioprintf(io,"\t</Material>\n");
+ }
+ ioprintf(io,"</MaterialList>\n");
+ }
+
+ // write animations
+ if (scene->mNumAnimations) {
+ ioprintf(io,"<AnimationList num=\"%i\">\n",scene->mNumAnimations);
+ for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+ aiAnimation* anim = scene->mAnimations[i];
+
+ // anim header
+ ConvertName(name,anim->mName);
+ ioprintf(io,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n",
+ name.data, anim->mDuration, anim->mTicksPerSecond);
+
+ // write bone animation channels
+ if (anim->mNumChannels) {
+ ioprintf(io,"\t\t<NodeAnimList num=\"%i\">\n",anim->mNumChannels);
+ for (unsigned int n = 0; n < anim->mNumChannels;++n) {
+ aiNodeAnim* nd = anim->mChannels[n];
+
+ // node anim header
+ ConvertName(name,nd->mNodeName);
+ ioprintf(io,"\t\t\t<NodeAnim node=\"%s\">\n",name.data);
+
+ if (!shortened) {
+ // write position keys
+ if (nd->mNumPositionKeys) {
+ ioprintf(io,"\t\t\t\t<PositionKeyList num=\"%i\">\n",nd->mNumPositionKeys);
+ for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) {
+ aiVectorKey* vc = nd->mPositionKeys+a;
+ ioprintf(io,"\t\t\t\t\t<PositionKey time=\"%e\">\n"
+ "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n",
+ vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
+ }
+ ioprintf(io,"\t\t\t\t</PositionKeyList>\n");
+ }
+
+ // write scaling keys
+ if (nd->mNumScalingKeys) {
+ ioprintf(io,"\t\t\t\t<ScalingKeyList num=\"%i\">\n",nd->mNumScalingKeys);
+ for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) {
+ aiVectorKey* vc = nd->mScalingKeys+a;
+ ioprintf(io,"\t\t\t\t\t<ScalingKey time=\"%e\">\n"
+ "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n",
+ vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
+ }
+ ioprintf(io,"\t\t\t\t</ScalingKeyList>\n");
+ }
+
+ // write rotation keys
+ if (nd->mNumRotationKeys) {
+ ioprintf(io,"\t\t\t\t<RotationKeyList num=\"%i\">\n",nd->mNumRotationKeys);
+ for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
+ aiQuatKey* vc = nd->mRotationKeys+a;
+ ioprintf(io,"\t\t\t\t\t<RotationKey time=\"%e\">\n"
+ "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n",
+ vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w);
+ }
+ ioprintf(io,"\t\t\t\t</RotationKeyList>\n");
+ }
+ }
+ ioprintf(io,"\t\t\t</NodeAnim>\n");
+ }
+ ioprintf(io,"\t\t</NodeAnimList>\n");
+ }
+ ioprintf(io,"\t</Animation>\n");
+ }
+ ioprintf(io,"</AnimationList>\n");
+ }
+
+ // write meshes
+ if (scene->mNumMeshes) {
+ ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes);
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ aiMesh* mesh = scene->mMeshes[i];
+ // const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1;
+
+ // mesh header
+ ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
+ (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""),
+ (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""),
+ (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""),
+ (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""),
+ mesh->mMaterialIndex);
+
+ // bones
+ if (mesh->mNumBones) {
+ ioprintf(io,"\t\t<BoneList num=\"%i\">\n",mesh->mNumBones);
+
+ for (unsigned int n = 0; n < mesh->mNumBones;++n) {
+ aiBone* bone = mesh->mBones[n];
+
+ ConvertName(name,bone->mName);
+ // bone header
+ ioprintf(io,"\t\t\t<Bone name=\"%s\">\n"
+ "\t\t\t\t<Matrix4> \n"
+ "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+ "\t\t\t\t</Matrix4> \n",
+ name.data,
+ bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4,
+ bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4,
+ bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4,
+ bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4);
+
+ if (!shortened && bone->mNumWeights) {
+ ioprintf(io,"\t\t\t\t<WeightList num=\"%i\">\n",bone->mNumWeights);
+
+ // bone weights
+ for (unsigned int a = 0; a < bone->mNumWeights;++a) {
+ aiVertexWeight* wght = bone->mWeights+a;
+
+ ioprintf(io,"\t\t\t\t\t<Weight index=\"%i\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n",
+ wght->mVertexId,wght->mWeight);
+ }
+ ioprintf(io,"\t\t\t\t</WeightList>\n");
+ }
+ ioprintf(io,"\t\t\t</Bone>\n");
+ }
+ ioprintf(io,"\t\t</BoneList>\n");
+ }
+
+ // faces
+ if (!shortened && mesh->mNumFaces) {
+ ioprintf(io,"\t\t<FaceList num=\"%i\">\n",mesh->mNumFaces);
+ for (unsigned int n = 0; n < mesh->mNumFaces; ++n) {
+ aiFace& f = mesh->mFaces[n];
+ ioprintf(io,"\t\t\t<Face num=\"%i\">\n"
+ "\t\t\t\t",f.mNumIndices);
+
+ for (unsigned int j = 0; j < f.mNumIndices;++j)
+ ioprintf(io,"%i ",f.mIndices[j]);
+
+ ioprintf(io,"\n\t\t\t</Face>\n");
+ }
+ ioprintf(io,"\t\t</FaceList>\n");
+ }
+
+ // vertex positions
+ if (mesh->HasPositions()) {
+ ioprintf(io,"\t\t<Positions num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+ if (!shortened) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+ mesh->mVertices[n].x,
+ mesh->mVertices[n].y,
+ mesh->mVertices[n].z);
+ }
+ }
+ ioprintf(io,"\t\t</Positions>\n");
+ }
+
+ // vertex normals
+ if (mesh->HasNormals()) {
+ ioprintf(io,"\t\t<Normals num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+ if (!shortened) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+ mesh->mNormals[n].x,
+ mesh->mNormals[n].y,
+ mesh->mNormals[n].z);
+ }
+ }
+ else {
+ }
+ ioprintf(io,"\t\t</Normals>\n");
+ }
+
+ // vertex tangents and bitangents
+ if (mesh->HasTangentsAndBitangents()) {
+ ioprintf(io,"\t\t<Tangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+ if (!shortened) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+ mesh->mTangents[n].x,
+ mesh->mTangents[n].y,
+ mesh->mTangents[n].z);
+ }
+ }
+ ioprintf(io,"\t\t</Tangents>\n");
+
+ ioprintf(io,"\t\t<Bitangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+ if (!shortened) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+ mesh->mBitangents[n].x,
+ mesh->mBitangents[n].y,
+ mesh->mBitangents[n].z);
+ }
+ }
+ ioprintf(io,"\t\t</Bitangents>\n");
+ }
+
+ // texture coordinates
+ for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+ if (!mesh->mTextureCoords[a])
+ break;
+
+ ioprintf(io,"\t\t<TextureCoords num=\"%i\" set=\"%i\" num_components=\"%i\"> \n",mesh->mNumVertices,
+ a,mesh->mNumUVComponents[a]);
+
+ if (!shortened) {
+ if (mesh->mNumUVComponents[a] == 3) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+ mesh->mTextureCoords[a][n].x,
+ mesh->mTextureCoords[a][n].y,
+ mesh->mTextureCoords[a][n].z);
+ }
+ }
+ else {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f\n",
+ mesh->mTextureCoords[a][n].x,
+ mesh->mTextureCoords[a][n].y);
+ }
+ }
+ }
+ ioprintf(io,"\t\t</TextureCoords>\n");
+ }
+
+ // vertex colors
+ for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
+ if (!mesh->mColors[a])
+ break;
+ ioprintf(io,"\t\t<Colors num=\"%i\" set=\"%i\" num_components=\"4\"> \n",mesh->mNumVertices,a);
+ if (!shortened) {
+ for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+ ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n",
+ mesh->mColors[a][n].r,
+ mesh->mColors[a][n].g,
+ mesh->mColors[a][n].b,
+ mesh->mColors[a][n].a);
+ }
+ }
+ ioprintf(io,"\t\t</Colors>\n");
+ }
+ ioprintf(io,"\t</Mesh>\n");
+ }
+ ioprintf(io,"</MeshList>\n");
+ }
+ ioprintf(io,"</Scene>\n</ASSIMP>");
+}
+
+} // end of namespace AssxmlExport
+
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ IOStream * out = pIOSystem->Open( pFile, "wt" );
+ if (!out) return;
+
+ bool shortened = false;
+ AssxmlExport::WriteDump( pScene, out, shortened );
+
+ pIOSystem->Close( out );
+}
+
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSXML_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/AssxmlExporter.h b/src/3rdparty/assimp/code/AssxmlExporter.h
new file mode 100644
index 000000000..ba9921f70
--- /dev/null
+++ b/src/3rdparty/assimp/code/AssxmlExporter.h
@@ -0,0 +1,49 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file AssxmlExporter.h
+ * ASSXML Exporter Main Header
+ */
+#ifndef AI_ASSXMLEXPORTER_H_INC
+#define AI_ASSXMLEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif
diff --git a/src/3rdparty/assimp/code/B3DImporter.cpp b/src/3rdparty/assimp/code/B3DImporter.cpp
index a2908d446..1b9ba1433 100644
--- a/src/3rdparty/assimp/code/B3DImporter.cpp
+++ b/src/3rdparty/assimp/code/B3DImporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,32 +43,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the b3d importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers
#include "B3DImporter.h"
#include "TextureTransform.h"
#include "ConvertToLHProcess.h"
+#include "StringUtils.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/anim.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
using namespace Assimp;
using namespace std;
static const aiImporterDesc desc = {
- "BlitzBasic 3D Importer",
- "",
- "",
- "http://www.blitzbasic.com/",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "b3d"
+ "BlitzBasic 3D Importer",
+ "",
+ "",
+ "http://www.blitzbasic.com/",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "b3d"
};
// (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings
-#ifdef _MSC_VER
+#ifdef _MSC_VER
# pragma warning (disable: 4018)
#endif
@@ -77,611 +84,613 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
- size_t pos=pFile.find_last_of( '.' );
- if( pos==string::npos ) return false;
+ size_t pos=pFile.find_last_of( '.' );
+ if( pos==string::npos ) return false;
- string ext=pFile.substr( pos+1 );
- if( ext.size()!=3 ) return false;
+ string ext=pFile.substr( pos+1 );
+ if( ext.size()!=3 ) return false;
- return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
+ return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* B3DImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
#ifdef DEBUG_B3D
- extern "C"{ void _stdcall AllocConsole(); }
+ extern "C"{ void _stdcall AllocConsole(); }
#endif
// ------------------------------------------------------------------------------------------------
void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){
#ifdef DEBUG_B3D
- AllocConsole();
- freopen( "conin$","r",stdin );
- freopen( "conout$","w",stdout );
- freopen( "conout$","w",stderr );
- cout<<"Hello world from the B3DImporter!"<<endl;
+ AllocConsole();
+ freopen( "conin$","r",stdin );
+ freopen( "conout$","w",stdout );
+ freopen( "conout$","w",stderr );
+ cout<<"Hello world from the B3DImporter!"<<endl;
#endif
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
- // check whether the .b3d file is large enough to contain
- // at least one chunk.
- size_t fileSize = file->FileSize();
- if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
+ // check whether the .b3d file is large enough to contain
+ // at least one chunk.
+ size_t fileSize = file->FileSize();
+ if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
- _pos=0;
- _buf.resize( fileSize );
- file->Read( &_buf[0],1,fileSize );
- _stack.clear();
+ _pos=0;
+ _buf.resize( fileSize );
+ file->Read( &_buf[0],1,fileSize );
+ _stack.clear();
- ReadBB3D( pScene );
+ ReadBB3D( pScene );
}
// ------------------------------------------------------------------------------------------------
-void B3DImporter::Oops(){
- throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
+AI_WONT_RETURN void B3DImporter::Oops(){
+ throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
}
// ------------------------------------------------------------------------------------------------
-void B3DImporter::Fail( string str ){
+AI_WONT_RETURN void B3DImporter::Fail( string str ){
#ifdef DEBUG_B3D
- cout<<"Error in B3D file data: "<<str<<endl;
+ cout<<"Error in B3D file data: "<<str<<endl;
#endif
- throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
+ throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
}
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadByte(){
- if( _pos<_buf.size() ) return _buf[_pos++];
- Fail( "EOF" );
- return 0;
+ if( _pos<_buf.size() ) return _buf[_pos++];
+ Fail( "EOF" );
+ return 0;
}
// ------------------------------------------------------------------------------------------------
int B3DImporter::ReadInt(){
- if( _pos+4<=_buf.size() ){
- int n=*(int*)&_buf[_pos];
- _pos+=4;
- return n;
- }
- Fail( "EOF" );
- return 0;
+ if( _pos+4<=_buf.size() ){
+ int n=*(int*)&_buf[_pos];
+ _pos+=4;
+ return n;
+ }
+ Fail( "EOF" );
+ return 0;
}
// ------------------------------------------------------------------------------------------------
float B3DImporter::ReadFloat(){
- if( _pos+4<=_buf.size() ){
- float n=*(float*)&_buf[_pos];
- _pos+=4;
- return n;
- }
- Fail( "EOF" );
- return 0.0f;
+ if( _pos+4<=_buf.size() ){
+ float n=*(float*)&_buf[_pos];
+ _pos+=4;
+ return n;
+ }
+ Fail( "EOF" );
+ return 0.0f;
}
// ------------------------------------------------------------------------------------------------
aiVector2D B3DImporter::ReadVec2(){
- float x=ReadFloat();
- float y=ReadFloat();
- return aiVector2D( x,y );
+ float x=ReadFloat();
+ float y=ReadFloat();
+ return aiVector2D( x,y );
}
// ------------------------------------------------------------------------------------------------
aiVector3D B3DImporter::ReadVec3(){
- float x=ReadFloat();
- float y=ReadFloat();
- float z=ReadFloat();
- return aiVector3D( x,y,z );
+ float x=ReadFloat();
+ float y=ReadFloat();
+ float z=ReadFloat();
+ return aiVector3D( x,y,z );
}
// ------------------------------------------------------------------------------------------------
aiQuaternion B3DImporter::ReadQuat(){
- // (aramis_acg) Fix to adapt the loader to changed quat orientation
- float w=-ReadFloat();
- float x=ReadFloat();
- float y=ReadFloat();
- float z=ReadFloat();
- return aiQuaternion( w,x,y,z );
+ // (aramis_acg) Fix to adapt the loader to changed quat orientation
+ float w=-ReadFloat();
+ float x=ReadFloat();
+ float y=ReadFloat();
+ float z=ReadFloat();
+ return aiQuaternion( w,x,y,z );
}
// ------------------------------------------------------------------------------------------------
string B3DImporter::ReadString(){
- string str;
- while( _pos<_buf.size() ){
- char c=(char)ReadByte();
- if( !c ) return str;
- str+=c;
- }
- Fail( "EOF" );
- return string();
+ string str;
+ while( _pos<_buf.size() ){
+ char c=(char)ReadByte();
+ if( !c ) return str;
+ str+=c;
+ }
+ Fail( "EOF" );
+ return string();
}
// ------------------------------------------------------------------------------------------------
string B3DImporter::ReadChunk(){
- string tag;
- for( int i=0;i<4;++i ){
- tag+=char( ReadByte() );
- }
+ string tag;
+ for( int i=0;i<4;++i ){
+ tag+=char( ReadByte() );
+ }
#ifdef DEBUG_B3D
// cout<<"ReadChunk:"<<tag<<endl;
#endif
- unsigned sz=(unsigned)ReadInt();
- _stack.push_back( _pos+sz );
- return tag;
+ unsigned sz=(unsigned)ReadInt();
+ _stack.push_back( _pos+sz );
+ return tag;
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ExitChunk(){
- _pos=_stack.back();
- _stack.pop_back();
+ _pos=_stack.back();
+ _stack.pop_back();
}
// ------------------------------------------------------------------------------------------------
unsigned B3DImporter::ChunkSize(){
- return _stack.back()-_pos;
+ return _stack.back()-_pos;
}
// ------------------------------------------------------------------------------------------------
template<class T>
T *B3DImporter::to_array( const vector<T> &v ){
- if( !v.size() ) return 0;
- T *p=new T[v.size()];
- for( size_t i=0;i<v.size();++i ){
- p[i]=v[i];
- }
- return p;
+ if( v.empty() ) {
+ return 0;
+ }
+ T *p=new T[ v.size() ];
+ for( size_t i=0;i<v.size();++i ){
+ p[i]=v[i];
+ }
+ return p;
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadTEXS(){
- while( ChunkSize() ){
- string name=ReadString();
- /*int flags=*/ReadInt();
- /*int blend=*/ReadInt();
- /*aiVector2D pos=*/ReadVec2();
- /*aiVector2D scale=*/ReadVec2();
- /*float rot=*/ReadFloat();
-
- _textures.push_back( name );
- }
+ while( ChunkSize() ){
+ string name=ReadString();
+ /*int flags=*/ReadInt();
+ /*int blend=*/ReadInt();
+ /*aiVector2D pos=*/ReadVec2();
+ /*aiVector2D scale=*/ReadVec2();
+ /*float rot=*/ReadFloat();
+
+ _textures.push_back( name );
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadBRUS(){
- int n_texs=ReadInt();
- if( n_texs<0 || n_texs>8 ){
- Fail( "Bad texture count" );
- }
- while( ChunkSize() ){
- string name=ReadString();
- aiVector3D color=ReadVec3();
- float alpha=ReadFloat();
- float shiny=ReadFloat();
- /*int blend=**/ReadInt();
- int fx=ReadInt();
-
- aiMaterial *mat=new aiMaterial;
- _materials.push_back( mat );
-
- // Name
- aiString ainame( name );
- mat->AddProperty( &ainame,AI_MATKEY_NAME );
-
- // Diffuse color
- mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE );
-
- // Opacity
- mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY );
-
- // Specular color
- aiColor3D speccolor( shiny,shiny,shiny );
- mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR );
-
- // Specular power
- float specpow=shiny*128;
- mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS );
-
- // Double sided
- if( fx & 0x10 ){
- int i=1;
- mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED );
- }
-
- //Textures
- for( int i=0;i<n_texs;++i ){
- int texid=ReadInt();
- if( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){
- Fail( "Bad texture id" );
- }
- if( i==0 && texid>=0 ){
- aiString texname( _textures[texid] );
- mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
- }
- }
- }
+ int n_texs=ReadInt();
+ if( n_texs<0 || n_texs>8 ){
+ Fail( "Bad texture count" );
+ }
+ while( ChunkSize() ){
+ string name=ReadString();
+ aiVector3D color=ReadVec3();
+ float alpha=ReadFloat();
+ float shiny=ReadFloat();
+ /*int blend=**/ReadInt();
+ int fx=ReadInt();
+
+ aiMaterial *mat=new aiMaterial;
+ _materials.push_back( mat );
+
+ // Name
+ aiString ainame( name );
+ mat->AddProperty( &ainame,AI_MATKEY_NAME );
+
+ // Diffuse color
+ mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE );
+
+ // Opacity
+ mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY );
+
+ // Specular color
+ aiColor3D speccolor( shiny,shiny,shiny );
+ mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR );
+
+ // Specular power
+ float specpow=shiny*128;
+ mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS );
+
+ // Double sided
+ if( fx & 0x10 ){
+ int i=1;
+ mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED );
+ }
+
+ //Textures
+ for( int i=0;i<n_texs;++i ){
+ int texid=ReadInt();
+ if( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){
+ Fail( "Bad texture id" );
+ }
+ if( i==0 && texid>=0 ){
+ aiString texname( _textures[texid] );
+ mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadVRTS(){
- _vflags=ReadInt();
- _tcsets=ReadInt();
- _tcsize=ReadInt();
- if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){
- Fail( "Bad texcoord data" );
- }
+ _vflags=ReadInt();
+ _tcsets=ReadInt();
+ _tcsize=ReadInt();
+ if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){
+ Fail( "Bad texcoord data" );
+ }
- int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
- int n_verts=ChunkSize()/sz;
+ int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
+ int n_verts=ChunkSize()/sz;
- int v0=_vertices.size();
- _vertices.resize( v0+n_verts );
+ int v0=_vertices.size();
+ _vertices.resize( v0+n_verts );
- for( int i=0;i<n_verts;++i ){
- Vertex &v=_vertices[v0+i];
+ for( int i=0;i<n_verts;++i ){
+ Vertex &v=_vertices[v0+i];
- memset( v.bones,0,sizeof(v.bones) );
- memset( v.weights,0,sizeof(v.weights) );
+ memset( v.bones,0,sizeof(v.bones) );
+ memset( v.weights,0,sizeof(v.weights) );
- v.vertex=ReadVec3();
+ v.vertex=ReadVec3();
- if( _vflags & 1 ) v.normal=ReadVec3();
+ if( _vflags & 1 ) v.normal=ReadVec3();
- if( _vflags & 2 ) ReadQuat(); //skip v 4bytes...
+ if( _vflags & 2 ) ReadQuat(); //skip v 4bytes...
- for( int i=0;i<_tcsets;++i ){
- float t[4]={0,0,0,0};
- for( int j=0;j<_tcsize;++j ){
- t[j]=ReadFloat();
- }
- t[1]=1-t[1];
- if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
- }
- }
+ for( int i=0;i<_tcsets;++i ){
+ float t[4]={0,0,0,0};
+ for( int j=0;j<_tcsize;++j ){
+ t[j]=ReadFloat();
+ }
+ t[1]=1-t[1];
+ if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadTRIS( int v0 ){
- int matid=ReadInt();
- if( matid==-1 ){
- matid=0;
- }else if( matid<0 || matid>=(int)_materials.size() ){
+ int matid=ReadInt();
+ if( matid==-1 ){
+ matid=0;
+ }else if( matid<0 || matid>=(int)_materials.size() ){
#ifdef DEBUG_B3D
- cout<<"material id="<<matid<<endl;
+ cout<<"material id="<<matid<<endl;
#endif
- Fail( "Bad material id" );
- }
+ Fail( "Bad material id" );
+ }
- aiMesh *mesh=new aiMesh;
- _meshes.push_back( mesh );
+ aiMesh *mesh=new aiMesh;
+ _meshes.push_back( mesh );
- mesh->mMaterialIndex=matid;
- mesh->mNumFaces=0;
- mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
+ mesh->mMaterialIndex=matid;
+ mesh->mNumFaces=0;
+ mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
- int n_tris=ChunkSize()/12;
- aiFace *face=mesh->mFaces=new aiFace[n_tris];
+ int n_tris=ChunkSize()/12;
+ aiFace *face=mesh->mFaces=new aiFace[n_tris];
- for( int i=0;i<n_tris;++i ){
- int i0=ReadInt()+v0;
- int i1=ReadInt()+v0;
- int i2=ReadInt()+v0;
- if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
+ for( int i=0;i<n_tris;++i ){
+ int i0=ReadInt()+v0;
+ int i1=ReadInt()+v0;
+ int i2=ReadInt()+v0;
+ if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
#ifdef DEBUG_B3D
- cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
+ cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
#endif
- Fail( "Bad triangle index" );
- continue;
- }
- face->mNumIndices=3;
- face->mIndices=new unsigned[3];
- face->mIndices[0]=i0;
- face->mIndices[1]=i1;
- face->mIndices[2]=i2;
- ++mesh->mNumFaces;
- ++face;
- }
+ Fail( "Bad triangle index" );
+ continue;
+ }
+ face->mNumIndices=3;
+ face->mIndices=new unsigned[3];
+ face->mIndices[0]=i0;
+ face->mIndices[1]=i1;
+ face->mIndices[2]=i2;
+ ++mesh->mNumFaces;
+ ++face;
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadMESH(){
- /*int matid=*/ReadInt();
-
- int v0=_vertices.size();
-
- while( ChunkSize() ){
- string t=ReadChunk();
- if( t=="VRTS" ){
- ReadVRTS();
- }else if( t=="TRIS" ){
- ReadTRIS( v0 );
- }
- ExitChunk();
- }
+ /*int matid=*/ReadInt();
+
+ int v0=_vertices.size();
+
+ while( ChunkSize() ){
+ string t=ReadChunk();
+ if( t=="VRTS" ){
+ ReadVRTS();
+ }else if( t=="TRIS" ){
+ ReadTRIS( v0 );
+ }
+ ExitChunk();
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadBONE( int id ){
- while( ChunkSize() ){
- int vertex=ReadInt();
- float weight=ReadFloat();
- if( vertex<0 || vertex>=(int)_vertices.size() ){
- Fail( "Bad vertex index" );
- }
-
- Vertex &v=_vertices[vertex];
- int i;
- for( i=0;i<4;++i ){
- if( !v.weights[i] ){
- v.bones[i]=id;
- v.weights[i]=weight;
- break;
- }
- }
+ while( ChunkSize() ){
+ int vertex=ReadInt();
+ float weight=ReadFloat();
+ if( vertex<0 || vertex>=(int)_vertices.size() ){
+ Fail( "Bad vertex index" );
+ }
+
+ Vertex &v=_vertices[vertex];
+ int i;
+ for( i=0;i<4;++i ){
+ if( !v.weights[i] ){
+ v.bones[i]=id;
+ v.weights[i]=weight;
+ break;
+ }
+ }
#ifdef DEBUG_B3D
- if( i==4 ){
- cout<<"Too many bone weights"<<endl;
- }
+ if( i==4 ){
+ cout<<"Too many bone weights"<<endl;
+ }
#endif
- }
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){
- vector<aiVectorKey> trans,scale;
- vector<aiQuatKey> rot;
- int flags=ReadInt();
- while( ChunkSize() ){
- int frame=ReadInt();
- if( flags & 1 ){
- trans.push_back( aiVectorKey( frame,ReadVec3() ) );
- }
- if( flags & 2 ){
- scale.push_back( aiVectorKey( frame,ReadVec3() ) );
- }
- if( flags & 4 ){
- rot.push_back( aiQuatKey( frame,ReadQuat() ) );
- }
- }
-
- if( flags & 1 ){
- nodeAnim->mNumPositionKeys=trans.size();
- nodeAnim->mPositionKeys=to_array( trans );
- }
-
- if( flags & 2 ){
- nodeAnim->mNumScalingKeys=scale.size();
- nodeAnim->mScalingKeys=to_array( scale );
- }
-
- if( flags & 4 ){
- nodeAnim->mNumRotationKeys=rot.size();
- nodeAnim->mRotationKeys=to_array( rot );
- }
+ vector<aiVectorKey> trans,scale;
+ vector<aiQuatKey> rot;
+ int flags=ReadInt();
+ while( ChunkSize() ){
+ int frame=ReadInt();
+ if( flags & 1 ){
+ trans.push_back( aiVectorKey( frame,ReadVec3() ) );
+ }
+ if( flags & 2 ){
+ scale.push_back( aiVectorKey( frame,ReadVec3() ) );
+ }
+ if( flags & 4 ){
+ rot.push_back( aiQuatKey( frame,ReadQuat() ) );
+ }
+ }
+
+ if( flags & 1 ){
+ nodeAnim->mNumPositionKeys=trans.size();
+ nodeAnim->mPositionKeys=to_array( trans );
+ }
+
+ if( flags & 2 ){
+ nodeAnim->mNumScalingKeys=scale.size();
+ nodeAnim->mScalingKeys=to_array( scale );
+ }
+
+ if( flags & 4 ){
+ nodeAnim->mNumRotationKeys=rot.size();
+ nodeAnim->mRotationKeys=to_array( rot );
+ }
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadANIM(){
- /*int flags=*/ReadInt();
- int frames=ReadInt();
- float fps=ReadFloat();
+ /*int flags=*/ReadInt();
+ int frames=ReadInt();
+ float fps=ReadFloat();
- aiAnimation *anim=new aiAnimation;
- _animations.push_back( anim );
+ aiAnimation *anim=new aiAnimation;
+ _animations.push_back( anim );
- anim->mDuration=frames;
- anim->mTicksPerSecond=fps;
+ anim->mDuration=frames;
+ anim->mTicksPerSecond=fps;
}
// ------------------------------------------------------------------------------------------------
aiNode *B3DImporter::ReadNODE( aiNode *parent ){
- string name=ReadString();
- aiVector3D t=ReadVec3();
- aiVector3D s=ReadVec3();
- aiQuaternion r=ReadQuat();
-
- aiMatrix4x4 trans,scale,rot;
-
- aiMatrix4x4::Translation( t,trans );
- aiMatrix4x4::Scaling( s,scale );
- rot=aiMatrix4x4( r.GetMatrix() );
-
- aiMatrix4x4 tform=trans * rot * scale;
-
- int nodeid=_nodes.size();
-
- aiNode *node=new aiNode( name );
- _nodes.push_back( node );
-
- node->mParent=parent;
- node->mTransformation=tform;
-
- aiNodeAnim *nodeAnim=0;
- vector<unsigned> meshes;
- vector<aiNode*> children;
-
- while( ChunkSize() ){
- string t=ReadChunk();
- if( t=="MESH" ){
- int n=_meshes.size();
- ReadMESH();
- for( int i=n;i<(int)_meshes.size();++i ){
- meshes.push_back( i );
- }
- }else if( t=="BONE" ){
- ReadBONE( nodeid );
- }else if( t=="ANIM" ){
- ReadANIM();
- }else if( t=="KEYS" ){
- if( !nodeAnim ){
- nodeAnim=new aiNodeAnim;
- _nodeAnims.push_back( nodeAnim );
- nodeAnim->mNodeName=node->mName;
- }
- ReadKEYS( nodeAnim );
- }else if( t=="NODE" ){
- aiNode *child=ReadNODE( node );
- children.push_back( child );
- }
- ExitChunk();
- }
-
- node->mNumMeshes=meshes.size();
- node->mMeshes=to_array( meshes );
-
- node->mNumChildren=children.size();
- node->mChildren=to_array( children );
-
- return node;
+ string name=ReadString();
+ aiVector3D t=ReadVec3();
+ aiVector3D s=ReadVec3();
+ aiQuaternion r=ReadQuat();
+
+ aiMatrix4x4 trans,scale,rot;
+
+ aiMatrix4x4::Translation( t,trans );
+ aiMatrix4x4::Scaling( s,scale );
+ rot=aiMatrix4x4( r.GetMatrix() );
+
+ aiMatrix4x4 tform=trans * rot * scale;
+
+ int nodeid=_nodes.size();
+
+ aiNode *node=new aiNode( name );
+ _nodes.push_back( node );
+
+ node->mParent=parent;
+ node->mTransformation=tform;
+
+ aiNodeAnim *nodeAnim=0;
+ vector<unsigned> meshes;
+ vector<aiNode*> children;
+
+ while( ChunkSize() ){
+ string t=ReadChunk();
+ if( t=="MESH" ){
+ int n=_meshes.size();
+ ReadMESH();
+ for( int i=n;i<(int)_meshes.size();++i ){
+ meshes.push_back( i );
+ }
+ }else if( t=="BONE" ){
+ ReadBONE( nodeid );
+ }else if( t=="ANIM" ){
+ ReadANIM();
+ }else if( t=="KEYS" ){
+ if( !nodeAnim ){
+ nodeAnim=new aiNodeAnim;
+ _nodeAnims.push_back( nodeAnim );
+ nodeAnim->mNodeName=node->mName;
+ }
+ ReadKEYS( nodeAnim );
+ }else if( t=="NODE" ){
+ aiNode *child=ReadNODE( node );
+ children.push_back( child );
+ }
+ ExitChunk();
+ }
+
+ node->mNumMeshes=meshes.size();
+ node->mMeshes=to_array( meshes );
+
+ node->mNumChildren=children.size();
+ node->mChildren=to_array( children );
+
+ return node;
}
// ------------------------------------------------------------------------------------------------
void B3DImporter::ReadBB3D( aiScene *scene ){
- _textures.clear();
- _materials.size();
-
- _vertices.clear();
- _meshes.clear();
-
- _nodes.clear();
- _nodeAnims.clear();
- _animations.clear();
-
- string t=ReadChunk();
- if( t=="BB3D" ){
- int version=ReadInt();
-
- if (!DefaultLogger::isNullLogger()) {
- char dmp[128];
- sprintf(dmp,"B3D file format version: %i",version);
- DefaultLogger::get()->info(dmp);
- }
-
- while( ChunkSize() ){
- string t=ReadChunk();
- if( t=="TEXS" ){
- ReadTEXS();
- }else if( t=="BRUS" ){
- ReadBRUS();
- }else if( t=="NODE" ){
- ReadNODE( 0 );
- }
- ExitChunk();
- }
- }
- ExitChunk();
-
- if( !_nodes.size() ) Fail( "No nodes" );
-
- if( !_meshes.size() ) Fail( "No meshes" );
-
- //Fix nodes/meshes/bones
- for(size_t i=0;i<_nodes.size();++i ){
- aiNode *node=_nodes[i];
-
- for( size_t j=0;j<node->mNumMeshes;++j ){
- aiMesh *mesh=_meshes[node->mMeshes[j]];
-
- int n_tris=mesh->mNumFaces;
- int n_verts=mesh->mNumVertices=n_tris * 3;
-
- aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
- if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
- if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
-
- aiFace *face=mesh->mFaces;
-
- vector< vector<aiVertexWeight> > vweights( _nodes.size() );
-
- for( int i=0;i<n_verts;i+=3 ){
- for( int j=0;j<3;++j ){
- Vertex &v=_vertices[face->mIndices[j]];
-
- *mv++=v.vertex;
- if( mn ) *mn++=v.normal;
- if( mc ) *mc++=v.texcoords;
-
- face->mIndices[j]=i+j;
-
- for( int k=0;k<4;++k ){
- if( !v.weights[k] ) break;
-
- int bone=v.bones[k];
- float weight=v.weights[k];
-
- vweights[bone].push_back( aiVertexWeight(i+j,weight) );
- }
- }
- ++face;
- }
-
- vector<aiBone*> bones;
- for(size_t i=0;i<vweights.size();++i ){
- vector<aiVertexWeight> &weights=vweights[i];
- if( !weights.size() ) continue;
-
- aiBone *bone=new aiBone;
- bones.push_back( bone );
-
- aiNode *bnode=_nodes[i];
-
- bone->mName=bnode->mName;
- bone->mNumWeights=weights.size();
- bone->mWeights=to_array( weights );
-
- aiMatrix4x4 mat=bnode->mTransformation;
- while( bnode->mParent ){
- bnode=bnode->mParent;
- mat=bnode->mTransformation * mat;
- }
- bone->mOffsetMatrix=mat.Inverse();
- }
- mesh->mNumBones=bones.size();
- mesh->mBones=to_array( bones );
- }
- }
-
- //nodes
- scene->mRootNode=_nodes[0];
-
- //material
- if( !_materials.size() ){
- _materials.push_back( new aiMaterial );
- }
- scene->mNumMaterials=_materials.size();
- scene->mMaterials=to_array( _materials );
-
- //meshes
- scene->mNumMeshes=_meshes.size();
- scene->mMeshes=to_array( _meshes );
-
- //animations
- if( _animations.size()==1 && _nodeAnims.size() ){
-
- aiAnimation *anim=_animations.back();
- anim->mNumChannels=_nodeAnims.size();
- anim->mChannels=to_array( _nodeAnims );
-
- scene->mNumAnimations=_animations.size();
- scene->mAnimations=to_array( _animations );
- }
+ _textures.clear();
+ _materials.clear();
+
+ _vertices.clear();
+ _meshes.clear();
+
+ _nodes.clear();
+ _nodeAnims.clear();
+ _animations.clear();
+
+ string t=ReadChunk();
+ if( t=="BB3D" ){
+ int version=ReadInt();
+
+ if (!DefaultLogger::isNullLogger()) {
+ char dmp[128];
+ ai_snprintf(dmp, 128, "B3D file format version: %i",version);
+ DefaultLogger::get()->info(dmp);
+ }
+
+ while( ChunkSize() ){
+ string t=ReadChunk();
+ if( t=="TEXS" ){
+ ReadTEXS();
+ }else if( t=="BRUS" ){
+ ReadBRUS();
+ }else if( t=="NODE" ){
+ ReadNODE( 0 );
+ }
+ ExitChunk();
+ }
+ }
+ ExitChunk();
+
+ if( !_nodes.size() ) Fail( "No nodes" );
+
+ if( !_meshes.size() ) Fail( "No meshes" );
+
+ //Fix nodes/meshes/bones
+ for(size_t i=0;i<_nodes.size();++i ){
+ aiNode *node=_nodes[i];
+
+ for( size_t j=0;j<node->mNumMeshes;++j ){
+ aiMesh *mesh=_meshes[node->mMeshes[j]];
+
+ int n_tris=mesh->mNumFaces;
+ int n_verts=mesh->mNumVertices=n_tris * 3;
+
+ aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
+ if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
+ if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
+
+ aiFace *face=mesh->mFaces;
+
+ vector< vector<aiVertexWeight> > vweights( _nodes.size() );
+
+ for( int i=0;i<n_verts;i+=3 ){
+ for( int j=0;j<3;++j ){
+ Vertex &v=_vertices[face->mIndices[j]];
+
+ *mv++=v.vertex;
+ if( mn ) *mn++=v.normal;
+ if( mc ) *mc++=v.texcoords;
+
+ face->mIndices[j]=i+j;
+
+ for( int k=0;k<4;++k ){
+ if( !v.weights[k] ) break;
+
+ int bone=v.bones[k];
+ float weight=v.weights[k];
+
+ vweights[bone].push_back( aiVertexWeight(i+j,weight) );
+ }
+ }
+ ++face;
+ }
+
+ vector<aiBone*> bones;
+ for(size_t i=0;i<vweights.size();++i ){
+ vector<aiVertexWeight> &weights=vweights[i];
+ if( !weights.size() ) continue;
+
+ aiBone *bone=new aiBone;
+ bones.push_back( bone );
+
+ aiNode *bnode=_nodes[i];
+
+ bone->mName=bnode->mName;
+ bone->mNumWeights=weights.size();
+ bone->mWeights=to_array( weights );
+
+ aiMatrix4x4 mat=bnode->mTransformation;
+ while( bnode->mParent ){
+ bnode=bnode->mParent;
+ mat=bnode->mTransformation * mat;
+ }
+ bone->mOffsetMatrix=mat.Inverse();
+ }
+ mesh->mNumBones=bones.size();
+ mesh->mBones=to_array( bones );
+ }
+ }
+
+ //nodes
+ scene->mRootNode=_nodes[0];
+
+ //material
+ if( !_materials.size() ){
+ _materials.push_back( new aiMaterial );
+ }
+ scene->mNumMaterials=_materials.size();
+ scene->mMaterials=to_array( _materials );
+
+ //meshes
+ scene->mNumMeshes=_meshes.size();
+ scene->mMeshes=to_array( _meshes );
+
+ //animations
+ if( _animations.size()==1 && _nodeAnims.size() ){
+
+ aiAnimation *anim=_animations.back();
+ anim->mNumChannels=_nodeAnims.size();
+ anim->mChannels=to_array( _nodeAnims );
+
+ scene->mNumAnimations=_animations.size();
+ scene->mAnimations=to_array( _animations );
+ }
- // convert to RH
- MakeLeftHandedProcess makeleft;
- makeleft.Execute( scene );
+ // convert to RH
+ MakeLeftHandedProcess makeleft;
+ makeleft.Execute( scene );
- FlipWindingOrderProcess flip;
- flip.Execute( scene );
+ FlipWindingOrderProcess flip;
+ flip.Execute( scene );
}
#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/B3DImporter.h b/src/3rdparty/assimp/code/B3DImporter.h
index 7587f6dc7..92ddc0272 100644
--- a/src/3rdparty/assimp/code/B3DImporter.h
+++ b/src/3rdparty/assimp/code/B3DImporter.h
@@ -1,13 +1,12 @@
-
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -24,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,81 +43,86 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_B3DIMPORTER_H_INC
#define AI_B3DIMPORTER_H_INC
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/material.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include "BaseImporter.h"
#include <string>
#include <vector>
+struct aiNodeAnim;
+struct aiNode;
+struct aiAnimation;
+
namespace Assimp{
class B3DImporter : public BaseImporter{
public:
- virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+ virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected:
- virtual const aiImporterDesc* GetInfo () const;
- virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+ virtual const aiImporterDesc* GetInfo () const;
+ virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
private:
- int ReadByte();
- int ReadInt();
- float ReadFloat();
- aiVector2D ReadVec2();
- aiVector3D ReadVec3();
- aiQuaternion ReadQuat();
- std::string ReadString();
- std::string ReadChunk();
- void ExitChunk();
- unsigned ChunkSize();
-
- template<class T>
- T *to_array( const std::vector<T> &v );
-
- struct Vertex{
- aiVector3D vertex;
- aiVector3D normal;
- aiVector3D texcoords;
- unsigned char bones[4];
- float weights[4];
- };
-
- void Oops();
- void Fail( std::string str );
-
- void ReadTEXS();
- void ReadBRUS();
-
- void ReadVRTS();
- void ReadTRIS( int v0 );
- void ReadMESH();
- void ReadBONE( int id );
- void ReadKEYS( aiNodeAnim *nodeAnim );
- void ReadANIM();
-
- aiNode *ReadNODE( aiNode *parent );
-
- void ReadBB3D( aiScene *scene );
-
- unsigned _pos;
-// unsigned _size;
- std::vector<unsigned char> _buf;
- std::vector<unsigned> _stack;
-
- std::vector<std::string> _textures;
- std::vector<aiMaterial*> _materials;
-
- int _vflags,_tcsets,_tcsize;
- std::vector<Vertex> _vertices;
-
- std::vector<aiNode*> _nodes;
- std::vector<aiMesh*> _meshes;
- std::vector<aiNodeAnim*> _nodeAnims;
- std::vector<aiAnimation*> _animations;
+ int ReadByte();
+ int ReadInt();
+ float ReadFloat();
+ aiVector2D ReadVec2();
+ aiVector3D ReadVec3();
+ aiQuaternion ReadQuat();
+ std::string ReadString();
+ std::string ReadChunk();
+ void ExitChunk();
+ unsigned ChunkSize();
+
+ template<class T>
+ T *to_array( const std::vector<T> &v );
+
+ struct Vertex{
+ aiVector3D vertex;
+ aiVector3D normal;
+ aiVector3D texcoords;
+ unsigned char bones[4];
+ float weights[4];
+ };
+
+ AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
+ AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
+
+ void ReadTEXS();
+ void ReadBRUS();
+
+ void ReadVRTS();
+ void ReadTRIS( int v0 );
+ void ReadMESH();
+ void ReadBONE( int id );
+ void ReadKEYS( aiNodeAnim *nodeAnim );
+ void ReadANIM();
+
+ aiNode *ReadNODE( aiNode *parent );
+
+ void ReadBB3D( aiScene *scene );
+
+ unsigned _pos;
+// unsigned _size;
+ std::vector<unsigned char> _buf;
+ std::vector<unsigned> _stack;
+
+ std::vector<std::string> _textures;
+ std::vector<aiMaterial*> _materials;
+
+ int _vflags,_tcsets,_tcsize;
+ std::vector<Vertex> _vertices;
+
+ std::vector<aiNode*> _nodes;
+ std::vector<aiMesh*> _meshes;
+ std::vector<aiNodeAnim*> _nodeAnims;
+ std::vector<aiAnimation*> _animations;
};
}
diff --git a/src/3rdparty/assimp/code/BVHLoader.cpp b/src/3rdparty/assimp/code/BVHLoader.cpp
index 35a3e20ef..ca6c5d36c 100644
--- a/src/3rdparty/assimp/code/BVHLoader.cpp
+++ b/src/3rdparty/assimp/code/BVHLoader.cpp
@@ -4,12 +4,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -26,46 +26,55 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
#include "BVHLoader.h"
#include "fast_atof.h"
#include "SkeletonMeshBuilder.h"
+#include <assimp/Importer.hpp>
+#include <memory>
+#include "TinyFormatter.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
using namespace Assimp;
+using namespace Assimp::Formatter;
static const aiImporterDesc desc = {
- "BVH Importer (MoCap)",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "bvh"
+ "BVH Importer (MoCap)",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "bvh"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
BVHLoader::BVHLoader()
-: noSkeletonMesh()
+ : mLine(),
+ mAnimTickDuration(),
+ mAnimNumFrames(),
+ noSkeletonMesh()
{}
// ------------------------------------------------------------------------------------------------
@@ -74,461 +83,461 @@ BVHLoader::~BVHLoader()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
{
- // check file extension
- const std::string extension = GetExtension(pFile);
-
- if( extension == "bvh")
- return true;
-
- if ((!extension.length() || cs) && pIOHandler) {
- const char* tokens[] = {"HIERARCHY"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "bvh")
+ return true;
+
+ if ((!extension.length() || cs) && pIOHandler) {
+ const char* tokens[] = {"HIERARCHY"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
void BVHLoader::SetupProperties(const Importer* pImp)
{
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* BVHLoader::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
+// Imports the given file into the given scene structure.
void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- mFileName = pFile;
+ mFileName = pFile;
- // read file into memory
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
+ // read file into memory
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open file " + pFile + ".");
- size_t fileSize = file->FileSize();
- if( fileSize == 0)
- throw DeadlyImportError( "File is too small.");
+ size_t fileSize = file->FileSize();
+ if( fileSize == 0)
+ throw DeadlyImportError( "File is too small.");
- mBuffer.resize( fileSize);
- file->Read( &mBuffer.front(), 1, fileSize);
+ mBuffer.resize( fileSize);
+ file->Read( &mBuffer.front(), 1, fileSize);
- // start reading
- mReader = mBuffer.begin();
- mLine = 1;
- ReadStructure( pScene);
+ // start reading
+ mReader = mBuffer.begin();
+ mLine = 1;
+ ReadStructure( pScene);
- if (!noSkeletonMesh) {
- // build a dummy mesh for the skeleton so that we see something at least
- SkeletonMeshBuilder meshBuilder( pScene);
- }
+ if (!noSkeletonMesh) {
+ // build a dummy mesh for the skeleton so that we see something at least
+ SkeletonMeshBuilder meshBuilder( pScene);
+ }
- // construct an animation from all the motion data we read
- CreateAnimation( pScene);
+ // construct an animation from all the motion data we read
+ CreateAnimation( pScene);
}
// ------------------------------------------------------------------------------------------------
// Reads the file
void BVHLoader::ReadStructure( aiScene* pScene)
{
- // first comes hierarchy
- std::string header = GetNextToken();
- if( header != "HIERARCHY")
- ThrowException( "Expected header string \"HIERARCHY\".");
- ReadHierarchy( pScene);
-
- // then comes the motion data
- std::string motion = GetNextToken();
- if( motion != "MOTION")
- ThrowException( "Expected beginning of motion data \"MOTION\".");
- ReadMotion( pScene);
+ // first comes hierarchy
+ std::string header = GetNextToken();
+ if( header != "HIERARCHY")
+ ThrowException( "Expected header string \"HIERARCHY\".");
+ ReadHierarchy( pScene);
+
+ // then comes the motion data
+ std::string motion = GetNextToken();
+ if( motion != "MOTION")
+ ThrowException( "Expected beginning of motion data \"MOTION\".");
+ ReadMotion( pScene);
}
// ------------------------------------------------------------------------------------------------
// Reads the hierarchy
void BVHLoader::ReadHierarchy( aiScene* pScene)
{
- std::string root = GetNextToken();
- if( root != "ROOT")
- ThrowException( "Expected root node \"ROOT\".");
+ std::string root = GetNextToken();
+ if( root != "ROOT")
+ ThrowException( "Expected root node \"ROOT\".");
- // Go read the hierarchy from here
- pScene->mRootNode = ReadNode();
+ // Go read the hierarchy from here
+ pScene->mRootNode = ReadNode();
}
// ------------------------------------------------------------------------------------------------
// Reads a node and recursively its childs and returns the created node;
aiNode* BVHLoader::ReadNode()
{
- // first token is name
- std::string nodeName = GetNextToken();
- if( nodeName.empty() || nodeName == "{")
- ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName));
-
- // then an opening brace should follow
- std::string openBrace = GetNextToken();
- if( openBrace != "{")
- ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
- // Create a node
- aiNode* node = new aiNode( nodeName);
- std::vector<aiNode*> childNodes;
-
- // and create an bone entry for it
- mNodes.push_back( Node( node));
- Node& internNode = mNodes.back();
-
- // now read the node's contents
- while( 1)
- {
- std::string token = GetNextToken();
-
- // node offset to parent node
- if( token == "OFFSET")
- ReadNodeOffset( node);
- else if( token == "CHANNELS")
- ReadNodeChannels( internNode);
- else if( token == "JOINT")
- {
- // child node follows
- aiNode* child = ReadNode();
- child->mParent = node;
- childNodes.push_back( child);
- }
- else if( token == "End")
- {
- // The real symbol is "End Site". Second part comes in a separate token
- std::string siteToken = GetNextToken();
- if( siteToken != "Site")
- ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken));
-
- aiNode* child = ReadEndSite( nodeName);
- child->mParent = node;
- childNodes.push_back( child);
- }
- else if( token == "}")
- {
- // we're done with that part of the hierarchy
- break;
- } else
- {
- // everything else is a parse error
- ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
- }
- }
-
- // add the child nodes if there are any
- if( childNodes.size() > 0)
- {
- node->mNumChildren = childNodes.size();
- node->mChildren = new aiNode*[node->mNumChildren];
- std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
- }
-
- // and return the sub-hierarchy we built here
- return node;
+ // first token is name
+ std::string nodeName = GetNextToken();
+ if( nodeName.empty() || nodeName == "{")
+ ThrowException( format() << "Expected node name, but found \"" << nodeName << "\"." );
+
+ // then an opening brace should follow
+ std::string openBrace = GetNextToken();
+ if( openBrace != "{")
+ ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"." );
+
+ // Create a node
+ aiNode* node = new aiNode( nodeName);
+ std::vector<aiNode*> childNodes;
+
+ // and create an bone entry for it
+ mNodes.push_back( Node( node));
+ Node& internNode = mNodes.back();
+
+ // now read the node's contents
+ while( 1)
+ {
+ std::string token = GetNextToken();
+
+ // node offset to parent node
+ if( token == "OFFSET")
+ ReadNodeOffset( node);
+ else if( token == "CHANNELS")
+ ReadNodeChannels( internNode);
+ else if( token == "JOINT")
+ {
+ // child node follows
+ aiNode* child = ReadNode();
+ child->mParent = node;
+ childNodes.push_back( child);
+ }
+ else if( token == "End")
+ {
+ // The real symbol is "End Site". Second part comes in a separate token
+ std::string siteToken = GetNextToken();
+ if( siteToken != "Site")
+ ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
+
+ aiNode* child = ReadEndSite( nodeName);
+ child->mParent = node;
+ childNodes.push_back( child);
+ }
+ else if( token == "}")
+ {
+ // we're done with that part of the hierarchy
+ break;
+ } else
+ {
+ // everything else is a parse error
+ ThrowException( format() << "Unknown keyword \"" << token << "\"." );
+ }
+ }
+
+ // add the child nodes if there are any
+ if( childNodes.size() > 0)
+ {
+ node->mNumChildren = childNodes.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+ std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
+ }
+
+ // and return the sub-hierarchy we built here
+ return node;
}
// ------------------------------------------------------------------------------------------------
// Reads an end node and returns the created node.
aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
{
- // check opening brace
- std::string openBrace = GetNextToken();
- if( openBrace != "{")
- ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
- // Create a node
- aiNode* node = new aiNode( "EndSite_" + pParentName);
-
- // now read the node's contents. Only possible entry is "OFFSET"
- while( 1)
- {
- std::string token = GetNextToken();
-
- // end node's offset
- if( token == "OFFSET")
- {
- ReadNodeOffset( node);
- }
- else if( token == "}")
- {
- // we're done with the end node
- break;
- } else
- {
- // everything else is a parse error
- ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
- }
- }
-
- // and return the sub-hierarchy we built here
- return node;
+ // check opening brace
+ std::string openBrace = GetNextToken();
+ if( openBrace != "{")
+ ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\".");
+
+ // Create a node
+ aiNode* node = new aiNode( "EndSite_" + pParentName);
+
+ // now read the node's contents. Only possible entry is "OFFSET"
+ while( 1)
+ {
+ std::string token = GetNextToken();
+
+ // end node's offset
+ if( token == "OFFSET")
+ {
+ ReadNodeOffset( node);
+ }
+ else if( token == "}")
+ {
+ // we're done with the end node
+ break;
+ } else
+ {
+ // everything else is a parse error
+ ThrowException( format() << "Unknown keyword \"" << token << "\"." );
+ }
+ }
+
+ // and return the sub-hierarchy we built here
+ return node;
}
// ------------------------------------------------------------------------------------------------
// Reads a node offset for the given node
void BVHLoader::ReadNodeOffset( aiNode* pNode)
{
- // Offset consists of three floats to read
- aiVector3D offset;
- offset.x = GetNextTokenAsFloat();
- offset.y = GetNextTokenAsFloat();
- offset.z = GetNextTokenAsFloat();
-
- // build a transformation matrix from it
- pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
- 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
+ // Offset consists of three floats to read
+ aiVector3D offset;
+ offset.x = GetNextTokenAsFloat();
+ offset.y = GetNextTokenAsFloat();
+ offset.z = GetNextTokenAsFloat();
+
+ // build a transformation matrix from it
+ pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
+ 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
}
// ------------------------------------------------------------------------------------------------
// Reads the animation channels for the given node
void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode)
{
- // number of channels. Use the float reader because we're lazy
- float numChannelsFloat = GetNextTokenAsFloat();
- unsigned int numChannels = (unsigned int) numChannelsFloat;
-
- for( unsigned int a = 0; a < numChannels; a++)
- {
- std::string channelToken = GetNextToken();
-
- if( channelToken == "Xposition")
- pNode.mChannels.push_back( Channel_PositionX);
- else if( channelToken == "Yposition")
- pNode.mChannels.push_back( Channel_PositionY);
- else if( channelToken == "Zposition")
- pNode.mChannels.push_back( Channel_PositionZ);
- else if( channelToken == "Xrotation")
- pNode.mChannels.push_back( Channel_RotationX);
- else if( channelToken == "Yrotation")
- pNode.mChannels.push_back( Channel_RotationY);
- else if( channelToken == "Zrotation")
- pNode.mChannels.push_back( Channel_RotationZ);
- else
- ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken));
- }
+ // number of channels. Use the float reader because we're lazy
+ float numChannelsFloat = GetNextTokenAsFloat();
+ unsigned int numChannels = (unsigned int) numChannelsFloat;
+
+ for( unsigned int a = 0; a < numChannels; a++)
+ {
+ std::string channelToken = GetNextToken();
+
+ if( channelToken == "Xposition")
+ pNode.mChannels.push_back( Channel_PositionX);
+ else if( channelToken == "Yposition")
+ pNode.mChannels.push_back( Channel_PositionY);
+ else if( channelToken == "Zposition")
+ pNode.mChannels.push_back( Channel_PositionZ);
+ else if( channelToken == "Xrotation")
+ pNode.mChannels.push_back( Channel_RotationX);
+ else if( channelToken == "Yrotation")
+ pNode.mChannels.push_back( Channel_RotationY);
+ else if( channelToken == "Zrotation")
+ pNode.mChannels.push_back( Channel_RotationZ);
+ else
+ ThrowException( format() << "Invalid channel specifier \"" << channelToken << "\"." );
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the motion data
void BVHLoader::ReadMotion( aiScene* /*pScene*/)
{
- // Read number of frames
- std::string tokenFrames = GetNextToken();
- if( tokenFrames != "Frames:")
- ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames));
-
- float numFramesFloat = GetNextTokenAsFloat();
- mAnimNumFrames = (unsigned int) numFramesFloat;
-
- // Read frame duration
- std::string tokenDuration1 = GetNextToken();
- std::string tokenDuration2 = GetNextToken();
- if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
- ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2));
-
- mAnimTickDuration = GetNextTokenAsFloat();
-
- // resize value vectors for each node
- for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
- it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
-
- // now read all the data and store it in the corresponding node's value vector
- for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
- {
- // on each line read the values for all nodes
- for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
- {
- // get as many values as the node has channels
- for( unsigned int c = 0; c < it->mChannels.size(); ++c)
- it->mChannelValues.push_back( GetNextTokenAsFloat());
- }
-
- // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
- }
+ // Read number of frames
+ std::string tokenFrames = GetNextToken();
+ if( tokenFrames != "Frames:")
+ ThrowException( format() << "Expected frame count \"Frames:\", but found \"" << tokenFrames << "\".");
+
+ float numFramesFloat = GetNextTokenAsFloat();
+ mAnimNumFrames = (unsigned int) numFramesFloat;
+
+ // Read frame duration
+ std::string tokenDuration1 = GetNextToken();
+ std::string tokenDuration2 = GetNextToken();
+ if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
+ ThrowException( format() << "Expected frame duration \"Frame Time:\", but found \"" << tokenDuration1 << " " << tokenDuration2 << "\"." );
+
+ mAnimTickDuration = GetNextTokenAsFloat();
+
+ // resize value vectors for each node
+ for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+ it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
+
+ // now read all the data and store it in the corresponding node's value vector
+ for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
+ {
+ // on each line read the values for all nodes
+ for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+ {
+ // get as many values as the node has channels
+ for( unsigned int c = 0; c < it->mChannels.size(); ++c)
+ it->mChannelValues.push_back( GetNextTokenAsFloat());
+ }
+
+ // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
+ }
}
// ------------------------------------------------------------------------------------------------
// Retrieves the next token
std::string BVHLoader::GetNextToken()
{
- // skip any preceeding whitespace
- while( mReader != mBuffer.end())
- {
- if( !isspace( *mReader))
- break;
-
- // count lines
- if( *mReader == '\n')
- mLine++;
-
- ++mReader;
- }
-
- // collect all chars till the next whitespace. BVH is easy in respect to that.
- std::string token;
- while( mReader != mBuffer.end())
- {
- if( isspace( *mReader))
- break;
-
- token.push_back( *mReader);
- ++mReader;
-
- // little extra logic to make sure braces are counted correctly
- if( token == "{" || token == "}")
- break;
- }
-
- // empty token means end of file, which is just fine
- return token;
+ // skip any preceding whitespace
+ while( mReader != mBuffer.end())
+ {
+ if( !isspace( *mReader))
+ break;
+
+ // count lines
+ if( *mReader == '\n')
+ mLine++;
+
+ ++mReader;
+ }
+
+ // collect all chars till the next whitespace. BVH is easy in respect to that.
+ std::string token;
+ while( mReader != mBuffer.end())
+ {
+ if( isspace( *mReader))
+ break;
+
+ token.push_back( *mReader);
+ ++mReader;
+
+ // little extra logic to make sure braces are counted correctly
+ if( token == "{" || token == "}")
+ break;
+ }
+
+ // empty token means end of file, which is just fine
+ return token;
}
// ------------------------------------------------------------------------------------------------
// Reads the next token as a float
float BVHLoader::GetNextTokenAsFloat()
{
- std::string token = GetNextToken();
- if( token.empty())
- ThrowException( "Unexpected end of file while trying to read a float");
+ std::string token = GetNextToken();
+ if( token.empty())
+ ThrowException( "Unexpected end of file while trying to read a float");
- // check if the float is valid by testing if the atof() function consumed every char of the token
- const char* ctoken = token.c_str();
- float result = 0.0f;
- ctoken = fast_atoreal_move<float>( ctoken, result);
+ // check if the float is valid by testing if the atof() function consumed every char of the token
+ const char* ctoken = token.c_str();
+ float result = 0.0f;
+ ctoken = fast_atoreal_move<float>( ctoken, result);
- if( ctoken != token.c_str() + token.length())
- ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
+ if( ctoken != token.c_str() + token.length())
+ ThrowException( format() << "Expected a floating point number, but found \"" << token << "\"." );
- return result;
+ return result;
}
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
-void BVHLoader::ThrowException( const std::string& pError)
+AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
{
- throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
+ throw DeadlyImportError( format() << mFileName << ":" << mLine << " - " << pError);
}
// ------------------------------------------------------------------------------------------------
// Constructs an animation for the motion data and stores it in the given scene
void BVHLoader::CreateAnimation( aiScene* pScene)
{
- // create the animation
- pScene->mNumAnimations = 1;
- pScene->mAnimations = new aiAnimation*[1];
- aiAnimation* anim = new aiAnimation;
- pScene->mAnimations[0] = anim;
-
- // put down the basic parameters
- anim->mName.Set( "Motion");
- anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
- anim->mDuration = double( mAnimNumFrames - 1);
-
- // now generate the tracks for all nodes
- anim->mNumChannels = mNodes.size();
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-
- // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
- for (unsigned int i = 0; i < anim->mNumChannels;++i)
- anim->mChannels[i] = NULL;
-
- for( unsigned int a = 0; a < anim->mNumChannels; a++)
- {
- const Node& node = mNodes[a];
- const std::string nodeName = std::string( node.mNode->mName.data );
- aiNodeAnim* nodeAnim = new aiNodeAnim;
- anim->mChannels[a] = nodeAnim;
- nodeAnim->mNodeName.Set( nodeName);
-
- // translational part, if given
- if( node.mChannels.size() == 6)
- {
- nodeAnim->mNumPositionKeys = mAnimNumFrames;
- nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
- aiVectorKey* poskey = nodeAnim->mPositionKeys;
- for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
- {
- poskey->mTime = double( fr);
-
- // Now compute all translations in the right order
- for( unsigned int channel = 0; channel < 3; ++channel)
- {
- switch( node.mChannels[channel])
- {
- case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
- default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
- }
- }
- ++poskey;
- }
- } else
- {
- // if no translation part is given, put a default sequence
- aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
- nodeAnim->mNumPositionKeys = 1;
- nodeAnim->mPositionKeys = new aiVectorKey[1];
- nodeAnim->mPositionKeys[0].mTime = 0.0;
- nodeAnim->mPositionKeys[0].mValue = nodePos;
- }
-
- // rotation part. Always present. First find value offsets
- {
- unsigned int rotOffset = 0;
- if( node.mChannels.size() == 6)
- {
- // Offset all further calculations
- rotOffset = 3;
- }
-
- // Then create the number of rotation keys
- nodeAnim->mNumRotationKeys = mAnimNumFrames;
- nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
- aiQuatKey* rotkey = nodeAnim->mRotationKeys;
- for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
- {
- aiMatrix4x4 temp;
- aiMatrix3x3 rotMatrix;
-
- for( unsigned int channel = 0; channel < 3; ++channel)
- {
- // translate ZXY euler angels into a quaternion
- const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
-
- // Compute rotation transformations in the right order
- switch (node.mChannels[rotOffset+channel])
- {
- case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
- default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
- }
- }
-
- rotkey->mTime = double( fr);
- rotkey->mValue = aiQuaternion( rotMatrix);
- ++rotkey;
- }
- }
-
- // scaling part. Always just a default track
- {
- nodeAnim->mNumScalingKeys = 1;
- nodeAnim->mScalingKeys = new aiVectorKey[1];
- nodeAnim->mScalingKeys[0].mTime = 0.0;
- nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
- }
- }
+ // create the animation
+ pScene->mNumAnimations = 1;
+ pScene->mAnimations = new aiAnimation*[1];
+ aiAnimation* anim = new aiAnimation;
+ pScene->mAnimations[0] = anim;
+
+ // put down the basic parameters
+ anim->mName.Set( "Motion");
+ anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
+ anim->mDuration = double( mAnimNumFrames - 1);
+
+ // now generate the tracks for all nodes
+ anim->mNumChannels = mNodes.size();
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+ // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
+ for (unsigned int i = 0; i < anim->mNumChannels;++i)
+ anim->mChannels[i] = NULL;
+
+ for( unsigned int a = 0; a < anim->mNumChannels; a++)
+ {
+ const Node& node = mNodes[a];
+ const std::string nodeName = std::string( node.mNode->mName.data );
+ aiNodeAnim* nodeAnim = new aiNodeAnim;
+ anim->mChannels[a] = nodeAnim;
+ nodeAnim->mNodeName.Set( nodeName);
+
+ // translational part, if given
+ if( node.mChannels.size() == 6)
+ {
+ nodeAnim->mNumPositionKeys = mAnimNumFrames;
+ nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
+ aiVectorKey* poskey = nodeAnim->mPositionKeys;
+ for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+ {
+ poskey->mTime = double( fr);
+
+ // Now compute all translations in the right order
+ for( unsigned int channel = 0; channel < 3; ++channel)
+ {
+ switch( node.mChannels[channel])
+ {
+ case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+ default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+ }
+ }
+ ++poskey;
+ }
+ } else
+ {
+ // if no translation part is given, put a default sequence
+ aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
+ nodeAnim->mNumPositionKeys = 1;
+ nodeAnim->mPositionKeys = new aiVectorKey[1];
+ nodeAnim->mPositionKeys[0].mTime = 0.0;
+ nodeAnim->mPositionKeys[0].mValue = nodePos;
+ }
+
+ // rotation part. Always present. First find value offsets
+ {
+ unsigned int rotOffset = 0;
+ if( node.mChannels.size() == 6)
+ {
+ // Offset all further calculations
+ rotOffset = 3;
+ }
+
+ // Then create the number of rotation keys
+ nodeAnim->mNumRotationKeys = mAnimNumFrames;
+ nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
+ aiQuatKey* rotkey = nodeAnim->mRotationKeys;
+ for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+ {
+ aiMatrix4x4 temp;
+ aiMatrix3x3 rotMatrix;
+
+ for( unsigned int channel = 0; channel < 3; ++channel)
+ {
+ // translate ZXY euler angels into a quaternion
+ const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
+
+ // Compute rotation transformations in the right order
+ switch (node.mChannels[rotOffset+channel])
+ {
+ case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+ default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+ }
+ }
+
+ rotkey->mTime = double( fr);
+ rotkey->mValue = aiQuaternion( rotMatrix);
+ ++rotkey;
+ }
+ }
+
+ // scaling part. Always just a default track
+ {
+ nodeAnim->mNumScalingKeys = 1;
+ nodeAnim->mScalingKeys = new aiVectorKey[1];
+ nodeAnim->mScalingKeys[0].mTime = 0.0;
+ nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER
diff --git a/src/3rdparty/assimp/code/BVHLoader.h b/src/3rdparty/assimp/code/BVHLoader.h
index 279f6bf1e..8a163d1e7 100644
--- a/src/3rdparty/assimp/code/BVHLoader.h
+++ b/src/3rdparty/assimp/code/BVHLoader.h
@@ -4,11 +4,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,11 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
+struct aiNode;
+
namespace Assimp
{
// --------------------------------------------------------------------------------
-/** Loader class to read Motion Capturing data from a .bvh file.
+/** Loader class to read Motion Capturing data from a .bvh file.
*
* This format only contains a hierarchy of joints and a series of keyframes for
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
@@ -62,106 +64,106 @@ namespace Assimp
class BVHLoader : public BaseImporter
{
- /** Possible animation channels for which the motion data holds the values */
- enum ChannelType
- {
- Channel_PositionX,
- Channel_PositionY,
- Channel_PositionZ,
- Channel_RotationX,
- Channel_RotationY,
- Channel_RotationZ
- };
-
- /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
- struct Node
- {
- const aiNode* mNode;
- std::vector<ChannelType> mChannels;
- std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
-
- Node() { }
- Node( const aiNode* pNode) : mNode( pNode) { }
- };
+ /** Possible animation channels for which the motion data holds the values */
+ enum ChannelType
+ {
+ Channel_PositionX,
+ Channel_PositionY,
+ Channel_PositionZ,
+ Channel_RotationX,
+ Channel_RotationY,
+ Channel_RotationZ
+ };
+
+ /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
+ struct Node
+ {
+ const aiNode* mNode;
+ std::vector<ChannelType> mChannels;
+ std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
+
+ Node() { }
+ explicit Node( const aiNode* pNode) : mNode( pNode) { }
+ };
public:
- BVHLoader();
- ~BVHLoader();
+ BVHLoader();
+ ~BVHLoader();
public:
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
- void SetupProperties(const Importer* pImp);
- const aiImporterDesc* GetInfo () const;
+ void SetupProperties(const Importer* pImp);
+ const aiImporterDesc* GetInfo () const;
protected:
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
protected:
- /** Reads the file */
- void ReadStructure( aiScene* pScene);
+ /** Reads the file */
+ void ReadStructure( aiScene* pScene);
- /** Reads the hierarchy */
- void ReadHierarchy( aiScene* pScene);
+ /** Reads the hierarchy */
+ void ReadHierarchy( aiScene* pScene);
- /** Reads a node and recursively its childs and returns the created node. */
- aiNode* ReadNode();
+ /** Reads a node and recursively its childs and returns the created node. */
+ aiNode* ReadNode();
- /** Reads an end node and returns the created node. */
- aiNode* ReadEndSite( const std::string& pParentName);
+ /** Reads an end node and returns the created node. */
+ aiNode* ReadEndSite( const std::string& pParentName);
- /** Reads a node offset for the given node */
- void ReadNodeOffset( aiNode* pNode);
+ /** Reads a node offset for the given node */
+ void ReadNodeOffset( aiNode* pNode);
- /** Reads the animation channels into the given node */
- void ReadNodeChannels( BVHLoader::Node& pNode);
+ /** Reads the animation channels into the given node */
+ void ReadNodeChannels( BVHLoader::Node& pNode);
- /** Reads the motion data */
- void ReadMotion( aiScene* pScene);
+ /** Reads the motion data */
+ void ReadMotion( aiScene* pScene);
- /** Retrieves the next token */
- std::string GetNextToken();
+ /** Retrieves the next token */
+ std::string GetNextToken();
- /** Reads the next token as a float */
- float GetNextTokenAsFloat();
+ /** Reads the next token as a float */
+ float GetNextTokenAsFloat();
- /** Aborts the file reading with an exception */
- void ThrowException( const std::string& pError);
+ /** Aborts the file reading with an exception */
+ AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
- /** Constructs an animation for the motion data and stores it in the given scene */
- void CreateAnimation( aiScene* pScene);
+ /** Constructs an animation for the motion data and stores it in the given scene */
+ void CreateAnimation( aiScene* pScene);
protected:
- /** Filename, for a verbose error message */
- std::string mFileName;
+ /** Filename, for a verbose error message */
+ std::string mFileName;
- /** Buffer to hold the loaded file */
- std::vector<char> mBuffer;
+ /** Buffer to hold the loaded file */
+ std::vector<char> mBuffer;
- /** Next char to read from the buffer */
- std::vector<char>::const_iterator mReader;
+ /** Next char to read from the buffer */
+ std::vector<char>::const_iterator mReader;
- /** Current line, for error messages */
- unsigned int mLine;
+ /** Current line, for error messages */
+ unsigned int mLine;
- /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
- * Also contain the motion data for the node's channels
- */
- std::vector<Node> mNodes;
+ /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
+ * Also contain the motion data for the node's channels
+ */
+ std::vector<Node> mNodes;
- /** basic Animation parameters */
- float mAnimTickDuration;
- unsigned int mAnimNumFrames;
+ /** basic Animation parameters */
+ float mAnimTickDuration;
+ unsigned int mAnimNumFrames;
- bool noSkeletonMesh;
+ bool noSkeletonMesh;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/BaseImporter.cpp b/src/3rdparty/assimp/code/BaseImporter.cpp
index 4b7163dd5..aa615e592 100644
--- a/src/3rdparty/assimp/code/BaseImporter.cpp
+++ b/src/3rdparty/assimp/code/BaseImporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,264 +25,280 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file BaseImporter.cpp
- * @brief Implementation of BaseImporter
+ * @brief Implementation of BaseImporter
*/
-#include "AssimpPCH.h"
#include "BaseImporter.h"
#include "FileSystemFilter.h"
-
#include "Importer.h"
+#include "ByteSwapper.h"
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include <ios>
+#include <list>
+#include <memory>
+#include <sstream>
+#include <cctype>
+
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
BaseImporter::BaseImporter()
-: progress()
+: m_progress()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
BaseImporter::~BaseImporter()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Imports the given file and returns the imported data.
aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
{
- progress = pImp->GetProgressHandler();
- ai_assert(progress);
+ m_progress = pImp->GetProgressHandler();
+ ai_assert(m_progress);
- // Gather configuration properties for this run
- SetupProperties( pImp );
+ // 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);
+ // 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
- ScopeGuard<aiScene> sc(new aiScene());
+ // create a scene object to hold the data
+ ScopeGuard<aiScene> sc(new aiScene());
- // dispatch importing
- try
- {
- InternReadFile( pFile, sc, &filter);
+ // dispatch importing
+ try
+ {
+ InternReadFile( pFile, sc, &filter);
- } catch( const std::exception& err ) {
- // extract error description
- mErrorText = err.what();
- DefaultLogger::get()->error(mErrorText);
- return NULL;
- }
+ } catch( const std::exception& err ) {
+ // extract error description
+ m_ErrorText = err.what();
+ DefaultLogger::get()->error(m_ErrorText);
+ return NULL;
+ }
- // return what we gathered from the import.
- sc.dismiss();
- return sc;
+ // return what we gathered from the import.
+ sc.dismiss();
+ return sc;
}
// ------------------------------------------------------------------------------------------------
void BaseImporter::SetupProperties(const Importer* /*pImp*/)
{
- // the default implementation does nothing
+ // the default implementation does nothing
}
// ------------------------------------------------------------------------------------------------
void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
{
- const aiImporterDesc* desc = GetInfo();
- ai_assert(desc != NULL);
-
- const char* ext = desc->mFileExtensions;
- ai_assert(ext != NULL);
-
- 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++);
+ const aiImporterDesc* desc = GetInfo();
+ ai_assert(desc != NULL);
+
+ const char* ext = desc->mFileExtensions;
+ ai_assert(ext != NULL);
+
+ 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 */)
+ const std::string& pFile,
+ const char** tokens,
+ unsigned int numTokens,
+ unsigned int searchBytes /* = 200 */,
+ bool tokensSol /* false */)
{
- ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes);
- if (!pIOHandler)
- return false;
-
- boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
- if (pStream.get() ) {
- // read 200 characters from the file
- boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]);
- char* buffer = _buffer.get();
-
- const unsigned int read = pStream->Read(buffer,1,searchBytes);
- if (!read)
- return false;
-
- for (unsigned int i = 0; i < read;++i)
- buffer[i] = ::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';
-
- for (unsigned int i = 0; i < numTokens;++i) {
- ai_assert(NULL != tokens[i]);
-
-
- const char* r = strstr(buffer,tokens[i]);
- if (!r)
- 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') {
- DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
- return true;
- }
- }
- }
- return false;
+ ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes);
+ if (!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();
+ if( NULL == buffer ) {
+ return false;
+ }
+
+ const size_t read = pStream->Read(buffer,1,searchBytes);
+ if( !read ) {
+ return false;
+ }
+
+ for( size_t i = 0; i < read; ++i ) {
+ buffer[ i ] = ::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';
+
+ for (unsigned int i = 0; i < numTokens;++i) {
+ ai_assert(NULL != tokens[i]);
+
+
+ const char* r = strstr(buffer,tokens[i]);
+ if( !r ) {
+ 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') {
+ DefaultLogger::get()->debug(std::string("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)
+/*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('.');
+ std::string::size_type pos = pFile.find_last_of('.');
+
+ // no file extension - can't read
+ if( pos == std::string::npos)
+ return false;
- // 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;
+ 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;
+ // check for other, optional, file extensions
+ if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
+ return true;
- if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
- return true;
+ if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
+ return true;
- return false;
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get file extension from path
/*static*/ std::string BaseImporter::GetExtension (const std::string& pFile)
{
- std::string::size_type pos = pFile.find_last_of('.');
+ std::string::size_type pos = pFile.find_last_of('.');
- // no file extension at all
- if( pos == std::string::npos)
- return "";
+ // no file extension at all
+ if( pos == std::string::npos)
+ return "";
- std::string ret = pFile.substr(pos+1);
- std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
- return ret;
+ std::string ret = pFile.substr(pos+1);
+ std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
+ 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)
+/* 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 && _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);
- boost::scoped_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 convinience, 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;
+ ai_assert(size <= 16 && _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;
}
#include "../contrib/ConvertUTF/ConvertUTF.h"
@@ -290,309 +306,312 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
// ------------------------------------------------------------------------------------------------
void ReportResult(ConversionResult res)
{
- if(res == sourceExhausted) {
- DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails");
- }
- else if(res == sourceIllegal) {
- DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails");
- }
+ if(res == sourceExhausted) {
+ DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails");
+ }
+ else if(res == sourceIllegal) {
+ DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails");
+ }
}
// ------------------------------------------------------------------------------------------------
// 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) {
- DefaultLogger::get()->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 endianess ..
- 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) {
- DefaultLogger::get()->debug("Found UTF-32 BOM ...");
-
- const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
- char* dstart,*dend;
- std::vector<char> output;
- do {
- output.resize(output.size()?output.size()*3/2:data.size()/2);
- dstart = &output.front(),dend = &output.back()+1;
-
- result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
- } while(result == targetExhausted);
-
- ReportResult(result);
-
- // copy to output buffer.
- const size_t outlen = (size_t)(dstart-&output.front());
- data.assign(output.begin(),output.begin()+outlen);
- return;
- }
-
- // UTF 16 BE with BOM
- if(*((uint16_t*)&data.front()) == 0xFFFE) {
-
- // swap the endianess ..
- 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) {
- DefaultLogger::get()->debug("Found UTF-16 BOM ...");
-
- const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
- char* dstart,*dend;
- std::vector<char> output;
- do {
- output.resize(output.size()?output.size()*3/2:data.size()*3/4);
- dstart = &output.front(),dend = &output.back()+1;
-
- result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
- } while(result == targetExhausted);
-
- ReportResult(result);
-
- // copy to output buffer.
- const size_t outlen = (size_t)(dstart-&output.front());
- data.assign(output.begin(),output.begin()+outlen);
- return;
- }
+ 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) {
+ DefaultLogger::get()->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) {
+ DefaultLogger::get()->debug("Found UTF-32 BOM ...");
+
+ const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
+ char* dstart,*dend;
+ std::vector<char> output;
+ do {
+ output.resize(output.size()?output.size()*3/2:data.size()/2);
+ dstart = &output.front(),dend = &output.back()+1;
+
+ result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
+ } while(result == targetExhausted);
+
+ ReportResult(result);
+
+ // copy to output buffer.
+ const size_t outlen = (size_t)(dstart-&output.front());
+ data.assign(output.begin(),output.begin()+outlen);
+ 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) {
+ DefaultLogger::get()->debug("Found UTF-16 BOM ...");
+
+ const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
+ char* dstart,*dend;
+ std::vector<char> output;
+ do {
+ output.resize(output.size()?output.size()*3/2:data.size()*3/4);
+ dstart = &output.front(),dend = &output.back()+1;
+
+ result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
+ } while(result == targetExhausted);
+
+ ReportResult(result);
+
+ // copy to output buffer.
+ const size_t outlen = (size_t)(dstart-&output.front());
+ data.assign(output.begin(),output.begin()+outlen);
+ return;
+ }
}
// ------------------------------------------------------------------------------------------------
// Convert to UTF8 data to ISO-8859-1
void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
{
- unsigned int size = data.size();
- unsigned int i = 0, j = 0;
+ size_t size = data.size();
+ size_t i = 0, j = 0;
- while(i < size) {
- if((unsigned char) data[i] < 0x80) {
- data[j] = data[i];
- } else if(i < size - 1) {
- if((unsigned char) data[i] == 0xC2) {
- data[j] = data[++i];
- } else if((unsigned char) data[i] == 0xC3) {
- data[j] = ((unsigned char) data[++i] + 0x40);
- } else {
- std::stringstream stream;
+ 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.";
+ stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
- DefaultLogger::get()->error(stream.str());
+ DefaultLogger::get()->error(stream.str());
- data[j++] = data[i++];
- data[j] = data[i];
- }
- } else {
- DefaultLogger::get()->error("UTF8 code but only one character remaining");
+ data[j++] = data[i++];
+ data[j] = data[i];
+ }
+ } else {
+ DefaultLogger::get()->error("UTF8 code but only one character remaining");
- data[j] = data[i];
- }
+ data[j] = data[i];
+ }
- i++; j++;
- }
+ i++; j++;
+ }
- data.resize(j);
+ data.resize(j);
}
// ------------------------------------------------------------------------------------------------
void BaseImporter::TextFileToBuffer(IOStream* stream,
- std::vector<char>& data)
+ std::vector<char>& data,
+ TextFileMode mode)
{
- ai_assert(NULL != stream);
-
- const size_t fileSize = stream->FileSize();
- if(!fileSize) {
- throw DeadlyImportError("File is empty");
- }
-
- data.reserve(fileSize+1);
- data.resize(fileSize);
- 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);
+ ai_assert(NULL != 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;
- }
-
- const std::string file;
- unsigned int flags;
- unsigned int refCnt;
- aiScene* scene;
- bool loaded;
- BatchLoader::PropertyMap map;
- unsigned int id;
-
- bool operator== (const std::string& f) {
- return file == f;
- }
- };
+ // 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;
+ }
+
+ const std::string file;
+ unsigned int flags;
+ unsigned int refCnt;
+ aiScene* scene;
+ bool loaded;
+ BatchLoader::PropertyMap map;
+ unsigned int id;
+
+ bool operator== (const std::string& f) {
+ return file == f;
+ }
+ };
}
// ------------------------------------------------------------------------------------------------
// BatchLoader::pimpl data structure
struct Assimp::BatchData
{
- BatchData()
- : next_id(0xffff)
- {}
+ BatchData()
+ : pIOSystem()
+ , pImporter()
+ , next_id(0xffff)
+ {}
- // IO system to be used for all imports
- IOSystem* pIOSystem;
+ // IO system to be used for all imports
+ IOSystem* pIOSystem;
- // Importer used to load all meshes
- Importer* pImporter;
+ // Importer used to load all meshes
+ Importer* pImporter;
- // List of all imports
- std::list<LoadRequest> requests;
+ // List of all imports
+ std::list<LoadRequest> requests;
- // Base path
- std::string pathBase;
+ // Base path
+ std::string pathBase;
- // Id for next item
- unsigned int next_id;
+ // Id for next item
+ unsigned int next_id;
};
// ------------------------------------------------------------------------------------------------
BatchLoader::BatchLoader(IOSystem* pIO)
{
- ai_assert(NULL != pIO);
+ ai_assert(NULL != pIO);
- data = new BatchData();
- data->pIOSystem = pIO;
+ data = new BatchData();
+ data->pIOSystem = pIO;
- data->pImporter = new Importer();
- data->pImporter->SetIOHandler(data->pIOSystem);
+ data->pImporter = new Importer();
+ data->pImporter->SetIOHandler(data->pIOSystem);
}
// ------------------------------------------------------------------------------------------------
BatchLoader::~BatchLoader()
{
- // delete all scenes wthat have not been polled by the user
- for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
-
- delete (*it).scene;
- }
- data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */
- delete data->pImporter;
- delete data;
+ // delete all scenes wthat have not been polled by the user
+ for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+
+ delete (*it).scene;
+ }
+ data->pImporter->SetIOHandler(NULL); /* get pointer back into our possession */
+ delete data->pImporter;
+ delete data;
}
// ------------------------------------------------------------------------------------------------
-unsigned int BatchLoader::AddLoadRequest (const std::string& file,
- unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
+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
- std::list<LoadRequest>::iterator it;
- for (it = data->requests.begin();it != data->requests.end(); ++it) {
-
- // Call IOSystem's path comparison function here
- if (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 ...
- data->requests.push_back(LoadRequest(file,steps,map,data->next_id));
- return data->next_id++;
+ ai_assert(!file.empty());
+
+ // check whether we have this loading request already
+ std::list<LoadRequest>::iterator it;
+ for (it = data->requests.begin();it != data->requests.end(); ++it) {
+
+ // Call IOSystem's path comparison function here
+ if (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 ...
+ data->requests.push_back(LoadRequest(file,steps,map,data->next_id));
+ return data->next_id++;
}
// ------------------------------------------------------------------------------------------------
-aiScene* BatchLoader::GetImport (unsigned int which)
+aiScene* BatchLoader::GetImport (unsigned int which)
{
- for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
-
- if ((*it).id == which && (*it).loaded) {
-
- aiScene* sc = (*it).scene;
- if (!(--(*it).refCnt)) {
- data->requests.erase(it);
- }
- return sc;
- }
- }
- return NULL;
+ for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+
+ if ((*it).id == which && (*it).loaded) {
+
+ aiScene* sc = (*it).scene;
+ if (!(--(*it).refCnt)) {
+ data->requests.erase(it);
+ }
+ return sc;
+ }
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
void BatchLoader::LoadAll()
{
- // no threaded implementation for the moment
- for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
- // force validation in debug builds
- unsigned int pp = (*it).flags;
+ // no threaded implementation for the moment
+ for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+ // force validation in debug builds
+ unsigned int pp = (*it).flags;
#ifdef ASSIMP_BUILD_DEBUG
- pp |= aiProcess_ValidateDataStructure;
+ pp |= aiProcess_ValidateDataStructure;
#endif
- // setup config properties if necessary
- ImporterPimpl* pimpl = 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())
- {
- DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
- DefaultLogger::get()->info("File: " + (*it).file);
- }
- data->pImporter->ReadFile((*it).file,pp);
- (*it).scene = data->pImporter->GetOrphanedScene();
- (*it).loaded = true;
-
- DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
- }
+ // setup config properties if necessary
+ ImporterPimpl* pimpl = 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())
+ {
+ DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
+ DefaultLogger::get()->info("File: " + (*it).file);
+ }
+ data->pImporter->ReadFile((*it).file,pp);
+ (*it).scene = data->pImporter->GetOrphanedScene();
+ (*it).loaded = true;
+
+ DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
+ }
}
-
-
-
-
diff --git a/src/3rdparty/assimp/code/BaseImporter.h b/src/3rdparty/assimp/code/BaseImporter.h
index 491c9cea1..5c9ddfa5e 100644
--- a/src/3rdparty/assimp/code/BaseImporter.h
+++ b/src/3rdparty/assimp/code/BaseImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,318 +47,350 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <map>
#include <vector>
-#include "./../include/assimp/types.h"
+#include <set>
+#include <assimp/types.h>
+#include <assimp/ProgressHandler.hpp>
struct aiScene;
-namespace Assimp {
+namespace Assimp {
-class IOSystem;
class Importer;
-class BaseImporter;
+class IOSystem;
class BaseProcess;
class SharedPostProcessInfo;
class IOStream;
+
// utility to do char4 to uint32 in a portable manner
#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
- (string[1] << 16) + (string[2] << 8) + string[3]))
+ (string[1] << 16) + (string[2] << 8) + string[3]))
// ---------------------------------------------------------------------------
template <typename T>
struct ScopeGuard
{
- ScopeGuard(T* obj) : obj(obj), mdismiss() {}
- ~ScopeGuard () throw() {
- if (!mdismiss) {
- delete obj;
- }
- obj = NULL;
- }
-
- T* dismiss() {
- mdismiss=true;
- return obj;
- }
-
- operator T*() {
- return obj;
- }
-
- T* operator -> () {
- return obj;
- }
+ explicit ScopeGuard(T* obj) : obj(obj), mdismiss() {}
+ ~ScopeGuard () throw() {
+ if (!mdismiss) {
+ delete obj;
+ }
+ obj = NULL;
+ }
+
+ T* dismiss() {
+ mdismiss=true;
+ return obj;
+ }
+
+ operator T*() {
+ return obj;
+ }
+
+ T* operator -> () {
+ return obj;
+ }
private:
- T* obj;
- bool mdismiss;
+ // no copying allowed.
+ ScopeGuard();
+ ScopeGuard( const ScopeGuard & );
+ ScopeGuard &operator = ( const ScopeGuard & );
+
+ T* obj;
+ bool mdismiss;
};
// ---------------------------------------------------------------------------
-/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
+/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
* for all importer worker classes.
*
- * The interface defines two functions: CanRead() is used to check if the
- * importer can handle the format of the given file. If an implementation of
- * this function returns true, the importer then calls ReadFile() which
- * imports the given file. ReadFile is not overridable, it just calls
+ * The interface defines two functions: CanRead() is used to check if the
+ * importer can handle the format of the given file. If an implementation of
+ * this function returns true, the importer then calls ReadFile() which
+ * imports the given file. ReadFile is not overridable, it just calls
* InternReadFile() and catches any ImportErrorException that might occur.
*/
class ASSIMP_API BaseImporter
{
- friend class Importer;
+ friend class Importer;
public:
- /** Constructor to be privately used by #Importer */
- BaseImporter();
+ /** Constructor to be privately used by #Importer */
+ BaseImporter();
- /** Destructor, private as well */
- virtual ~BaseImporter();
+ /** Destructor, private as well */
+ virtual ~BaseImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- *
- * The implementation should be as quick as possible. A check for
- * the file extension is enough. If no suitable loader is found with
- * this strategy, CanRead() is called again, the 'checkSig' parameter
- * set to true this time. Now the implementation is expected to
- * perform a full check of the file structure, possibly searching the
- * first bytes of the file for magic identifiers or keywords.
- *
- * @param pFile Path and file name of the file to be examined.
- * @param pIOHandler The IO handler to use for accessing any file.
- * @param checkSig Set to true if this method is called a second time.
- * This time, the implementation may take more time to examine the
- * contents of the file to be loaded for magic bytes, keywords, etc
- * to be able to load files with unknown/not existent file extensions.
- * @return true if the class can read this file, false if not.
- */
- virtual bool CanRead(
- const std::string& pFile,
- IOSystem* pIOHandler,
- bool checkSig
- ) const = 0;
-
- // -------------------------------------------------------------------
- /** Imports the given file and returns the imported data.
- * If the import succeeds, ownership of the data is transferred to
- * the caller. If the import fails, NULL is returned. The function
- * takes care that any partially constructed data is destroyed
- * beforehand.
- *
- * @param pImp #Importer object hosting this loader.
- * @param pFile Path of the file to be imported.
- * @param pIOHandler IO-Handler used to open this and possible other files.
- * @return The imported data or NULL if failed. If it failed a
- * human-readable error description can be retrieved by calling
- * GetErrorText()
- *
- * @note This function is not intended to be overridden. Implement
- * InternReadFile() to do the import. If an exception is thrown somewhere
- * in InternReadFile(), this function will catch it and transform it into
- * a suitable response to the caller.
- */
- aiScene* ReadFile(
- const Importer* pImp,
- const std::string& pFile,
- IOSystem* pIOHandler
- );
-
- // -------------------------------------------------------------------
- /** Returns the error description of the last error that occured.
- * @return A description of the last error that occured. An empty
- * string if there was no error.
- */
- const std::string& GetErrorText() const {
- return mErrorText;
- }
-
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- * @param pImp Importer instance
- */
- virtual void SetupProperties(
- const Importer* pImp
- );
-
-
- // -------------------------------------------------------------------
- /** Called by #Importer::GetImporterInfo to get a description of
- * some loader features. Importers must provide this information. */
- virtual const aiImporterDesc* GetInfo() const = 0;
-
-
-
- // -------------------------------------------------------------------
- /** Called by #Importer::GetExtensionList for each loaded importer.
- * Take the extension list contained in the structure returned by
- * #GetInfo and insert all file extensions into the given set.
- * @param extension set to collect file extensions in*/
- void GetExtensionList(std::set<std::string>& extensions);
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ *
+ * The implementation should be as quick as possible. A check for
+ * the file extension is enough. If no suitable loader is found with
+ * this strategy, CanRead() is called again, the 'checkSig' parameter
+ * set to true this time. Now the implementation is expected to
+ * perform a full check of the file structure, possibly searching the
+ * first bytes of the file for magic identifiers or keywords.
+ *
+ * @param pFile Path and file name of the file to be examined.
+ * @param pIOHandler The IO handler to use for accessing any file.
+ * @param checkSig Set to true if this method is called a second time.
+ * This time, the implementation may take more time to examine the
+ * contents of the file to be loaded for magic bytes, keywords, etc
+ * to be able to load files with unknown/not existent file extensions.
+ * @return true if the class can read this file, false if not.
+ */
+ virtual bool CanRead(
+ const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const = 0;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file and returns the imported data.
+ * If the import succeeds, ownership of the data is transferred to
+ * the caller. If the import fails, NULL is returned. The function
+ * takes care that any partially constructed data is destroyed
+ * beforehand.
+ *
+ * @param pImp #Importer object hosting this loader.
+ * @param pFile Path of the file to be imported.
+ * @param pIOHandler IO-Handler used to open this and possible other files.
+ * @return The imported data or NULL if failed. If it failed a
+ * human-readable error description can be retrieved by calling
+ * GetErrorText()
+ *
+ * @note This function is not intended to be overridden. Implement
+ * InternReadFile() to do the import. If an exception is thrown somewhere
+ * in InternReadFile(), this function will catch it and transform it into
+ * a suitable response to the caller.
+ */
+ aiScene* ReadFile(
+ const Importer* pImp,
+ const std::string& pFile,
+ IOSystem* pIOHandler
+ );
+
+ // -------------------------------------------------------------------
+ /** Returns the error description of the last error that occurred.
+ * @return A description of the last error that occurred. An empty
+ * string if there was no error.
+ */
+ const std::string& GetErrorText() const {
+ return m_ErrorText;
+ }
+
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ * @param pImp Importer instance
+ */
+ virtual void SetupProperties(
+ const Importer* pImp
+ );
+
+
+ // -------------------------------------------------------------------
+ /** Called by #Importer::GetImporterInfo to get a description of
+ * some loader features. Importers must provide this information. */
+ virtual const aiImporterDesc* GetInfo() const = 0;
+
+
+
+ // -------------------------------------------------------------------
+ /** Called by #Importer::GetExtensionList for each loaded importer.
+ * Take the extension list contained in the structure returned by
+ * #GetInfo and insert all file extensions into the given set.
+ * @param extension set to collect file extensions in*/
+ void GetExtensionList(std::set<std::string>& extensions);
protected:
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure. The
- * function is expected to throw an ImportErrorException if there is
- * an error. If it terminates normally, the data in aiScene is
- * expected to be correct. Override this function to implement the
- * actual importing.
- * <br>
- * The output scene must meet the following requirements:<br>
- * <ul>
- * <li>At least a root node must be there, even if its only purpose
- * is to reference one mesh.</li>
- * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
- * in the mesh are determined automatically in this case.</li>
- * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
- * In fact this means that every vertex that is referenced by
- * a face is unique. Or the other way round: a vertex index may
- * not occur twice in a single aiMesh.</li>
- * <li>aiAnimation::mDuration may be -1. Assimp determines the length
- * of the animation automatically in this case as the length of
- * the longest animation channel.</li>
- * <li>aiMesh::mBitangents may be NULL if tangents and normals are
- * given. In this case bitangents are computed as the cross product
- * between normal and tangent.</li>
- * <li>There needn't be a material. If none is there a default material
- * is generated. However, it is recommended practice for loaders
- * to generate a default material for yourself that matches the
- * default material setting for the file format better than Assimp's
- * generic default material. Note that default materials *should*
- * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
- * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
- * texture. </li>
- * </ul>
- * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
- * <li> at least one mesh must be there</li>
- * <li> there may be no meshes with 0 vertices or faces</li>
- * </ul>
- * This won't be checked (except by the validation step): Assimp will
- * crash if one of the conditions is not met!
- *
- * @param pFile Path of the file to be imported.
- * @param pScene The scene object to hold the imported data.
- * NULL is not a valid parameter.
- * @param pIOHandler The IO handler to use for any file access.
- * NULL is not a valid parameter. */
- virtual void InternReadFile(
- const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler
- ) = 0;
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure. The
+ * function is expected to throw an ImportErrorException if there is
+ * an error. If it terminates normally, the data in aiScene is
+ * expected to be correct. Override this function to implement the
+ * actual importing.
+ * <br>
+ * The output scene must meet the following requirements:<br>
+ * <ul>
+ * <li>At least a root node must be there, even if its only purpose
+ * is to reference one mesh.</li>
+ * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
+ * in the mesh are determined automatically in this case.</li>
+ * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
+ * In fact this means that every vertex that is referenced by
+ * a face is unique. Or the other way round: a vertex index may
+ * not occur twice in a single aiMesh.</li>
+ * <li>aiAnimation::mDuration may be -1. Assimp determines the length
+ * of the animation automatically in this case as the length of
+ * the longest animation channel.</li>
+ * <li>aiMesh::mBitangents may be NULL if tangents and normals are
+ * given. In this case bitangents are computed as the cross product
+ * between normal and tangent.</li>
+ * <li>There needn't be a material. If none is there a default material
+ * is generated. However, it is recommended practice for loaders
+ * to generate a default material for yourself that matches the
+ * default material setting for the file format better than Assimp's
+ * generic default material. Note that default materials *should*
+ * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
+ * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
+ * texture. </li>
+ * </ul>
+ * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
+ * <li> at least one mesh must be there</li>
+ * <li> there may be no meshes with 0 vertices or faces</li>
+ * </ul>
+ * This won't be checked (except by the validation step): Assimp will
+ * crash if one of the conditions is not met!
+ *
+ * @param pFile Path of the file to be imported.
+ * @param pScene The scene object to hold the imported data.
+ * NULL is not a valid parameter.
+ * @param pIOHandler The IO handler to use for any file access.
+ * NULL is not a valid parameter. */
+ virtual void InternReadFile(
+ const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ ) = 0;
public: // static utilities
- // -------------------------------------------------------------------
- /** A utility for CanRead().
- *
- * The function searches the header of a file for a specific token
- * and returns true if this token is found. This works for text
- * files only. There is a rudimentary handling of UNICODE files.
- * The comparison is case independent.
- *
- * @param pIOSystem IO System to work with
- * @param file File name of the file
- * @param tokens List of tokens to search for
- * @param numTokens Size of the token array
- * @param searchBytes Number of bytes to be searched for the tokens.
- */
- static bool SearchFileHeaderForToken(
- IOSystem* pIOSystem,
- const std::string& file,
- const char** tokens,
- unsigned int numTokens,
- unsigned int searchBytes = 200,
- bool tokensSol = false);
-
- // -------------------------------------------------------------------
- /** @brief Check whether a file has a specific file extension
- * @param pFile Input file
- * @param ext0 Extension to check for. Lowercase characters only, no dot!
- * @param ext1 Optional second extension
- * @param ext2 Optional third extension
- * @note Case-insensitive
- */
- static bool SimpleExtensionCheck (
- const std::string& pFile,
- const char* ext0,
- const char* ext1 = NULL,
- const char* ext2 = NULL);
-
- // -------------------------------------------------------------------
- /** @brief Extract file extension from a string
- * @param pFile Input file
- * @return Extension without trailing dot, all lowercase
- */
- static std::string GetExtension (
- const std::string& pFile);
-
- // -------------------------------------------------------------------
- /** @brief Check whether a file starts with one or more magic tokens
- * @param pFile Input file
- * @param pIOHandler IO system to be used
- * @param magic n magic tokens
- * @params num Size of magic
- * @param offset Offset from file start where tokens are located
- * @param Size of one token, in bytes. Maximally 16 bytes.
- * @return true if one of the given tokens was found
- *
- * @note For convinence, the check is also performed for the
- * byte-swapped variant of all tokens (big endian). Only for
- * tokens of size 2,4.
- */
- static bool CheckMagicToken(
- IOSystem* pIOHandler,
- const std::string& pFile,
- const void* magic,
- unsigned int num,
- unsigned int offset = 0,
- unsigned int size = 4);
-
- // -------------------------------------------------------------------
- /** An utility for all text file loaders. It converts a file to our
- * UTF8 character set. Errors are reported, but ignored.
- *
- * @param data File buffer to be converted to UTF8 data. The buffer
- * is resized as appropriate. */
- static void ConvertToUTF8(
- std::vector<char>& data);
-
- // -------------------------------------------------------------------
- /** An utility for all text file loaders. It converts a file from our
- * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
- *
- * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
- * is resized as appropriate. */
- static void ConvertUTF8toISO8859_1(
- std::string& data);
-
- // -------------------------------------------------------------------
- /** Utility for text file loaders which copies the contents of the
- * file into a memory buffer and converts it to our UTF8
- * representation.
- * @param stream Stream to read from.
- * @param data Output buffer to be resized and filled with the
- * converted text file data. The buffer is terminated with
- * a binary 0. */
- static void TextFileToBuffer(
- IOStream* stream,
- std::vector<char>& data);
+ // -------------------------------------------------------------------
+ /** A utility for CanRead().
+ *
+ * The function searches the header of a file for a specific token
+ * and returns true if this token is found. This works for text
+ * files only. There is a rudimentary handling of UNICODE files.
+ * The comparison is case independent.
+ *
+ * @param pIOSystem IO System to work with
+ * @param file File name of the file
+ * @param tokens List of tokens to search for
+ * @param numTokens Size of the token array
+ * @param searchBytes Number of bytes to be searched for the tokens.
+ */
+ static bool SearchFileHeaderForToken(
+ IOSystem* pIOSystem,
+ const std::string& file,
+ const char** tokens,
+ unsigned int numTokens,
+ unsigned int searchBytes = 200,
+ bool tokensSol = false);
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a file has a specific file extension
+ * @param pFile Input file
+ * @param ext0 Extension to check for. Lowercase characters only, no dot!
+ * @param ext1 Optional second extension
+ * @param ext2 Optional third extension
+ * @note Case-insensitive
+ */
+ static bool SimpleExtensionCheck (
+ const std::string& pFile,
+ const char* ext0,
+ const char* ext1 = NULL,
+ const char* ext2 = NULL);
+
+ // -------------------------------------------------------------------
+ /** @brief Extract file extension from a string
+ * @param pFile Input file
+ * @return Extension without trailing dot, all lowercase
+ */
+ static std::string GetExtension (
+ const std::string& pFile);
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether a file starts with one or more magic tokens
+ * @param pFile Input file
+ * @param pIOHandler IO system to be used
+ * @param magic n magic tokens
+ * @params num Size of magic
+ * @param offset Offset from file start where tokens are located
+ * @param Size of one token, in bytes. Maximally 16 bytes.
+ * @return true if one of the given tokens was found
+ *
+ * @note For convinence, the check is also performed for the
+ * byte-swapped variant of all tokens (big endian). Only for
+ * tokens of size 2,4.
+ */
+ static bool CheckMagicToken(
+ IOSystem* pIOHandler,
+ const std::string& pFile,
+ const void* magic,
+ unsigned int num,
+ unsigned int offset = 0,
+ unsigned int size = 4);
+
+ // -------------------------------------------------------------------
+ /** An utility for all text file loaders. It converts a file to our
+ * UTF8 character set. Errors are reported, but ignored.
+ *
+ * @param data File buffer to be converted to UTF8 data. The buffer
+ * is resized as appropriate. */
+ static void ConvertToUTF8(
+ std::vector<char>& data);
+
+ // -------------------------------------------------------------------
+ /** An utility for all text file loaders. It converts a file from our
+ * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
+ *
+ * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
+ * is resized as appropriate. */
+ static void ConvertUTF8toISO8859_1(
+ std::string& data);
+
+ enum TextFileMode { ALLOW_EMPTY, FORBID_EMPTY };
+
+ // -------------------------------------------------------------------
+ /** Utility for text file loaders which copies the contents of the
+ * file into a memory buffer and converts it to our UTF8
+ * representation.
+ * @param stream Stream to read from.
+ * @param data Output buffer to be resized and filled with the
+ * converted text file data. The buffer is terminated with
+ * a binary 0.
+ * @param mode Whether it is OK to load empty text files. */
+ static void TextFileToBuffer(
+ IOStream* stream,
+ std::vector<char>& data,
+ TextFileMode mode = FORBID_EMPTY);
+
+ // -------------------------------------------------------------------
+ /** Utility function to move a std::vector into a aiScene array
+ * @param vec The vector to be moved
+ * @param out The output pointer to the allocated array.
+ * @param numOut The output count of elements copied. */
+ template<typename T>
+ AI_FORCE_INLINE
+ static void CopyVector(
+ std::vector<T>& vec,
+ T*& out,
+ unsigned int& outLength)
+ {
+ outLength = unsigned(vec.size());
+ if (outLength) {
+ out = new T[outLength];
+ std::swap_ranges(vec.begin(), vec.end(), out);
+ }
+ }
+
+
protected:
- /** Error description in case there was one. */
- std::string mErrorText;
+ /** Error description in case there was one. */
+ std::string m_ErrorText;
- /** Currently set progress handler */
- ProgressHandler* progress;
+ /** Currently set progress handler */
+ ProgressHandler* m_progress;
};
diff --git a/src/3rdparty/assimp/code/BaseProcess.cpp b/src/3rdparty/assimp/code/BaseProcess.cpp
index 9bac9ec89..580f89cdb 100644
--- a/src/3rdparty/assimp/code/BaseProcess.cpp
+++ b/src/3rdparty/assimp/code/BaseProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,26 +25,26 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of BaseProcess */
-#include "AssimpPCH.h"
#include "BaseImporter.h"
#include "BaseProcess.h"
-
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
#include "Importer.h"
using namespace Assimp;
@@ -61,45 +61,45 @@ BaseProcess::BaseProcess()
// Destructor, private as well
BaseProcess::~BaseProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
void BaseProcess::ExecuteOnScene( Importer* pImp)
{
- ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
+ ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
- progress = pImp->GetProgressHandler();
- ai_assert(progress);
+ progress = pImp->GetProgressHandler();
+ ai_assert(progress);
- SetupProperties( pImp );
+ SetupProperties( pImp );
- // catch exceptions thrown inside the PostProcess-Step
- try
- {
- Execute(pImp->Pimpl()->mScene);
+ // catch exceptions thrown inside the PostProcess-Step
+ try
+ {
+ Execute(pImp->Pimpl()->mScene);
- } catch( const std::exception& err ) {
+ } catch( const std::exception& err ) {
- // extract error description
- pImp->Pimpl()->mErrorString = err.what();
- DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
+ // extract error description
+ pImp->Pimpl()->mErrorString = err.what();
+ DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
- // and kill the partially imported data
- delete pImp->Pimpl()->mScene;
- pImp->Pimpl()->mScene = NULL;
- }
+ // and kill the partially imported data
+ delete pImp->Pimpl()->mScene;
+ pImp->Pimpl()->mScene = NULL;
+ }
}
// ------------------------------------------------------------------------------------------------
void BaseProcess::SetupProperties(const Importer* /*pImp*/)
{
- // the default implementation does nothing
+ // the default implementation does nothing
}
// ------------------------------------------------------------------------------------------------
bool BaseProcess::RequireVerboseFormat() const
{
- return true;
+ return true;
}
diff --git a/src/3rdparty/assimp/code/BaseProcess.h b/src/3rdparty/assimp/code/BaseProcess.h
index 3bae1899d..148f07284 100644
--- a/src/3rdparty/assimp/code/BaseProcess.h
+++ b/src/3rdparty/assimp/code/BaseProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,12 +44,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include "GenericProperty.h"
struct aiScene;
-namespace Assimp {
+namespace Assimp {
class Importer;
@@ -64,121 +64,121 @@ 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
- {
- 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
- {
- TStaticData(T in)
- : data (in)
- {}
-
- ~TStaticData()
- {}
-
- T data;
- };
-
- // some typedefs for cleaner code
- typedef unsigned int KeyType;
- typedef std::map<KeyType, Base*> PropertyMap;
+ 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);
- }
+ //! 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);
- }
+ void AddProperty( const char* name, Base* data) {
+ SetGenericPropertyPtr<Base>(pmap,name,data);
+ }
- Base* GetPropertyInternal( const char* name) const {
- return GetGenericProperty<Base*>(pmap,name,NULL);
- }
+ Base* GetPropertyInternal( const char* name) const {
+ return GetGenericProperty<Base*>(pmap,name,NULL);
+ }
private:
- //! Map of all stored properties
- PropertyMap pmap;
+ //! Map of all stored properties
+ PropertyMap pmap;
};
#if 0
@@ -188,12 +188,12 @@ private:
*
* For future use.
*/
- struct PPDependencyTable
+ 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;
+ 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
@@ -204,88 +204,88 @@ private:
// ---------------------------------------------------------------------------
/** 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()
+ * 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
+class ASSIMP_API_WINONLY BaseProcess
{
- friend class Importer;
+ friend class Importer;
public:
- /** Constructor to be privately used by Importer */
- BaseProcess();
+ /** Constructor to be privately used by Importer */
+ BaseProcess();
- /** Destructor, private as well */
- virtual ~BaseProcess();
+ /** Destructor, private as well */
+ virtual ~BaseProcess();
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.
- */
- 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;
- }
+ // -------------------------------------------------------------------
+ /** 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;
+ /** See the doc of #SharedPostProcessInfo for more details */
+ SharedPostProcessInfo* shared;
- /** Currently active progress handler */
- ProgressHandler* progress;
+ /** Currently active progress handler */
+ ProgressHandler* progress;
};
diff --git a/src/3rdparty/assimp/code/Bitmap.cpp b/src/3rdparty/assimp/code/Bitmap.cpp
index 30b5744ad..ae6d62083 100644
--- a/src/3rdparty/assimp/code/Bitmap.cpp
+++ b/src/3rdparty/assimp/code/Bitmap.cpp
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, assimp team
All rights reserved.
@@ -45,101 +45,108 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Used for file formats which embed their textures into the model file.
*/
-#include "AssimpPCH.h"
#include "Bitmap.h"
+#include <assimp/texture.h>
+#include <assimp/IOStream.hpp>
+#include "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, T& field) {
- std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
- }
-
- void Bitmap::WriteHeader(Header& header, IOStream* file) {
- uint8_t data[Header::header_size];
-
- std::size_t offset = 0;
-
- offset += Copy(&data[offset], header.type);
- offset += Copy(&data[offset], header.size);
- offset += Copy(&data[offset], header.reserved1);
- offset += Copy(&data[offset], header.reserved2);
- offset += Copy(&data[offset], header.offset);
-
- file->Write(data, Header::header_size, 1);
- }
-
- void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
- uint8_t data[DIB::dib_size];
-
- std::size_t offset = 0;
-
- offset += Copy(&data[offset], dib.size);
- offset += Copy(&data[offset], dib.width);
- offset += Copy(&data[offset], dib.height);
- offset += Copy(&data[offset], dib.planes);
- offset += Copy(&data[offset], dib.bits_per_pixel);
- offset += Copy(&data[offset], dib.compression);
- offset += Copy(&data[offset], dib.image_size);
- offset += Copy(&data[offset], dib.x_resolution);
- offset += Copy(&data[offset], dib.y_resolution);
- offset += Copy(&data[offset], dib.nb_colors);
- offset += Copy(&data[offset], dib.nb_important_colors);
-
- file->Write(data, DIB::dib_size, 1);
- }
-
- void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
- static const std::size_t padding_offset = 4;
- static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
-
- unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
- uint8_t pixel[mBytesPerPixel];
-
- for(std::size_t i = 0; i < texture->mHeight; ++i) {
- for(std::size_t j = 0; j < texture->mWidth; ++j) {
- const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
-
- pixel[0] = texel.r;
- pixel[1] = texel.g;
- pixel[2] = texel.b;
- pixel[3] = texel.a;
-
- file->Write(pixel, mBytesPerPixel, 1);
- }
-
- file->Write(padding_data, padding, 1);
- }
- }
+ void Bitmap::Save(aiTexture* texture, IOStream* file) {
+ if(file != NULL) {
+ Header header;
+ DIB dib;
+
+ dib.size = DIB::dib_size;
+ dib.width = texture->mWidth;
+ dib.height = texture->mHeight;
+ dib.planes = 1;
+ dib.bits_per_pixel = 8 * mBytesPerPixel;
+ dib.compression = 0;
+ dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
+ dib.x_resolution = 0;
+ dib.y_resolution = 0;
+ dib.nb_colors = 0;
+ dib.nb_important_colors = 0;
+
+ header.type = 0x4D42; // 'BM'
+ header.offset = Header::header_size + DIB::dib_size;
+ header.size = header.offset + dib.image_size;
+ header.reserved1 = 0;
+ header.reserved2 = 0;
+
+ WriteHeader(header, file);
+ WriteDIB(dib, file);
+ WriteData(texture, file);
+ }
+ }
+
+ template<typename T>
+ inline std::size_t Copy(uint8_t* data, T& field) {
+#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);
+ offset += Copy(&data[offset], header.offset);
+
+ file->Write(data, Header::header_size, 1);
+ }
+
+ void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
+ uint8_t data[DIB::dib_size];
+
+ std::size_t offset = 0;
+
+ offset += Copy(&data[offset], dib.size);
+ offset += Copy(&data[offset], dib.width);
+ offset += Copy(&data[offset], dib.height);
+ offset += Copy(&data[offset], dib.planes);
+ offset += Copy(&data[offset], dib.bits_per_pixel);
+ offset += Copy(&data[offset], dib.compression);
+ offset += Copy(&data[offset], dib.image_size);
+ offset += Copy(&data[offset], dib.x_resolution);
+ offset += Copy(&data[offset], dib.y_resolution);
+ offset += Copy(&data[offset], dib.nb_colors);
+ offset += Copy(&data[offset], dib.nb_important_colors);
+
+ file->Write(data, DIB::dib_size, 1);
+ }
+
+ void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
+ static const std::size_t padding_offset = 4;
+ static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
+
+ unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
+ uint8_t pixel[mBytesPerPixel];
+
+ for(std::size_t i = 0; i < texture->mHeight; ++i) {
+ for(std::size_t j = 0; j < texture->mWidth; ++j) {
+ const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
+
+ pixel[0] = texel.r;
+ pixel[1] = texel.g;
+ pixel[2] = texel.b;
+ pixel[3] = texel.a;
+
+ file->Write(pixel, mBytesPerPixel, 1);
+ }
+
+ file->Write(padding_data, padding, 1);
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/Bitmap.h b/src/3rdparty/assimp/code/Bitmap.h
index 36f80363e..ad29783ce 100644
--- a/src/3rdparty/assimp/code/Bitmap.h
+++ b/src/3rdparty/assimp/code/Bitmap.h
@@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, assimp team
All rights reserved.
@@ -48,89 +48,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BITMAP_H_INC
#define AI_BITMAP_H_INC
+#include <stdint.h>
+#include <cstddef>
+struct aiTexture;
+
namespace Assimp {
+class IOStream;
class Bitmap {
- protected:
+ protected:
- struct Header {
+ struct Header {
- uint16_t type;
+ uint16_t type;
- uint32_t size;
+ uint32_t size;
- uint16_t reserved1;
+ uint16_t reserved1;
- uint16_t reserved2;
+ uint16_t reserved2;
- uint32_t offset;
+ uint32_t offset;
- // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
- // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
- static const std::size_t header_size =
- sizeof(uint16_t) + // type
- sizeof(uint32_t) + // size
- sizeof(uint16_t) + // reserved1
- sizeof(uint16_t) + // reserved2
- sizeof(uint32_t); // offset
+ // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t header_size =
+ sizeof(uint16_t) + // type
+ sizeof(uint32_t) + // size
+ sizeof(uint16_t) + // reserved1
+ sizeof(uint16_t) + // reserved2
+ sizeof(uint32_t); // offset
- };
+ };
- struct DIB {
+ struct DIB {
- uint32_t size;
+ uint32_t size;
- int32_t width;
+ int32_t width;
- int32_t height;
+ int32_t height;
- uint16_t planes;
+ uint16_t planes;
- uint16_t bits_per_pixel;
+ uint16_t bits_per_pixel;
- uint32_t compression;
+ uint32_t compression;
- uint32_t image_size;
+ uint32_t image_size;
- int32_t x_resolution;
+ int32_t x_resolution;
- int32_t y_resolution;
+ int32_t y_resolution;
- uint32_t nb_colors;
+ uint32_t nb_colors;
- uint32_t nb_important_colors;
+ uint32_t nb_important_colors;
- // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
- // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
- static const std::size_t dib_size =
- sizeof(uint32_t) + // size
- sizeof(int32_t) + // width
- sizeof(int32_t) + // height
- sizeof(uint16_t) + // planes
- sizeof(uint16_t) + // bits_per_pixel
- sizeof(uint32_t) + // compression
- sizeof(uint32_t) + // image_size
- sizeof(int32_t) + // x_resolution
- sizeof(int32_t) + // y_resolution
- sizeof(uint32_t) + // nb_colors
- sizeof(uint32_t); // nb_important_colors
+ // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
+ // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+ static const std::size_t dib_size =
+ sizeof(uint32_t) + // size
+ sizeof(int32_t) + // width
+ sizeof(int32_t) + // height
+ sizeof(uint16_t) + // planes
+ sizeof(uint16_t) + // bits_per_pixel
+ sizeof(uint32_t) + // compression
+ sizeof(uint32_t) + // image_size
+ sizeof(int32_t) + // x_resolution
+ sizeof(int32_t) + // y_resolution
+ sizeof(uint32_t) + // nb_colors
+ sizeof(uint32_t); // nb_important_colors
- };
+ };
- static const std::size_t mBytesPerPixel = 4;
+ static const std::size_t mBytesPerPixel = 4;
- public:
+ public:
- static void Save(aiTexture* texture, IOStream* file);
+ static void Save(aiTexture* texture, IOStream* file);
- protected:
+ protected:
- static void WriteHeader(Header& header, IOStream* file);
+ static void WriteHeader(Header& header, IOStream* file);
- static void WriteDIB(DIB& dib, IOStream* file);
+ static void WriteDIB(DIB& dib, IOStream* file);
- static void WriteData(aiTexture* texture, IOStream* file);
+ static void WriteData(aiTexture* texture, IOStream* file);
};
diff --git a/src/3rdparty/assimp/code/BlenderBMesh.cpp b/src/3rdparty/assimp/code/BlenderBMesh.cpp
index 0e517f4c8..bf27a9396 100644
--- a/src/3rdparty/assimp/code/BlenderBMesh.cpp
+++ b/src/3rdparty/assimp/code/BlenderBMesh.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2013, 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Conversion of Blender's new BMesh stuff
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
@@ -53,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
- template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
+ template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
}
using namespace Assimp;
@@ -62,115 +61,142 @@ using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
- BMesh( mesh ),
- triMesh( NULL )
+ BMesh( mesh ),
+ triMesh( NULL )
{
- AssertValidMesh( );
}
// ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::~BlenderBMeshConverter( )
{
- DestroyTriMesh( );
+ DestroyTriMesh( );
}
// ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh( ) const
{
- // TODO - Should probably do some additional verification here
- return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
+ // TODO - Should probably do some additional verification here
+ return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
}
// ------------------------------------------------------------------------------------------------
const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
{
- AssertValidMesh( );
- AssertValidSizes( );
- PrepareTriMesh( );
+ AssertValidMesh( );
+ AssertValidSizes( );
+ PrepareTriMesh( );
- for ( int i = 0; i < BMesh->totpoly; ++i )
- {
- const MPoly& poly = BMesh->mpoly[ i ];
- ConvertPolyToFaces( poly );
- }
+ for ( int i = 0; i < BMesh->totpoly; ++i )
+ {
+ const MPoly& poly = BMesh->mpoly[ i ];
+ ConvertPolyToFaces( poly );
+ }
- return triMesh;
+ return triMesh;
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidMesh( )
{
- if ( !ContainsBMesh( ) )
- {
- ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
- }
+ if ( !ContainsBMesh( ) )
+ {
+ ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidSizes( )
{
- if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
- {
- ThrowException( "BMesh poly array has incorrect size" );
- }
- if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
- {
- ThrowException( "BMesh loop array has incorrect size" );
- }
+ if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
+ {
+ ThrowException( "BMesh poly array has incorrect size" );
+ }
+ if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
+ {
+ ThrowException( "BMesh loop array has incorrect size" );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::PrepareTriMesh( )
{
- if ( triMesh )
- {
- DestroyTriMesh( );
- }
-
- triMesh = new Mesh( *BMesh );
- triMesh->totface = 0;
- triMesh->mface.clear( );
+ if ( triMesh )
+ {
+ DestroyTriMesh( );
+ }
+
+ triMesh = new Mesh( *BMesh );
+ triMesh->totface = 0;
+ triMesh->mface.clear( );
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::DestroyTriMesh( )
{
- delete triMesh;
- triMesh = NULL;
+ delete triMesh;
+ triMesh = NULL;
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
{
- const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
- if ( poly.totloop == 3 || poly.totloop == 4 )
- {
- AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
- }
- else if ( poly.totloop > 4 )
- {
+ const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
+
+ if ( poly.totloop == 3 || poly.totloop == 4 )
+ {
+ AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
+
+ // UVs are optional, so only convert when present.
+ if ( BMesh->mloopuv.size() )
+ {
+ if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
+ {
+ ThrowException( "BMesh uv loop array has incorrect size" );
+ }
+ const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
+ AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
+ }
+ }
+ else if ( poly.totloop > 4 )
+ {
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
- BlenderTessellatorGL tessGL( *this );
- tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
+ BlenderTessellatorGL tessGL( *this );
+ tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#elif ASSIMP_BLEND_WITH_POLY_2_TRI
- BlenderTessellatorP2T tessP2T( *this );
- tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
+ BlenderTessellatorP2T tessP2T( *this );
+ tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#endif
- }
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
{
- MFace face;
- face.v1 = v1;
- face.v2 = v2;
- face.v3 = v3;
- face.v4 = v4;
- // TODO - Work out how materials work
- face.mat_nr = 0;
- triMesh->mface.push_back( face );
- triMesh->totface = triMesh->mface.size( );
+ MFace face;
+ face.v1 = v1;
+ face.v2 = v2;
+ face.v3 = v3;
+ face.v4 = v4;
+ // TODO - Work out how materials work
+ face.mat_nr = 0;
+ triMesh->mface.push_back( face );
+ triMesh->totface = triMesh->mface.size( );
+}
+
+// ------------------------------------------------------------------------------------------------
+void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
+{
+ MTFace mtface;
+ memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
+ memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
+ memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
+
+ if ( uv4 )
+ {
+ memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
+ }
+
+ triMesh->mtface.push_back( mtface );
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
diff --git a/src/3rdparty/assimp/code/BlenderBMesh.h b/src/3rdparty/assimp/code/BlenderBMesh.h
index 47afbf437..0d58b818c 100644
--- a/src/3rdparty/assimp/code/BlenderBMesh.h
+++ b/src/3rdparty/assimp/code/BlenderBMesh.h
@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2013, 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,45 +48,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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;
- }
-
- // BlenderScene.h
- namespace Blender
- {
- struct Mesh;
- struct MPoly;
- struct MLoop;
- }
-
- class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
- {
- public:
- BlenderBMeshConverter( const Blender::Mesh* mesh );
- ~BlenderBMeshConverter( );
-
- bool ContainsBMesh( ) const;
-
- const Blender::Mesh* TriangulateBMesh( );
-
- private:
- void AssertValidMesh( );
- void AssertValidSizes( );
- void PrepareTriMesh( );
- void DestroyTriMesh( );
- void ConvertPolyToFaces( const Blender::MPoly& poly );
- void AddFace( int v1, int v2, int v3, int v4 = 0 );
-
- const Blender::Mesh* BMesh;
- Blender::Mesh* triMesh;
-
- friend class BlenderTessellatorGL;
- friend class BlenderTessellatorP2T;
- };
+ // 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;
+ }
+
+ // BlenderScene.h
+ namespace Blender
+ {
+ struct Mesh;
+ struct MPoly;
+ struct MLoop;
+ }
+
+ class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
+ {
+ public:
+ BlenderBMeshConverter( const Blender::Mesh* mesh );
+ ~BlenderBMeshConverter( );
+
+ bool ContainsBMesh( ) const;
+
+ const Blender::Mesh* TriangulateBMesh( );
+
+ private:
+ void AssertValidMesh( );
+ void AssertValidSizes( );
+ void PrepareTriMesh( );
+ void DestroyTriMesh( );
+ void ConvertPolyToFaces( const Blender::MPoly& poly );
+ void AddFace( int v1, int v2, int v3, int v4 = 0 );
+ void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
+
+ const Blender::Mesh* BMesh;
+ Blender::Mesh* triMesh;
+
+ friend class BlenderTessellatorGL;
+ friend class BlenderTessellatorP2T;
+ };
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/BlenderDNA.cpp b/src/3rdparty/assimp/code/BlenderDNA.cpp
index b380fbe8d..18ec9f2b4 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.cpp
+++ b/src/3rdparty/assimp/code/BlenderDNA.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Blender `DNA`, that is its own
* serialized set of data structures.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderDNA.h"
@@ -53,170 +53,169 @@ using namespace Assimp;
using namespace Assimp::Blender;
using namespace Assimp::Formatter;
-#define for_each BOOST_FOREACH
bool match4(StreamReaderAny& stream, const char* string) {
- char tmp[] = {
- (stream).GetI1(),
- (stream).GetI1(),
- (stream).GetI1(),
- (stream).GetI1()
- };
- return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
+ char tmp[] = {
+ (stream).GetI1(),
+ (stream).GetI1(),
+ (stream).GetI1(),
+ (stream).GetI1()
+ };
+ return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
}
struct Type {
- size_t size;
- std::string name;
+ size_t size;
+ std::string name;
};
// ------------------------------------------------------------------------------------------------
-void DNAParser :: Parse ()
+void DNAParser :: Parse ()
{
- StreamReaderAny& stream = *db.reader.get();
- DNA& dna = db.dna;
-
- if(!match4(stream,"SDNA")) {
- throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
- }
-
- // name dictionary
- if(!match4(stream,"NAME")) {
- throw DeadlyImportError("BlenderDNA: Expected NAME field");
- }
-
- std::vector<std::string> names (stream.GetI4());
- for_each(std::string& s, names) {
- while (char c = stream.GetI1()) {
- s += c;
- }
- }
-
- // type dictionary
- for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
- if(!match4(stream,"TYPE")) {
- throw DeadlyImportError("BlenderDNA: Expected TYPE field");
- }
-
- std::vector<Type> types (stream.GetI4());
- for_each(Type& s, types) {
- while (char c = stream.GetI1()) {
- s.name += c;
- }
- }
-
- // type length dictionary
- for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
- if(!match4(stream,"TLEN")) {
- throw DeadlyImportError("BlenderDNA: Expected TLEN field");
- }
-
- for_each(Type& s, types) {
- s.size = stream.GetI2();
- }
-
- // structures dictionary
- for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
- if(!match4(stream,"STRC")) {
- throw DeadlyImportError("BlenderDNA: Expected STRC field");
- }
-
- size_t end = stream.GetI4(), fields = 0;
-
- dna.structures.reserve(end);
- for(size_t i = 0; i != end; ++i) {
-
- uint16_t n = stream.GetI2();
- if (n >= types.size()) {
- throw DeadlyImportError((format(),
- "BlenderDNA: Invalid type index in structure name" ,n,
- " (there are only ", types.size(), " entries)"
- ));
- }
-
- // maintain separate indexes
- dna.indices[types[n].name] = dna.structures.size();
-
- dna.structures.push_back(Structure());
- Structure& s = dna.structures.back();
- s.name = types[n].name;
- //s.index = dna.structures.size()-1;
-
- n = stream.GetI2();
- s.fields.reserve(n);
-
- size_t offset = 0;
- for (size_t m = 0; m < n; ++m, ++fields) {
-
- uint16_t j = stream.GetI2();
- if (j >= types.size()) {
- throw DeadlyImportError((format(),
- "BlenderDNA: Invalid type index in structure field ", j,
- " (there are only ", types.size(), " entries)"
- ));
- }
- s.fields.push_back(Field());
- Field& f = s.fields.back();
- f.offset = offset;
-
- f.type = types[j].name;
- f.size = types[j].size;
-
- j = stream.GetI2();
- if (j >= names.size()) {
- throw DeadlyImportError((format(),
- "BlenderDNA: Invalid name index in structure field ", j,
- " (there are only ", names.size(), " entries)"
- ));
- }
-
- f.name = names[j];
- f.flags = 0u;
-
- // pointers always specify the size of the pointee instead of their own.
- // The pointer asterisk remains a property of the lookup name.
- if (f.name[0] == '*') {
- f.size = db.i64bit ? 8 : 4;
- f.flags |= FieldFlag_Pointer;
- }
-
- // arrays, however, specify the size of a single element so we
- // need to parse the (possibly multi-dimensional) array declaration
- // in order to obtain the actual size of the array in the file.
- // Also we need to alter the lookup name to include no array
- // brackets anymore or size fixup won't work (if our size does
- // not match the size read from the DNA).
- if (*f.name.rbegin() == ']') {
- const std::string::size_type rb = f.name.find('[');
- if (rb == std::string::npos) {
- throw DeadlyImportError((format(),
- "BlenderDNA: Encountered invalid array declaration ",
- f.name
- ));
- }
-
- f.flags |= FieldFlag_Array;
- DNA::ExtractArraySize(f.name,f.array_sizes);
- f.name = f.name.substr(0,rb);
-
- f.size *= f.array_sizes[0] * f.array_sizes[1];
- }
-
- // maintain separate indexes
- s.indices[f.name] = s.fields.size()-1;
- offset += f.size;
- }
- s.size = offset;
- }
-
- DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
- " structures with totally ",fields," fields"));
+ StreamReaderAny& stream = *db.reader.get();
+ DNA& dna = db.dna;
+
+ if(!match4(stream,"SDNA")) {
+ throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
+ }
+
+ // name dictionary
+ if(!match4(stream,"NAME")) {
+ throw DeadlyImportError("BlenderDNA: Expected NAME field");
+ }
+
+ std::vector<std::string> names (stream.GetI4());
+ for(std::string& s : names) {
+ while (char c = stream.GetI1()) {
+ s += c;
+ }
+ }
+
+ // type dictionary
+ for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+ if(!match4(stream,"TYPE")) {
+ throw DeadlyImportError("BlenderDNA: Expected TYPE field");
+ }
+
+ std::vector<Type> types (stream.GetI4());
+ for(Type& s : types) {
+ while (char c = stream.GetI1()) {
+ s.name += c;
+ }
+ }
+
+ // type length dictionary
+ for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+ if(!match4(stream,"TLEN")) {
+ throw DeadlyImportError("BlenderDNA: Expected TLEN field");
+ }
+
+ for(Type& s : types) {
+ s.size = stream.GetI2();
+ }
+
+ // structures dictionary
+ for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+ if(!match4(stream,"STRC")) {
+ throw DeadlyImportError("BlenderDNA: Expected STRC field");
+ }
+
+ size_t end = stream.GetI4(), fields = 0;
+
+ dna.structures.reserve(end);
+ for(size_t i = 0; i != end; ++i) {
+
+ uint16_t n = stream.GetI2();
+ if (n >= types.size()) {
+ throw DeadlyImportError((format(),
+ "BlenderDNA: Invalid type index in structure name" ,n,
+ " (there are only ", types.size(), " entries)"
+ ));
+ }
+
+ // maintain separate indexes
+ dna.indices[types[n].name] = dna.structures.size();
+
+ dna.structures.push_back(Structure());
+ Structure& s = dna.structures.back();
+ s.name = types[n].name;
+ //s.index = dna.structures.size()-1;
+
+ n = stream.GetI2();
+ s.fields.reserve(n);
+
+ size_t offset = 0;
+ for (size_t m = 0; m < n; ++m, ++fields) {
+
+ uint16_t j = stream.GetI2();
+ if (j >= types.size()) {
+ throw DeadlyImportError((format(),
+ "BlenderDNA: Invalid type index in structure field ", j,
+ " (there are only ", types.size(), " entries)"
+ ));
+ }
+ s.fields.push_back(Field());
+ Field& f = s.fields.back();
+ f.offset = offset;
+
+ f.type = types[j].name;
+ f.size = types[j].size;
+
+ j = stream.GetI2();
+ if (j >= names.size()) {
+ throw DeadlyImportError((format(),
+ "BlenderDNA: Invalid name index in structure field ", j,
+ " (there are only ", names.size(), " entries)"
+ ));
+ }
+
+ f.name = names[j];
+ f.flags = 0u;
+
+ // pointers always specify the size of the pointee instead of their own.
+ // The pointer asterisk remains a property of the lookup name.
+ if (f.name[0] == '*') {
+ f.size = db.i64bit ? 8 : 4;
+ f.flags |= FieldFlag_Pointer;
+ }
+
+ // arrays, however, specify the size of a single element so we
+ // need to parse the (possibly multi-dimensional) array declaration
+ // in order to obtain the actual size of the array in the file.
+ // Also we need to alter the lookup name to include no array
+ // brackets anymore or size fixup won't work (if our size does
+ // not match the size read from the DNA).
+ if (*f.name.rbegin() == ']') {
+ const std::string::size_type rb = f.name.find('[');
+ if (rb == std::string::npos) {
+ throw DeadlyImportError((format(),
+ "BlenderDNA: Encountered invalid array declaration ",
+ f.name
+ ));
+ }
+
+ f.flags |= FieldFlag_Array;
+ DNA::ExtractArraySize(f.name,f.array_sizes);
+ f.name = f.name.substr(0,rb);
+
+ f.size *= f.array_sizes[0] * f.array_sizes[1];
+ }
+
+ // maintain separate indexes
+ s.indices[f.name] = s.fields.size()-1;
+ offset += f.size;
+ }
+ s.size = offset;
+ }
+
+ DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
+ " structures with totally ",fields," fields"));
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
- dna.DumpToFile();
+ dna.DumpToFile();
#endif
- dna.AddPrimitiveStructures();
- dna.RegisterConverters();
+ dna.AddPrimitiveStructures();
+ dna.RegisterConverters();
}
@@ -226,144 +225,146 @@ void DNAParser :: Parse ()
// ------------------------------------------------------------------------------------------------
void DNA :: DumpToFile()
{
- // we dont't bother using the VFS here for this is only for debugging.
- // (and all your bases are belong to us).
-
- std::ofstream f("dna.txt");
- if (f.fail()) {
- DefaultLogger::get()->error("Could not dump dna to dna.txt");
- return;
- }
- f << "Field format: type name offset size" << "\n";
- f << "Structure format: name size" << "\n";
-
- for_each(const Structure& s, structures) {
- f << s.name << " " << s.size << "\n\n";
- for_each(const Field& ff, s.fields) {
- f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl;
- }
- f << std::endl;
- }
- DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
+ // we dont't bother using the VFS here for this is only for debugging.
+ // (and all your bases are belong to us).
+
+ std::ofstream f("dna.txt");
+ if (f.fail()) {
+ DefaultLogger::get()->error("Could not dump dna to dna.txt");
+ return;
+ }
+ f << "Field format: type name offset size" << "\n";
+ f << "Structure format: name size" << "\n";
+
+ for(const Structure& s : structures) {
+ f << s.name << " " << s.size << "\n\n";
+ for(const Field& ff : s.fields) {
+ f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << "\n";
+ }
+ f << "\n";
+ }
+ f << std::flush;
+
+ DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
}
#endif
// ------------------------------------------------------------------------------------------------
/*static*/ void DNA :: ExtractArraySize(
- const std::string& out,
- size_t array_sizes[2]
+ const std::string& out,
+ size_t array_sizes[2]
)
{
- array_sizes[0] = array_sizes[1] = 1;
- std::string::size_type pos = out.find('[');
- if (pos++ == std::string::npos) {
- return;
- }
- array_sizes[0] = strtoul10(&out[pos]);
-
- pos = out.find('[',pos);
- if (pos++ == std::string::npos) {
- return;
- }
- array_sizes[1] = strtoul10(&out[pos]);
+ array_sizes[0] = array_sizes[1] = 1;
+ std::string::size_type pos = out.find('[');
+ if (pos++ == std::string::npos) {
+ return;
+ }
+ array_sizes[0] = strtoul10(&out[pos]);
+
+ pos = out.find('[',pos);
+ if (pos++ == std::string::npos) {
+ return;
+ }
+ array_sizes[1] = strtoul10(&out[pos]);
}
// ------------------------------------------------------------------------------------------------
-boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
- const Structure& structure,
- const FileDatabase& db
-) const
+std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
+ const Structure& structure,
+ const FileDatabase& db
+) const
{
- std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
- if (it == converters.end()) {
- return boost::shared_ptr< ElemBase >();
- }
-
- boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
- (structure.*((*it).second.second))(ret,db);
-
- return ret;
+ std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
+ if (it == converters.end()) {
+ return std::shared_ptr< ElemBase >();
+ }
+
+ std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
+ (structure.*((*it).second.second))(ret,db);
+
+ return ret;
}
// ------------------------------------------------------------------------------------------------
DNA::FactoryPair DNA :: GetBlobToStructureConverter(
- const Structure& structure,
- const FileDatabase& /*db*/
-) const
+ const Structure& structure,
+ const FileDatabase& /*db*/
+) const
{
- std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name);
- return it == converters.end() ? FactoryPair() : (*it).second;
+ std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name);
+ return it == converters.end() ? FactoryPair() : (*it).second;
}
// basing on http://www.blender.org/development/architecture/notes-on-sdna/
// ------------------------------------------------------------------------------------------------
void DNA :: AddPrimitiveStructures()
{
- // NOTE: these are just dummies. Their presence enforces
- // Structure::Convert<target_type> to be called on these
- // empty structures. These converters are special
- // overloads which scan the name of the structure and
- // perform the required data type conversion if one
- // of these special names is found in the structure
- // in question.
+ // NOTE: these are just dummies. Their presence enforces
+ // Structure::Convert<target_type> to be called on these
+ // empty structures. These converters are special
+ // overloads which scan the name of the structure and
+ // perform the required data type conversion if one
+ // of these special names is found in the structure
+ // in question.
- indices["int"] = structures.size();
- structures.push_back( Structure() );
- structures.back().name = "int";
- structures.back().size = 4;
+ indices["int"] = structures.size();
+ structures.push_back( Structure() );
+ structures.back().name = "int";
+ structures.back().size = 4;
- indices["short"] = structures.size();
- structures.push_back( Structure() );
- structures.back().name = "short";
- structures.back().size = 2;
+ indices["short"] = structures.size();
+ structures.push_back( Structure() );
+ structures.back().name = "short";
+ structures.back().size = 2;
- indices["char"] = structures.size();
- structures.push_back( Structure() );
- structures.back().name = "char";
- structures.back().size = 1;
+ indices["char"] = structures.size();
+ structures.push_back( Structure() );
+ structures.back().name = "char";
+ structures.back().size = 1;
- indices["float"] = structures.size();
- structures.push_back( Structure() );
- structures.back().name = "float";
- structures.back().size = 4;
+ indices["float"] = structures.size();
+ structures.push_back( Structure() );
+ structures.back().name = "float";
+ structures.back().size = 4;
- indices["double"] = structures.size();
- structures.push_back( Structure() );
- structures.back().name = "double";
- structures.back().size = 8;
+ indices["double"] = structures.size();
+ structures.push_back( Structure() );
+ structures.back().name = "double";
+ structures.back().size = 8;
- // no long, seemingly.
+ // no long, seemingly.
}
// ------------------------------------------------------------------------------------------------
void SectionParser :: Next()
{
- stream.SetCurrentPos(current.start + current.size);
+ stream.SetCurrentPos(current.start + current.size);
- const char tmp[] = {
- stream.GetI1(),
- stream.GetI1(),
- stream.GetI1(),
- stream.GetI1()
- };
- current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
+ const char tmp[] = {
+ stream.GetI1(),
+ stream.GetI1(),
+ stream.GetI1(),
+ stream.GetI1()
+ };
+ current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
- current.size = stream.GetI4();
- current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
+ current.size = stream.GetI4();
+ current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
- current.dna_index = stream.GetI4();
- current.num = stream.GetI4();
+ current.dna_index = stream.GetI4();
+ current.num = stream.GetI4();
- current.start = stream.GetCurrentPos();
- if (stream.GetRemainingSizeToLimit() < current.size) {
- throw DeadlyImportError("BLEND: invalid size of file block");
- }
+ current.start = stream.GetCurrentPos();
+ if (stream.GetRemainingSizeToLimit() < current.size) {
+ throw DeadlyImportError("BLEND: invalid size of file block");
+ }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
- DefaultLogger::get()->debug(current.id);
+ DefaultLogger::get()->debug(current.id);
#endif
}
diff --git a/src/3rdparty/assimp/code/BlenderDNA.h b/src/3rdparty/assimp/code/BlenderDNA.h
index c52eb28a3..801d68fce 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.h
+++ b/src/3rdparty/assimp/code/BlenderDNA.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,23 +23,23 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file BlenderDNA.h
- * @brief Blender `DNA` (file format specification embedded in
+ * @brief Blender `DNA` (file format specification embedded in
* blend file itself) loader.
*/
#ifndef INCLUDED_AI_BLEND_DNA_H
@@ -47,24 +47,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "TinyFormatter.h"
+#include "StreamReader.h"
+#include <assimp/DefaultLogger.hpp>
+#include <stdint.h>
+#include <memory>
+
// enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG
-# define ASSIMP_BUILD_BLENDER_DEBUG
+# define ASSIMP_BUILD_BLENDER_DEBUG
#endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS
-namespace Assimp {
- template <bool,bool> class StreamReader;
- typedef StreamReader<true,true> StreamReaderAny;
+namespace Assimp {
+ template <bool,bool> class StreamReader;
+ typedef StreamReader<true,true> StreamReaderAny;
- namespace Blender {
- class FileDatabase;
- struct FileBlockHead;
+ namespace Blender {
+ class FileDatabase;
+ struct FileBlockHead;
- template <template <typename> class TOUT>
- class ObjectCache;
+ template <template <typename> class TOUT>
+ class ObjectCache;
// -------------------------------------------------------------------------------
/** Exception class used by the blender loader to selectively catch exceptions
@@ -75,40 +80,40 @@ namespace Assimp {
// -------------------------------------------------------------------------------
struct Error : DeadlyImportError
{
- Error (const std::string& s)
- : DeadlyImportError(s)
- {}
+ Error (const std::string& s)
+ : DeadlyImportError(s)
+ {}
};
// -------------------------------------------------------------------------------
/** The only purpose of this structure is to feed a virtual dtor into its
* descendents. It serves as base class for all data structure fields. */
// -------------------------------------------------------------------------------
-struct ElemBase
+struct ElemBase
{
- virtual ~ElemBase() {}
-
- /** Type name of the element. The type
- * string points is the `c_str` of the `name` attribute of the
- * corresponding `Structure`, that is, it is only valid as long
- * as the DNA is not modified. The dna_type is only set if the
- * data type is not static, i.e. a boost::shared_ptr<ElemBase>
- * in the scene description would have its type resolved
- * at runtime, so this member is always set. */
- const char* dna_type;
+ virtual ~ElemBase() {}
+
+ /** Type name of the element. The type
+ * string points is the `c_str` of the `name` attribute of the
+ * corresponding `Structure`, that is, it is only valid as long
+ * as the DNA is not modified. The dna_type is only set if the
+ * data type is not static, i.e. a std::shared_ptr<ElemBase>
+ * in the scene description would have its type resolved
+ * at runtime, so this member is always set. */
+ const char* dna_type;
};
// -------------------------------------------------------------------------------
/** Represents a generic pointer to a memory location, which can be either 32
* or 64 bits. These pointers are loaded from the BLEND file and finally
- * fixed to point to the real, converted representation of the objects
+ * fixed to point to the real, converted representation of the objects
* they used to point to.*/
// -------------------------------------------------------------------------------
struct Pointer
{
- Pointer() : val() {}
- uint64_t val;
+ Pointer() : val() {}
+ uint64_t val;
};
// -------------------------------------------------------------------------------
@@ -116,13 +121,13 @@ struct Pointer
// -------------------------------------------------------------------------------
struct FileOffset
{
- FileOffset() : val() {}
- uint64_t val;
+ FileOffset() : val() {}
+ uint64_t val;
};
// -------------------------------------------------------------------------------
/** Dummy derivate of std::vector to be able to use it in templates simultaenously
- * with boost::shared_ptr, which takes only one template argument
+ * with std::shared_ptr, which takes only one template argument
* while std::vector takes three. Also we need to provide some special member
* functions of shared_ptr */
// -------------------------------------------------------------------------------
@@ -130,44 +135,44 @@ template <typename T>
class vector : public std::vector<T>
{
public:
- using std::vector<T>::resize;
- using std::vector<T>::empty;
+ using std::vector<T>::resize;
+ using std::vector<T>::empty;
- void reset() {
- resize(0);
- }
+ void reset() {
+ resize(0);
+ }
- operator bool () const {
- return !empty();
- }
+ operator bool () const {
+ return !empty();
+ }
};
// -------------------------------------------------------------------------------
/** Mixed flags for use in #Field */
// -------------------------------------------------------------------------------
-enum FieldFlags
+enum FieldFlags
{
- FieldFlag_Pointer = 0x1,
- FieldFlag_Array = 0x2
+ FieldFlag_Pointer = 0x1,
+ FieldFlag_Array = 0x2
};
// -------------------------------------------------------------------------------
/** Represents a single member of a data structure in a BLEND file */
// -------------------------------------------------------------------------------
-struct Field
-{
- std::string name;
- std::string type;
+struct Field
+{
+ std::string name;
+ std::string type;
- size_t size;
- size_t offset;
+ size_t size;
+ size_t offset;
- /** Size of each array dimension. For flat arrays,
- * the second dimension is set to 1. */
- size_t array_sizes[2];
+ /** Size of each array dimension. For flat arrays,
+ * the second dimension is set to 1. */
+ size_t array_sizes[2];
- /** Any of the #FieldFlags enumerated values */
- unsigned int flags;
+ /** Any of the #FieldFlags enumerated values */
+ unsigned int flags;
};
// -------------------------------------------------------------------------------
@@ -175,18 +180,18 @@ struct Field
* mission critical so we need them, while others can silently be default
* initialized and no animations are harmed. */
// -------------------------------------------------------------------------------
-enum ErrorPolicy
+enum ErrorPolicy
{
- /** Substitute default value and ignore */
- ErrorPolicy_Igno,
- /** Substitute default value and write to log */
- ErrorPolicy_Warn,
- /** Substitute a massive error message and crash the whole matrix. Its time for another zion */
- ErrorPolicy_Fail
+ /** Substitute default value and ignore */
+ ErrorPolicy_Igno,
+ /** Substitute default value and write to log */
+ ErrorPolicy_Warn,
+ /** Substitute a massive error message and crash the whole matrix. Its time for another zion */
+ ErrorPolicy_Fail
};
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
-# define ErrorPolicy_Igno ErrorPolicy_Warn
+# define ErrorPolicy_Igno ErrorPolicy_Warn
#endif
// -------------------------------------------------------------------------------
@@ -197,395 +202,395 @@ enum ErrorPolicy
* binary `blob` read from the file to such a structure instance with
* meaningful contents. */
// -------------------------------------------------------------------------------
-class Structure
+class Structure
{
- template <template <typename> class> friend class ObjectCache;
+ template <template <typename> class> friend class ObjectCache;
public:
- Structure()
- : cache_idx(-1)
- {}
+ Structure()
+ : cache_idx(static_cast<size_t>(-1) )
+ {}
public:
- // publicly accessible members
- std::string name;
- vector< Field > fields;
- std::map<std::string, size_t> indices;
+ // publicly accessible members
+ std::string name;
+ vector< Field > fields;
+ std::map<std::string, size_t> indices;
- size_t size;
+ size_t size;
public:
- // --------------------------------------------------------
- /** Access a field of the structure by its canonical name. The pointer version
- * returns NULL on failure while the reference version raises an import error. */
- inline const Field& operator [] (const std::string& ss) const;
- inline const Field* Get (const std::string& ss) const;
+ // --------------------------------------------------------
+ /** Access a field of the structure by its canonical name. The pointer version
+ * returns NULL on failure while the reference version raises an import error. */
+ inline const Field& operator [] (const std::string& ss) const;
+ inline const Field* Get (const std::string& ss) const;
- // --------------------------------------------------------
- /** Access a field of the structure by its index */
- inline const Field& operator [] (const size_t i) const;
+ // --------------------------------------------------------
+ /** Access a field of the structure by its index */
+ inline const Field& operator [] (const size_t i) const;
- // --------------------------------------------------------
- inline bool operator== (const Structure& other) const {
- return name == other.name; // name is meant to be an unique identifier
- }
+ // --------------------------------------------------------
+ inline bool operator== (const Structure& other) const {
+ return name == other.name; // name is meant to be an unique identifier
+ }
- // --------------------------------------------------------
- inline bool operator!= (const Structure& other) const {
- return name != other.name;
- }
+ // --------------------------------------------------------
+ inline bool operator!= (const Structure& other) const {
+ return name != other.name;
+ }
public:
- // --------------------------------------------------------
- /** Try to read an instance of the structure from the stream
- * and attempt to convert to `T`. This is done by
- * an appropriate specialization. If none is available,
- * a compiler complain is the result.
- * @param dest Destination value to be written
- * @param db File database, including input stream. */
- template <typename T> inline void Convert (T& dest,
- const FileDatabase& db) const;
-
-
-
- // --------------------------------------------------------
- // generic converter
- template <typename T>
- void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const;
-
- // --------------------------------------------------------
- // generic allocator
- template <typename T> boost::shared_ptr<ElemBase> Allocate() const;
-
-
-
- // --------------------------------------------------------
- // field parsing for 1d arrays
- template <int error_policy, typename T, size_t M>
- void ReadFieldArray(T (& out)[M], const char* name,
- const FileDatabase& db) const;
-
- // --------------------------------------------------------
- // field parsing for 2d arrays
- template <int error_policy, typename T, size_t M, size_t N>
- void ReadFieldArray2(T (& out)[M][N], const char* name,
- const FileDatabase& db) const;
-
- // --------------------------------------------------------
- // field parsing for pointer or dynamic array types
- // (boost::shared_ptr or boost::shared_array)
- // The return value indicates whether the data was already cached.
- template <int error_policy, template <typename> class TOUT, typename T>
- bool ReadFieldPtr(TOUT<T>& out, const char* name,
- const FileDatabase& db,
- bool non_recursive = false) const;
-
- // --------------------------------------------------------
- // field parsing for static arrays of pointer or dynamic
- // array types (boost::shared_ptr[] or boost::shared_array[])
- // The return value indicates whether the data was already cached.
- template <int error_policy, template <typename> class TOUT, typename T, size_t N>
- bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
- const FileDatabase& db) const;
-
- // --------------------------------------------------------
- // field parsing for `normal` values
- // The return value indicates whether the data was already cached.
- template <int error_policy, typename T>
- void ReadField(T& out, const char* name,
- const FileDatabase& db) const;
+ // --------------------------------------------------------
+ /** Try to read an instance of the structure from the stream
+ * and attempt to convert to `T`. This is done by
+ * an appropriate specialization. If none is available,
+ * a compiler complain is the result.
+ * @param dest Destination value to be written
+ * @param db File database, including input stream. */
+ template <typename T> inline void Convert (T& dest,
+ const FileDatabase& db) const;
+
+
+
+ // --------------------------------------------------------
+ // generic converter
+ template <typename T>
+ void Convert(std::shared_ptr<ElemBase> in,const FileDatabase& db) const;
+
+ // --------------------------------------------------------
+ // generic allocator
+ template <typename T> std::shared_ptr<ElemBase> Allocate() const;
+
+
+
+ // --------------------------------------------------------
+ // field parsing for 1d arrays
+ template <int error_policy, typename T, size_t M>
+ void ReadFieldArray(T (& out)[M], const char* name,
+ const FileDatabase& db) const;
+
+ // --------------------------------------------------------
+ // field parsing for 2d arrays
+ template <int error_policy, typename T, size_t M, size_t N>
+ void ReadFieldArray2(T (& out)[M][N], const char* name,
+ const FileDatabase& db) const;
+
+ // --------------------------------------------------------
+ // field parsing for pointer or dynamic array types
+ // (std::shared_ptr)
+ // The return value indicates whether the data was already cached.
+ template <int error_policy, template <typename> class TOUT, typename T>
+ bool ReadFieldPtr(TOUT<T>& out, const char* name,
+ const FileDatabase& db,
+ bool non_recursive = false) const;
+
+ // --------------------------------------------------------
+ // field parsing for static arrays of pointer or dynamic
+ // array types (std::shared_ptr[])
+ // The return value indicates whether the data was already cached.
+ template <int error_policy, template <typename> class TOUT, typename T, size_t N>
+ bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
+ const FileDatabase& db) const;
+
+ // --------------------------------------------------------
+ // field parsing for `normal` values
+ // The return value indicates whether the data was already cached.
+ template <int error_policy, typename T>
+ void ReadField(T& out, const char* name,
+ const FileDatabase& db) const;
private:
- // --------------------------------------------------------
- template <template <typename> class TOUT, typename T>
- bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
- const FileDatabase& db, const Field& f,
- bool non_recursive = false) const;
+ // --------------------------------------------------------
+ template <template <typename> class TOUT, typename T>
+ bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
+ const FileDatabase& db, const Field& f,
+ bool non_recursive = false) const;
- // --------------------------------------------------------
- template <template <typename> class TOUT, typename T>
- bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
- const FileDatabase& db, const Field& f, bool) const;
+ // --------------------------------------------------------
+ template <template <typename> class TOUT, typename T>
+ bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
+ const FileDatabase& db, const Field& f, bool) const;
- // --------------------------------------------------------
- bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
- const FileDatabase& db, const Field& f, bool) const;
+ // --------------------------------------------------------
+ bool ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
+ const FileDatabase& db, const Field& f, bool) const;
- // --------------------------------------------------------
- inline const FileBlockHead* LocateFileBlockForAddress(
- const Pointer & ptrval,
- const FileDatabase& db) const;
+ // --------------------------------------------------------
+ inline const FileBlockHead* LocateFileBlockForAddress(
+ const Pointer & ptrval,
+ const FileDatabase& db) const;
private:
- // ------------------------------------------------------------------------------
- template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const {
- out = boost::shared_ptr<T>(new T());
- s = 1;
- return out.get();
- }
-
- template <typename T> T* _allocate(vector<T>& out, size_t& s) const {
- out.resize(s);
- return s ? &out.front() : NULL;
- }
-
- // --------------------------------------------------------
- template <int error_policy>
- struct _defaultInitializer {
-
- template <typename T, unsigned int N>
- void operator ()(T (& out)[N], const char* = NULL) {
- for (unsigned int i = 0; i < N; ++i) {
- out[i] = T();
- }
- }
-
- template <typename T, unsigned int N, unsigned int M>
- void operator ()(T (& out)[N][M], const char* = NULL) {
- for (unsigned int i = 0; i < N; ++i) {
- for (unsigned int j = 0; j < M; ++j) {
- out[i][j] = T();
- }
- }
- }
-
- template <typename T>
- void operator ()(T& out, const char* = NULL) {
- out = T();
- }
- };
+ // ------------------------------------------------------------------------------
+ template <typename T> T* _allocate(std::shared_ptr<T>& out, size_t& s) const {
+ out = std::shared_ptr<T>(new T());
+ s = 1;
+ return out.get();
+ }
+
+ template <typename T> T* _allocate(vector<T>& out, size_t& s) const {
+ out.resize(s);
+ return s ? &out.front() : NULL;
+ }
+
+ // --------------------------------------------------------
+ template <int error_policy>
+ struct _defaultInitializer {
+
+ template <typename T, unsigned int N>
+ void operator ()(T (& out)[N], const char* = NULL) {
+ for (unsigned int i = 0; i < N; ++i) {
+ out[i] = T();
+ }
+ }
+
+ template <typename T, unsigned int N, unsigned int M>
+ void operator ()(T (& out)[N][M], const char* = NULL) {
+ for (unsigned int i = 0; i < N; ++i) {
+ for (unsigned int j = 0; j < M; ++j) {
+ out[i][j] = T();
+ }
+ }
+ }
+
+ template <typename T>
+ void operator ()(T& out, const char* = NULL) {
+ out = T();
+ }
+ };
private:
- mutable size_t cache_idx;
+ mutable size_t cache_idx;
};
// --------------------------------------------------------
template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
- template <typename T>
- void operator ()(T& out, const char* reason = "<add reason>") {
- DefaultLogger::get()->warn(reason);
+ template <typename T>
+ void operator ()(T& out, const char* reason = "<add reason>") {
+ DefaultLogger::get()->warn(reason);
- // ... and let the show go on
- _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
- }
+ // ... and let the show go on
+ _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
+ }
};
template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
- template <typename T>
- void operator ()(T& /*out*/,const char* = "") {
- // obviously, it is crucial that _DefaultInitializer is used
- // only from within a catch clause.
- throw;
- }
+ template <typename T>
+ void operator ()(T& /*out*/,const char* = "") {
+ // obviously, it is crucial that _DefaultInitializer is used
+ // only from within a catch clause.
+ throw;
+ }
};
// -------------------------------------------------------------------------------------------------------
-template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
- const Pointer & ptrval,
- const FileDatabase& db,
- const Field& f,
- bool
- ) const;
+template <> inline bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
+ const Pointer & ptrval,
+ const FileDatabase& db,
+ const Field& f,
+ bool
+ ) const;
// -------------------------------------------------------------------------------
/** Represents the full data structure information for a single BLEND file.
* This data is extracted from the DNA1 chunk in the file.
- * #DNAParser does the reading and represents currently the only place where
+ * #DNAParser does the reading and represents currently the only place where
* DNA is altered.*/
// -------------------------------------------------------------------------------
class DNA
{
public:
- typedef void (Structure::*ConvertProcPtr) (
- boost::shared_ptr<ElemBase> in,
- const FileDatabase&
- ) const;
+ typedef void (Structure::*ConvertProcPtr) (
+ std::shared_ptr<ElemBase> in,
+ const FileDatabase&
+ ) const;
+
+ typedef std::shared_ptr<ElemBase> (
+ Structure::*AllocProcPtr) () const;
- typedef boost::shared_ptr<ElemBase> (
- Structure::*AllocProcPtr) () const;
-
- typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
+ typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
public:
- std::map<std::string, FactoryPair > converters;
- vector<Structure > structures;
- std::map<std::string, size_t> indices;
+ std::map<std::string, FactoryPair > converters;
+ vector<Structure > structures;
+ std::map<std::string, size_t> indices;
public:
- // --------------------------------------------------------
- /** Access a structure by its canonical name, the pointer version returns NULL on failure
- * while the reference version raises an error. */
- inline const Structure& operator [] (const std::string& ss) const;
- inline const Structure* Get (const std::string& ss) const;
+ // --------------------------------------------------------
+ /** Access a structure by its canonical name, the pointer version returns NULL on failure
+ * while the reference version raises an error. */
+ inline const Structure& operator [] (const std::string& ss) const;
+ inline const Structure* Get (const std::string& ss) const;
- // --------------------------------------------------------
- /** Access a structure by its index */
- inline const Structure& operator [] (const size_t i) const;
+ // --------------------------------------------------------
+ /** Access a structure by its index */
+ inline const Structure& operator [] (const size_t i) const;
public:
- // --------------------------------------------------------
- /** Add structure definitions for all the primitive types,
- * i.e. integer, short, char, float */
- void AddPrimitiveStructures();
-
- // --------------------------------------------------------
- /** Fill the @c converters member with converters for all
- * known data types. The implementation of this method is
- * in BlenderScene.cpp and is machine-generated.
- * Converters are used to quickly handle objects whose
- * exact data type is a runtime-property and not yet
- * known at compile time (consier Object::data).*/
- void RegisterConverters();
-
-
- // --------------------------------------------------------
- /** Take an input blob from the stream, interpret it according to
- * a its structure name and convert it to the intermediate
- * representation.
- * @param structure Destination structure definition
- * @param db File database.
- * @return A null pointer if no appropriate converter is available.*/
- boost::shared_ptr< ElemBase > ConvertBlobToStructure(
- const Structure& structure,
- const FileDatabase& db
- ) const;
-
- // --------------------------------------------------------
- /** Find a suitable conversion function for a given Structure.
- * Such a converter function takes a blob from the input
- * stream, reads as much as it needs, and builds up a
- * complete object in intermediate representation.
- * @param structure Destination structure definition
- * @param db File database.
- * @return A null pointer in .first if no appropriate converter is available.*/
- FactoryPair GetBlobToStructureConverter(
- const Structure& structure,
- const FileDatabase& db
- ) const;
+ // --------------------------------------------------------
+ /** Add structure definitions for all the primitive types,
+ * i.e. integer, short, char, float */
+ void AddPrimitiveStructures();
+
+ // --------------------------------------------------------
+ /** Fill the @c converters member with converters for all
+ * known data types. The implementation of this method is
+ * in BlenderScene.cpp and is machine-generated.
+ * Converters are used to quickly handle objects whose
+ * exact data type is a runtime-property and not yet
+ * known at compile time (consier Object::data).*/
+ void RegisterConverters();
+
+
+ // --------------------------------------------------------
+ /** Take an input blob from the stream, interpret it according to
+ * a its structure name and convert it to the intermediate
+ * representation.
+ * @param structure Destination structure definition
+ * @param db File database.
+ * @return A null pointer if no appropriate converter is available.*/
+ std::shared_ptr< ElemBase > ConvertBlobToStructure(
+ const Structure& structure,
+ const FileDatabase& db
+ ) const;
+
+ // --------------------------------------------------------
+ /** Find a suitable conversion function for a given Structure.
+ * Such a converter function takes a blob from the input
+ * stream, reads as much as it needs, and builds up a
+ * complete object in intermediate representation.
+ * @param structure Destination structure definition
+ * @param db File database.
+ * @return A null pointer in .first if no appropriate converter is available.*/
+ FactoryPair GetBlobToStructureConverter(
+ const Structure& structure,
+ const FileDatabase& db
+ ) const;
#ifdef ASSIMP_BUILD_BLENDER_DEBUG
- // --------------------------------------------------------
- /** Dump the DNA to a text file. This is for debugging purposes.
- * The output file is `dna.txt` in the current working folder*/
- void DumpToFile();
+ // --------------------------------------------------------
+ /** Dump the DNA to a text file. This is for debugging purposes.
+ * The output file is `dna.txt` in the current working folder*/
+ void DumpToFile();
#endif
- // --------------------------------------------------------
- /** Extract array dimensions from a C array declaration, such
- * as `...[4][6]`. Returned string would be `...[][]`.
- * @param out
- * @param array_sizes Receive maximally two array dimensions,
- * the second element is set to 1 if the array is flat.
- * Both are set to 1 if the input is not an array.
- * @throw DeadlyImportError if more than 2 dimensions are
- * encountered. */
- static void ExtractArraySize(
- const std::string& out,
- size_t array_sizes[2]
- );
+ // --------------------------------------------------------
+ /** Extract array dimensions from a C array declaration, such
+ * as `...[4][6]`. Returned string would be `...[][]`.
+ * @param out
+ * @param array_sizes Receive maximally two array dimensions,
+ * the second element is set to 1 if the array is flat.
+ * Both are set to 1 if the input is not an array.
+ * @throw DeadlyImportError if more than 2 dimensions are
+ * encountered. */
+ static void ExtractArraySize(
+ const std::string& out,
+ size_t array_sizes[2]
+ );
};
// special converters for primitive types
-template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const;
// -------------------------------------------------------------------------------
/** Describes a master file block header. Each master file sections holds n
* elements of a certain SDNA structure (or otherwise unspecified data). */
// -------------------------------------------------------------------------------
-struct FileBlockHead
+struct FileBlockHead
{
- // points right after the header of the file block
- StreamReaderAny::pos start;
+ // points right after the header of the file block
+ StreamReaderAny::pos start;
- std::string id;
- size_t size;
+ std::string id;
+ size_t size;
- // original memory address of the data
- Pointer address;
+ // original memory address of the data
+ Pointer address;
- // index into DNA
- unsigned int dna_index;
+ // index into DNA
+ unsigned int dna_index;
- // number of structure instances to follow
- size_t num;
+ // number of structure instances to follow
+ size_t num;
- // file blocks are sorted by address to quickly locate specific memory addresses
- bool operator < (const FileBlockHead& o) const {
- return address.val < o.address.val;
- }
+ // file blocks are sorted by address to quickly locate specific memory addresses
+ bool operator < (const FileBlockHead& o) const {
+ return address.val < o.address.val;
+ }
- // for std::upper_bound
- operator const Pointer& () const {
- return address;
- }
+ // for std::upper_bound
+ operator const Pointer& () const {
+ return address;
+ }
};
// for std::upper_bound
inline bool operator< (const Pointer& a, const Pointer& b) {
- return a.val < b.val;
+ return a.val < b.val;
}
// -------------------------------------------------------------------------------
/** Utility to read all master file blocks in turn. */
// -------------------------------------------------------------------------------
-class SectionParser
+class SectionParser
{
public:
- // --------------------------------------------------------
- /** @param stream Inout stream, must point to the
- * first section in the file. Call Next() once
- * to have it read.
- * @param ptr64 Pointer size in file is 64 bits? */
- SectionParser(StreamReaderAny& stream,bool ptr64)
- : stream(stream)
- , ptr64(ptr64)
- {
- current.size = current.start = 0;
- }
+ // --------------------------------------------------------
+ /** @param stream Inout stream, must point to the
+ * first section in the file. Call Next() once
+ * to have it read.
+ * @param ptr64 Pointer size in file is 64 bits? */
+ SectionParser(StreamReaderAny& stream,bool ptr64)
+ : stream(stream)
+ , ptr64(ptr64)
+ {
+ current.size = current.start = 0;
+ }
public:
- // --------------------------------------------------------
- const FileBlockHead& GetCurrent() const {
- return current;
- }
-
+ // --------------------------------------------------------
+ const FileBlockHead& GetCurrent() const {
+ return current;
+ }
+
public:
- // --------------------------------------------------------
- /** Advance to the next section.
- * @throw DeadlyImportError if the last chunk was passed. */
- void Next();
+ // --------------------------------------------------------
+ /** Advance to the next section.
+ * @throw DeadlyImportError if the last chunk was passed. */
+ void Next();
public:
- FileBlockHead current;
- StreamReaderAny& stream;
- bool ptr64;
+ FileBlockHead current;
+ StreamReaderAny& stream;
+ bool ptr64;
};
@@ -597,31 +602,31 @@ class Statistics {
public:
- Statistics ()
- : fields_read ()
- , pointers_resolved ()
- , cache_hits ()
-// , blocks_read ()
- , cached_objects ()
- {}
+ Statistics ()
+ : fields_read ()
+ , pointers_resolved ()
+ , cache_hits ()
+// , blocks_read ()
+ , cached_objects ()
+ {}
public:
- /** total number of fields we read */
- unsigned int fields_read;
+ /** total number of fields we read */
+ unsigned int fields_read;
- /** total number of resolved pointers */
- unsigned int pointers_resolved;
+ /** total number of resolved pointers */
+ unsigned int pointers_resolved;
- /** number of pointers resolved from the cache */
- unsigned int cache_hits;
+ /** number of pointers resolved from the cache */
+ unsigned int cache_hits;
- /** number of blocks (from FileDatabase::entries)
- we did actually read from. */
- // unsigned int blocks_read;
+ /** number of blocks (from FileDatabase::entries)
+ we did actually read from. */
+ // unsigned int blocks_read;
- /** objects in FileData::cache */
- unsigned int cached_objects;
+ /** objects in FileData::cache */
+ unsigned int cached_objects;
};
#endif
@@ -630,173 +635,173 @@ public:
* avoids circular references and avoids object duplication. */
// -------------------------------------------------------------------------------
template <template <typename> class TOUT>
-class ObjectCache
+class ObjectCache
{
public:
- typedef std::map< Pointer, TOUT<ElemBase> > StructureCache;
+ typedef std::map< Pointer, TOUT<ElemBase> > StructureCache;
public:
- ObjectCache(const FileDatabase& db)
- : db(db)
- {
- // currently there are only ~400 structure records per blend file.
- // we read only a small part of them and don't cache objects
- // which we don't need, so this should suffice.
- caches.reserve(64);
- }
+ ObjectCache(const FileDatabase& db)
+ : db(db)
+ {
+ // currently there are only ~400 structure records per blend file.
+ // we read only a small part of them and don't cache objects
+ // which we don't need, so this should suffice.
+ caches.reserve(64);
+ }
public:
- // --------------------------------------------------------
- /** Check whether a specific item is in the cache.
- * @param s Data type of the item
- * @param out Output pointer. Unchanged if the
- * cache doens't know the item yet.
- * @param ptr Item address to look for. */
- template <typename T> void get (
- const Structure& s,
- TOUT<T>& out,
- const Pointer& ptr) const;
-
- // --------------------------------------------------------
- /** Add an item to the cache after the item has
- * been fully read. Do not insert anything that
- * may be faulty or might cause the loading
- * to abort.
- * @param s Data type of the item
- * @param out Item to insert into the cache
- * @param ptr address (cache key) of the item. */
- template <typename T> void set
- (const Structure& s,
- const TOUT<T>& out,
- const Pointer& ptr);
+ // --------------------------------------------------------
+ /** Check whether a specific item is in the cache.
+ * @param s Data type of the item
+ * @param out Output pointer. Unchanged if the
+ * cache doens't know the item yet.
+ * @param ptr Item address to look for. */
+ template <typename T> void get (
+ const Structure& s,
+ TOUT<T>& out,
+ const Pointer& ptr) const;
+
+ // --------------------------------------------------------
+ /** Add an item to the cache after the item has
+ * been fully read. Do not insert anything that
+ * may be faulty or might cause the loading
+ * to abort.
+ * @param s Data type of the item
+ * @param out Item to insert into the cache
+ * @param ptr address (cache key) of the item. */
+ template <typename T> void set
+ (const Structure& s,
+ const TOUT<T>& out,
+ const Pointer& ptr);
private:
- mutable vector<StructureCache> caches;
- const FileDatabase& db;
+ mutable vector<StructureCache> caches;
+ const FileDatabase& db;
};
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
-template <> class ObjectCache<Blender::vector>
+template <> class ObjectCache<Blender::vector>
{
public:
- ObjectCache(const FileDatabase&) {}
+ ObjectCache(const FileDatabase&) {}
- template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {}
- template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {}
+ template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {}
+ template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {}
};
#ifdef _MSC_VER
-# pragma warning(disable:4355)
+# pragma warning(disable:4355)
#endif
// -------------------------------------------------------------------------------
/** Memory representation of a full BLEND file and all its dependencies. The
* output aiScene is constructed from an instance of this data structure. */
// -------------------------------------------------------------------------------
-class FileDatabase
+class FileDatabase
{
- template <template <typename> class TOUT> friend class ObjectCache;
+ template <template <typename> class TOUT> friend class ObjectCache;
public:
- FileDatabase()
- : _cacheArrays(*this)
- , _cache(*this)
- , next_cache_idx()
- {}
+ FileDatabase()
+ : _cacheArrays(*this)
+ , _cache(*this)
+ , next_cache_idx()
+ {}
public:
- // publicly accessible fields
- bool i64bit;
- bool little;
+ // publicly accessible fields
+ bool i64bit;
+ bool little;
- DNA dna;
- boost::shared_ptr< StreamReaderAny > reader;
- vector< FileBlockHead > entries;
+ DNA dna;
+ std::shared_ptr< StreamReaderAny > reader;
+ vector< FileBlockHead > entries;
public:
- Statistics& stats() const {
- return _stats;
- }
+ Statistics& stats() const {
+ return _stats;
+ }
- // For all our templates to work on both shared_ptr's and vector's
- // using the same code, a dummy cache for arrays is provided. Actually,
- // arrays of objects are never cached because we can't easily
- // ensure their proper destruction.
- template <typename T>
- ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const {
- return _cache;
- }
+ // For all our templates to work on both shared_ptr's and vector's
+ // using the same code, a dummy cache for arrays is provided. Actually,
+ // arrays of objects are never cached because we can't easily
+ // ensure their proper destruction.
+ template <typename T>
+ ObjectCache<std::shared_ptr>& cache(std::shared_ptr<T>& /*in*/) const {
+ return _cache;
+ }
- template <typename T>
- ObjectCache<vector>& cache(vector<T>& /*in*/) const {
- return _cacheArrays;
- }
+ template <typename T>
+ ObjectCache<vector>& cache(vector<T>& /*in*/) const {
+ return _cacheArrays;
+ }
private:
-
+
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- mutable Statistics _stats;
+ mutable Statistics _stats;
#endif
- mutable ObjectCache<vector> _cacheArrays;
- mutable ObjectCache<boost::shared_ptr> _cache;
+ mutable ObjectCache<vector> _cacheArrays;
+ mutable ObjectCache<std::shared_ptr> _cache;
- mutable size_t next_cache_idx;
+ mutable size_t next_cache_idx;
};
#ifdef _MSC_VER
-# pragma warning(default:4355)
+# pragma warning(default:4355)
#endif
// -------------------------------------------------------------------------------
/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
// -------------------------------------------------------------------------------
-class DNAParser
+class DNAParser
{
public:
- /** Bind the parser to a empty DNA and an input stream */
- DNAParser(FileDatabase& db)
- : db(db)
- {}
+ /** Bind the parser to a empty DNA and an input stream */
+ DNAParser(FileDatabase& db)
+ : db(db)
+ {}
public:
- // --------------------------------------------------------
- /** Locate the DNA in the file and parse it. The input
- * stream is expected to point to the beginning of the DN1
- * chunk at the time this method is called and is
- * undefined afterwards.
- * @throw DeadlyImportError if the DNA cannot be read.
- * @note The position of the stream pointer is undefined
- * afterwards.*/
- void Parse ();
+ // --------------------------------------------------------
+ /** Locate the DNA in the file and parse it. The input
+ * stream is expected to point to the beginning of the DN1
+ * chunk at the time this method is called and is
+ * undefined afterwards.
+ * @throw DeadlyImportError if the DNA cannot be read.
+ * @note The position of the stream pointer is undefined
+ * afterwards.*/
+ void Parse ();
public:
- /** Obtain a reference to the extracted DNA information */
- const Blender::DNA& GetDNA() const {
- return db.dna;
- }
+ /** Obtain a reference to the extracted DNA information */
+ const Blender::DNA& GetDNA() const {
+ return db.dna;
+ }
private:
- FileDatabase& db;
+ FileDatabase& db;
};
- } // end Blend
+ } // end Blend
} // end Assimp
#include "BlenderDNA.inl"
diff --git a/src/3rdparty/assimp/code/BlenderDNA.inl b/src/3rdparty/assimp/code/BlenderDNA.inl
index d555b7c85..0b3f2fd02 100644
--- a/src/3rdparty/assimp/code/BlenderDNA.inl
+++ b/src/3rdparty/assimp/code/BlenderDNA.inl
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,113 +23,115 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file BlenderDNA.inl
- * @brief Blender `DNA` (file format specification embedded in
+ * @brief Blender `DNA` (file format specification embedded in
* blend file itself) loader.
*/
#ifndef INCLUDED_AI_BLEND_DNA_INL
#define INCLUDED_AI_BLEND_DNA_INL
-namespace Assimp {
- namespace Blender {
+#include <memory>
+
+namespace Assimp {
+ namespace Blender {
//--------------------------------------------------------------------------------
const Field& Structure :: operator [] (const std::string& ss) const
{
- std::map<std::string, size_t>::const_iterator it = indices.find(ss);
- if (it == indices.end()) {
- throw Error((Formatter::format(),
- "BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
- ));
- }
-
- return fields[(*it).second];
+ std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+ if (it == indices.end()) {
+ throw Error((Formatter::format(),
+ "BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
+ ));
+ }
+
+ return fields[(*it).second];
}
//--------------------------------------------------------------------------------
const Field* Structure :: Get (const std::string& ss) const
{
- std::map<std::string, size_t>::const_iterator it = indices.find(ss);
- return it == indices.end() ? NULL : &fields[(*it).second];
+ std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+ return it == indices.end() ? NULL : &fields[(*it).second];
}
//--------------------------------------------------------------------------------
-const Field& Structure :: operator [] (const size_t i) const
+const Field& Structure :: operator [] (const size_t i) const
{
- if (i >= fields.size()) {
- throw Error((Formatter::format(),
- "BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
- ));
- }
+ if (i >= fields.size()) {
+ throw Error((Formatter::format(),
+ "BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
+ ));
+ }
- return fields[i];
+ return fields[i];
}
//--------------------------------------------------------------------------------
-template <typename T> boost::shared_ptr<ElemBase> Structure :: Allocate() const
+template <typename T> std::shared_ptr<ElemBase> Structure :: Allocate() const
{
- return boost::shared_ptr<T>(new T());
+ return std::shared_ptr<T>(new T());
}
//--------------------------------------------------------------------------------
template <typename T> void Structure :: Convert(
- boost::shared_ptr<ElemBase> in,
- const FileDatabase& db) const
+ std::shared_ptr<ElemBase> in,
+ const FileDatabase& db) const
{
- Convert<T> (*static_cast<T*> ( in.get() ),db);
+ Convert<T> (*static_cast<T*> ( in.get() ),db);
}
//--------------------------------------------------------------------------------
template <int error_policy, typename T, size_t M>
void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatabase& db) const
{
- const StreamReaderAny::pos old = db.reader->GetCurrentPos();
- try {
- const Field& f = (*this)[name];
- const Structure& s = db.dna[f.type];
-
- // is the input actually an array?
- if (!(f.flags & FieldFlag_Array)) {
- throw Error((Formatter::format(),"Field `",name,"` of structure `",
- this->name,"` ought to be an array of size ",M
- ));
- }
-
- db.reader->IncPtr(f.offset);
-
- // size conversions are always allowed, regardless of error_policy
- unsigned int i = 0;
- for(; i < std::min(f.array_sizes[0],M); ++i) {
- s.Convert(out[i],db);
- }
- for(; i < M; ++i) {
- _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
- }
- }
- catch (const Error& e) {
- _defaultInitializer<error_policy>()(out,e.what());
- }
-
- // and recover the previous stream position
- db.reader->SetCurrentPos(old);
+ const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+ try {
+ const Field& f = (*this)[name];
+ const Structure& s = db.dna[f.type];
+
+ // is the input actually an array?
+ if (!(f.flags & FieldFlag_Array)) {
+ throw Error((Formatter::format(),"Field `",name,"` of structure `",
+ this->name,"` ought to be an array of size ",M
+ ));
+ }
+
+ db.reader->IncPtr(f.offset);
+
+ // size conversions are always allowed, regardless of error_policy
+ unsigned int i = 0;
+ for(; i < std::min(f.array_sizes[0],M); ++i) {
+ s.Convert(out[i],db);
+ }
+ for(; i < M; ++i) {
+ _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
+ }
+ }
+ catch (const Error& e) {
+ _defaultInitializer<error_policy>()(out,e.what());
+ }
+
+ // and recover the previous stream position
+ db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().fields_read;
+ ++db.stats().fields_read;
#endif
}
@@ -137,393 +139,393 @@ void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatab
template <int error_policy, typename T, size_t M, size_t N>
void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileDatabase& db) const
{
- const StreamReaderAny::pos old = db.reader->GetCurrentPos();
- try {
- const Field& f = (*this)[name];
- const Structure& s = db.dna[f.type];
-
- // is the input actually an array?
- if (!(f.flags & FieldFlag_Array)) {
- throw Error((Formatter::format(),"Field `",name,"` of structure `",
- this->name,"` ought to be an array of size ",M,"*",N
- ));
- }
-
- db.reader->IncPtr(f.offset);
-
- // size conversions are always allowed, regardless of error_policy
- unsigned int i = 0;
- for(; i < std::min(f.array_sizes[0],M); ++i) {
- unsigned int j = 0;
- for(; j < std::min(f.array_sizes[1],N); ++j) {
- s.Convert(out[i][j],db);
- }
- for(; j < N; ++j) {
- _defaultInitializer<ErrorPolicy_Igno>()(out[i][j]);
- }
- }
- for(; i < M; ++i) {
- _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
- }
- }
- catch (const Error& e) {
- _defaultInitializer<error_policy>()(out,e.what());
- }
-
- // and recover the previous stream position
- db.reader->SetCurrentPos(old);
+ const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+ try {
+ const Field& f = (*this)[name];
+ const Structure& s = db.dna[f.type];
+
+ // is the input actually an array?
+ if (!(f.flags & FieldFlag_Array)) {
+ throw Error((Formatter::format(),"Field `",name,"` of structure `",
+ this->name,"` ought to be an array of size ",M,"*",N
+ ));
+ }
+
+ db.reader->IncPtr(f.offset);
+
+ // size conversions are always allowed, regardless of error_policy
+ unsigned int i = 0;
+ for(; i < std::min(f.array_sizes[0],M); ++i) {
+ unsigned int j = 0;
+ for(; j < std::min(f.array_sizes[1],N); ++j) {
+ s.Convert(out[i][j],db);
+ }
+ for(; j < N; ++j) {
+ _defaultInitializer<ErrorPolicy_Igno>()(out[i][j]);
+ }
+ }
+ for(; i < M; ++i) {
+ _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
+ }
+ }
+ catch (const Error& e) {
+ _defaultInitializer<error_policy>()(out,e.what());
+ }
+
+ // and recover the previous stream position
+ db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().fields_read;
+ ++db.stats().fields_read;
#endif
}
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T>
bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
- bool non_recursive /*= false*/) const
+ bool non_recursive /*= false*/) const
{
- const StreamReaderAny::pos old = db.reader->GetCurrentPos();
- Pointer ptrval;
- const Field* f;
- try {
- f = &(*this)[name];
-
- // sanity check, should never happen if the genblenddna script is right
- if (!(f->flags & FieldFlag_Pointer)) {
- throw Error((Formatter::format(),"Field `",name,"` of structure `",
- this->name,"` ought to be a pointer"));
- }
-
- db.reader->IncPtr(f->offset);
- Convert(ptrval,db);
- // actually it is meaningless on which Structure the Convert is called
- // because the `Pointer` argument triggers a special implementation.
- }
- catch (const Error& e) {
- _defaultInitializer<error_policy>()(out,e.what());
-
- out.reset();
- return false;
- }
-
- // resolve the pointer and load the corresponding structure
- const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
-
- if(!non_recursive) {
- // and recover the previous stream position
- db.reader->SetCurrentPos(old);
- }
+ const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+ Pointer ptrval;
+ const Field* f;
+ try {
+ f = &(*this)[name];
+
+ // sanity check, should never happen if the genblenddna script is right
+ if (!(f->flags & FieldFlag_Pointer)) {
+ throw Error((Formatter::format(),"Field `",name,"` of structure `",
+ this->name,"` ought to be a pointer"));
+ }
+
+ db.reader->IncPtr(f->offset);
+ Convert(ptrval,db);
+ // actually it is meaningless on which Structure the Convert is called
+ // because the `Pointer` argument triggers a special implementation.
+ }
+ catch (const Error& e) {
+ _defaultInitializer<error_policy>()(out,e.what());
+
+ out.reset();
+ return false;
+ }
+
+ // resolve the pointer and load the corresponding structure
+ const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
+
+ if(!non_recursive) {
+ // and recover the previous stream position
+ db.reader->SetCurrentPos(old);
+ }
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().fields_read;
+ ++db.stats().fields_read;
#endif
- return res;
+ return res;
}
//--------------------------------------------------------------------------------
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
-bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
- const FileDatabase& db) const
+bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
+ const FileDatabase& db) const
{
- // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
- const StreamReaderAny::pos old = db.reader->GetCurrentPos();
- Pointer ptrval[N];
- const Field* f;
- try {
- f = &(*this)[name];
-
- // sanity check, should never happen if the genblenddna script is right
- if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
- throw Error((Formatter::format(),"Field `",name,"` of structure `",
- this->name,"` ought to be a pointer AND an array"));
- }
-
- db.reader->IncPtr(f->offset);
-
- size_t i = 0;
- for(; i < std::min(f->array_sizes[0],N); ++i) {
- Convert(ptrval[i],db);
- }
- for(; i < N; ++i) {
- _defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
- }
-
- // actually it is meaningless on which Structure the Convert is called
- // because the `Pointer` argument triggers a special implementation.
- }
- catch (const Error& e) {
- _defaultInitializer<error_policy>()(out,e.what());
- for(size_t i = 0; i < N; ++i) {
- out[i].reset();
- }
- return false;
- }
-
- bool res = true;
- for(size_t i = 0; i < N; ++i) {
- // resolve the pointer and load the corresponding structure
- res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
- }
-
- // and recover the previous stream position
- db.reader->SetCurrentPos(old);
+ // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
+ const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+ Pointer ptrval[N];
+ const Field* f;
+ try {
+ f = &(*this)[name];
+
+ // sanity check, should never happen if the genblenddna script is right
+ if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
+ throw Error((Formatter::format(),"Field `",name,"` of structure `",
+ this->name,"` ought to be a pointer AND an array"));
+ }
+
+ db.reader->IncPtr(f->offset);
+
+ size_t i = 0;
+ for(; i < std::min(f->array_sizes[0],N); ++i) {
+ Convert(ptrval[i],db);
+ }
+ for(; i < N; ++i) {
+ _defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
+ }
+
+ // actually it is meaningless on which Structure the Convert is called
+ // because the `Pointer` argument triggers a special implementation.
+ }
+ catch (const Error& e) {
+ _defaultInitializer<error_policy>()(out,e.what());
+ for(size_t i = 0; i < N; ++i) {
+ out[i].reset();
+ }
+ return false;
+ }
+
+ bool res = true;
+ for(size_t i = 0; i < N; ++i) {
+ // resolve the pointer and load the corresponding structure
+ res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
+ }
+
+ // and recover the previous stream position
+ db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().fields_read;
+ ++db.stats().fields_read;
#endif
- return res;
+ return res;
}
//--------------------------------------------------------------------------------
template <int error_policy, typename T>
void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) const
{
- const StreamReaderAny::pos old = db.reader->GetCurrentPos();
- try {
- const Field& f = (*this)[name];
- // find the structure definition pertaining to this field
- const Structure& s = db.dna[f.type];
-
- db.reader->IncPtr(f.offset);
- s.Convert(out,db);
- }
- catch (const Error& e) {
- _defaultInitializer<error_policy>()(out,e.what());
- }
-
- // and recover the previous stream position
- db.reader->SetCurrentPos(old);
+ const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+ try {
+ const Field& f = (*this)[name];
+ // find the structure definition pertaining to this field
+ const Structure& s = db.dna[f.type];
+
+ db.reader->IncPtr(f.offset);
+ s.Convert(out,db);
+ }
+ catch (const Error& e) {
+ _defaultInitializer<error_policy>()(out,e.what());
+ }
+
+ // and recover the previous stream position
+ db.reader->SetCurrentPos(old);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().fields_read;
+ ++db.stats().fields_read;
#endif
}
//--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T>
-bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
- const Field& f,
- bool non_recursive /*= false*/) const
+bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
+ const Field& f,
+ bool non_recursive /*= false*/) const
{
- out.reset(); // ensure null pointers work
- if (!ptrval.val) {
- return false;
- }
- const Structure& s = db.dna[f.type];
- // find the file block the pointer is pointing to
- const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
- // also determine the target type from the block header
- // and check if it matches the type which we expect.
- const Structure& ss = db.dna[block->dna_index];
- if (ss != s) {
- throw Error((Formatter::format(),"Expected target to be of type `",s.name,
- "` but seemingly it is a `",ss.name,"` instead"
- ));
- }
-
- // try to retrieve the object from the cache
- db.cache(out).get(s,out,ptrval);
- if (out) {
- return true;
- }
-
- // seek to this location, but save the previous stream pointer.
- const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
- db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
- // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
- // I really ought to improve StreamReader to work with 64 bit indices exclusively.
-
- // continue conversion after allocating the required storage
- size_t num = block->size / ss.size;
- T* o = _allocate(out,num);
-
- // cache the object before we convert it to avoid cyclic recursion.
- db.cache(out).set(s,out,ptrval);
-
- // if the non_recursive flag is set, we don't do anything but leave
- // the cursor at the correct position to resolve the object.
- if (!non_recursive) {
- for (size_t i = 0; i < num; ++i,++o) {
- s.Convert(*o,db);
- }
-
- db.reader->SetCurrentPos(pold);
- }
+ out.reset(); // ensure null pointers work
+ if (!ptrval.val) {
+ return false;
+ }
+ const Structure& s = db.dna[f.type];
+ // find the file block the pointer is pointing to
+ const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+ // also determine the target type from the block header
+ // and check if it matches the type which we expect.
+ const Structure& ss = db.dna[block->dna_index];
+ if (ss != s) {
+ throw Error((Formatter::format(),"Expected target to be of type `",s.name,
+ "` but seemingly it is a `",ss.name,"` instead"
+ ));
+ }
+
+ // try to retrieve the object from the cache
+ db.cache(out).get(s,out,ptrval);
+ if (out) {
+ return true;
+ }
+
+ // seek to this location, but save the previous stream pointer.
+ const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+ db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+ // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+ // I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+ // continue conversion after allocating the required storage
+ size_t num = block->size / ss.size;
+ T* o = _allocate(out,num);
+
+ // cache the object before we convert it to avoid cyclic recursion.
+ db.cache(out).set(s,out,ptrval);
+
+ // if the non_recursive flag is set, we don't do anything but leave
+ // the cursor at the correct position to resolve the object.
+ if (!non_recursive) {
+ for (size_t i = 0; i < num; ++i,++o) {
+ s.Convert(*o,db);
+ }
+
+ db.reader->SetCurrentPos(pold);
+ }
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- if(out) {
- ++db.stats().pointers_resolved;
- }
+ if(out) {
+ ++db.stats().pointers_resolved;
+ }
#endif
- return false;
+ return false;
}
//--------------------------------------------------------------------------------
-inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
- const FileDatabase& db,
- const Field&,
- bool) const
+inline bool Structure :: ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
+ const FileDatabase& db,
+ const Field&,
+ bool) const
{
- // Currently used exclusively by PackedFile::data to represent
- // a simple offset into the mapped BLEND file.
- out.reset();
- if (!ptrval.val) {
- return false;
- }
-
- // find the file block the pointer is pointing to
- const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
- out = boost::shared_ptr< FileOffset > (new FileOffset());
- out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
- return false;
+ // Currently used exclusively by PackedFile::data to represent
+ // a simple offset into the mapped BLEND file.
+ out.reset();
+ if (!ptrval.val) {
+ return false;
+ }
+
+ // find the file block the pointer is pointing to
+ const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+ out = std::shared_ptr< FileOffset > (new FileOffset());
+ out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
+ return false;
}
//--------------------------------------------------------------------------------
template <template <typename> class TOUT, typename T>
-bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
- const FileDatabase& db,
- const Field& f,
- bool) const
+bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
+ const FileDatabase& db,
+ const Field& f,
+ bool) const
{
- // This is a function overload, not a template specialization. According to
- // the partial ordering rules, it should be selected by the compiler
- // for array-of-pointer inputs, i.e. Object::mats.
-
- out.reset();
- if (!ptrval.val) {
- return false;
- }
-
- // find the file block the pointer is pointing to
- const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
- const size_t num = block->size / (db.i64bit?8:4);
-
- // keep the old stream position
- const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
- db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
-
- bool res = false;
- // allocate raw storage for the array
- out.resize(num);
- for (size_t i = 0; i< num; ++i) {
- Pointer val;
- Convert(val,db);
-
- // and resolve the pointees
- res = ResolvePointer(out[i],val,db,f) && res;
- }
-
- db.reader->SetCurrentPos(pold);
- return res;
+ // This is a function overload, not a template specialization. According to
+ // the partial ordering rules, it should be selected by the compiler
+ // for array-of-pointer inputs, i.e. Object::mats.
+
+ out.reset();
+ if (!ptrval.val) {
+ return false;
+ }
+
+ // find the file block the pointer is pointing to
+ const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+ const size_t num = block->size / (db.i64bit?8:4);
+
+ // keep the old stream position
+ const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+ db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+
+ bool res = false;
+ // allocate raw storage for the array
+ out.resize(num);
+ for (size_t i = 0; i< num; ++i) {
+ Pointer val;
+ Convert(val,db);
+
+ // and resolve the pointees
+ res = ResolvePointer(out[i],val,db,f) && res;
+ }
+
+ db.reader->SetCurrentPos(pold);
+ return res;
}
//--------------------------------------------------------------------------------
-template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
- const Pointer & ptrval,
- const FileDatabase& db,
- const Field&,
- bool
-) const
+template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
+ const Pointer & ptrval,
+ const FileDatabase& db,
+ const Field&,
+ bool
+) const
{
- // Special case when the data type needs to be determined at runtime.
- // Less secure than in the `strongly-typed` case.
-
- out.reset();
- if (!ptrval.val) {
- return false;
- }
-
- // find the file block the pointer is pointing to
- const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
- // determine the target type from the block header
- const Structure& s = db.dna[block->dna_index];
-
- // try to retrieve the object from the cache
- db.cache(out).get(s,out,ptrval);
- if (out) {
- return true;
- }
-
- // seek to this location, but save the previous stream pointer.
- const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
- db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
- // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
- // I really ought to improve StreamReader to work with 64 bit indices exclusively.
-
- // continue conversion after allocating the required storage
- DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db);
- if (!builders.first) {
- // this might happen if DNA::RegisterConverters hasn't been called so far
- // or if the target type is not contained in `our` DNA.
- out.reset();
- DefaultLogger::get()->warn((Formatter::format(),
- "Failed to find a converter for the `",s.name,"` structure"
- ));
- return false;
- }
-
- // allocate the object hull
- out = (s.*builders.first)();
-
- // cache the object immediately to prevent infinite recursion in a
- // circular list with a single element (i.e. a self-referencing element).
- db.cache(out).set(s,out,ptrval);
-
- // and do the actual conversion
- (s.*builders.second)(out,db);
- db.reader->SetCurrentPos(pold);
-
- // store a pointer to the name string of the actual type
- // in the object itself. This allows the conversion code
- // to perform additional type checking.
- out->dna_type = s.name.c_str();
+ // Special case when the data type needs to be determined at runtime.
+ // Less secure than in the `strongly-typed` case.
+
+ out.reset();
+ if (!ptrval.val) {
+ return false;
+ }
+
+ // find the file block the pointer is pointing to
+ const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+ // determine the target type from the block header
+ const Structure& s = db.dna[block->dna_index];
+
+ // try to retrieve the object from the cache
+ db.cache(out).get(s,out,ptrval);
+ if (out) {
+ return true;
+ }
+
+ // seek to this location, but save the previous stream pointer.
+ const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+ db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+ // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+ // I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+ // continue conversion after allocating the required storage
+ DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db);
+ if (!builders.first) {
+ // this might happen if DNA::RegisterConverters hasn't been called so far
+ // or if the target type is not contained in `our` DNA.
+ out.reset();
+ DefaultLogger::get()->warn((Formatter::format(),
+ "Failed to find a converter for the `",s.name,"` structure"
+ ));
+ return false;
+ }
+
+ // allocate the object hull
+ out = (s.*builders.first)();
+
+ // cache the object immediately to prevent infinite recursion in a
+ // circular list with a single element (i.e. a self-referencing element).
+ db.cache(out).set(s,out,ptrval);
+
+ // and do the actual conversion
+ (s.*builders.second)(out,db);
+ db.reader->SetCurrentPos(pold);
+
+ // store a pointer to the name string of the actual type
+ // in the object itself. This allows the conversion code
+ // to perform additional type checking.
+ out->dna_type = s.name.c_str();
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().pointers_resolved;
+ ++db.stats().pointers_resolved;
#endif
- return false;
+ return false;
}
//--------------------------------------------------------------------------------
-const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const
+const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const
{
- // the file blocks appear in list sorted by
- // with ascending base addresses so we can run a
- // binary search to locate the pointee quickly.
-
- // NOTE: Blender seems to distinguish between side-by-side
- // data (stored in the same data block) and far pointers,
- // which are only used for structures starting with an ID.
- // We don't need to make this distinction, our algorithm
- // works regardless where the data is stored.
- vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval);
- if (it == db.entries.end()) {
- // this is crucial, pointers may not be invalid.
- // this is either a corrupted file or an attempted attack.
- throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
- std::hex,ptrval.val,", no file block falls into this address range"
- ));
- }
- if (ptrval.val >= (*it).address.val + (*it).size) {
- throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
- std::hex,ptrval.val,", nearest file block starting at 0x",
- (*it).address.val," ends at 0x",
- (*it).address.val + (*it).size
- ));
- }
- return &*it;
+ // the file blocks appear in list sorted by
+ // with ascending base addresses so we can run a
+ // binary search to locate the pointee quickly.
+
+ // NOTE: Blender seems to distinguish between side-by-side
+ // data (stored in the same data block) and far pointers,
+ // which are only used for structures starting with an ID.
+ // We don't need to make this distinction, our algorithm
+ // works regardless where the data is stored.
+ vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval);
+ if (it == db.entries.end()) {
+ // this is crucial, pointers may not be invalid.
+ // this is either a corrupted file or an attempted attack.
+ throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
+ std::hex,ptrval.val,", no file block falls into this address range"
+ ));
+ }
+ if (ptrval.val >= (*it).address.val + (*it).size) {
+ throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
+ std::hex,ptrval.val,", nearest file block starting at 0x",
+ (*it).address.val," ends at 0x",
+ (*it).address.val + (*it).size
+ ));
+ }
+ return &*it;
}
// ------------------------------------------------------------------------------------------------
-// NOTE: The MSVC debugger keeps showing up this annoying `a cast to a smaller data type has
+// NOTE: The MSVC debugger keeps showing up this annoying `a cast to a smaller data type has
// caused a loss of data`-warning. Avoid this warning by a masking with an appropriate bitmask.
template <typename T> struct signless;
@@ -532,199 +534,199 @@ template <> struct signless<short> {typedef unsigned short type;};
template <> struct signless<int> {typedef unsigned int type;};
template <typename T>
-struct static_cast_silent {
- template <typename V>
- T operator()(V in) {
- return static_cast<T>(in & static_cast<typename signless<T>::type>(-1));
- }
+struct static_cast_silent {
+ template <typename V>
+ T operator()(V in) {
+ return static_cast<T>(in & static_cast<typename signless<T>::type>(-1));
+ }
};
template <> struct static_cast_silent<float> {
- template <typename V> float operator()(V in) {
- return static_cast<float> (in);
- }
+ template <typename V> float operator()(V in) {
+ return static_cast<float> (in);
+ }
};
template <> struct static_cast_silent<double> {
- template <typename V> double operator()(V in) {
- return static_cast<double>(in);
- }
+ template <typename V> double operator()(V in) {
+ return static_cast<double>(in);
+ }
};
// ------------------------------------------------------------------------------------------------
-template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db)
+template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db)
{
- if (in.name == "int") {
- out = static_cast_silent<T>()(db.reader->GetU4());
- }
- else if (in.name == "short") {
- out = static_cast_silent<T>()(db.reader->GetU2());
- }
- else if (in.name == "char") {
- out = static_cast_silent<T>()(db.reader->GetU1());
- }
- else if (in.name == "float") {
- out = static_cast<T>(db.reader->GetF4());
- }
- else if (in.name == "double") {
- out = static_cast<T>(db.reader->GetF8());
- }
- else {
- throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name);
- }
+ if (in.name == "int") {
+ out = static_cast_silent<T>()(db.reader->GetU4());
+ }
+ else if (in.name == "short") {
+ out = static_cast_silent<T>()(db.reader->GetU2());
+ }
+ else if (in.name == "char") {
+ out = static_cast_silent<T>()(db.reader->GetU1());
+ }
+ else if (in.name == "float") {
+ out = static_cast<T>(db.reader->GetF4());
+ }
+ else if (in.name == "double") {
+ out = static_cast<T>(db.reader->GetF8());
+ }
+ else {
+ throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name);
+ }
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const
{
- ConvertDispatcher(dest,*this,db);
+ ConvertDispatcher(dest,*this,db);
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const
{
- // automatic rescaling from short to float and vice versa (seems to be used by normals)
- if (name == "float") {
- dest = static_cast<short>(db.reader->GetF4() * 32767.f);
- //db.reader->IncPtr(-4);
- return;
- }
- else if (name == "double") {
- dest = static_cast<short>(db.reader->GetF8() * 32767.);
- //db.reader->IncPtr(-8);
- return;
- }
- ConvertDispatcher(dest,*this,db);
+ // automatic rescaling from short to float and vice versa (seems to be used by normals)
+ if (name == "float") {
+ dest = static_cast<short>(db.reader->GetF4() * 32767.f);
+ //db.reader->IncPtr(-4);
+ return;
+ }
+ else if (name == "double") {
+ dest = static_cast<short>(db.reader->GetF8() * 32767.);
+ //db.reader->IncPtr(-8);
+ return;
+ }
+ ConvertDispatcher(dest,*this,db);
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const
{
- // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
- if (name == "float") {
- dest = static_cast<char>(db.reader->GetF4() * 255.f);
- return;
- }
- else if (name == "double") {
- dest = static_cast<char>(db.reader->GetF8() * 255.f);
- return;
- }
- ConvertDispatcher(dest,*this,db);
+ // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
+ if (name == "float") {
+ dest = static_cast<char>(db.reader->GetF4() * 255.f);
+ return;
+ }
+ else if (name == "double") {
+ dest = static_cast<char>(db.reader->GetF8() * 255.f);
+ return;
+ }
+ ConvertDispatcher(dest,*this,db);
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const
{
- // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
- if (name == "char") {
- dest = db.reader->GetI1() / 255.f;
- return;
- }
- // automatic rescaling from short to float and vice versa (used by normals)
- else if (name == "short") {
- dest = db.reader->GetI2() / 32767.f;
- return;
- }
- ConvertDispatcher(dest,*this,db);
+ // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
+ if (name == "char") {
+ dest = db.reader->GetI1() / 255.f;
+ return;
+ }
+ // automatic rescaling from short to float and vice versa (used by normals)
+ else if (name == "short") {
+ dest = db.reader->GetI2() / 32767.f;
+ return;
+ }
+ ConvertDispatcher(dest,*this,db);
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const
{
- if (name == "char") {
- dest = db.reader->GetI1() / 255.;
- return;
- }
- else if (name == "short") {
- dest = db.reader->GetI2() / 32767.;
- return;
- }
- ConvertDispatcher(dest,*this,db);
+ if (name == "char") {
+ dest = db.reader->GetI1() / 255.;
+ return;
+ }
+ else if (name == "short") {
+ dest = db.reader->GetI2() / 32767.;
+ return;
+ }
+ ConvertDispatcher(dest,*this,db);
}
// ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const
{
- if (db.i64bit) {
- dest.val = db.reader->GetU8();
- //db.reader->IncPtr(-8);
- return;
- }
- dest.val = db.reader->GetU4();
- //db.reader->IncPtr(-4);
+ if (db.i64bit) {
+ dest.val = db.reader->GetU8();
+ //db.reader->IncPtr(-8);
+ return;
+ }
+ dest.val = db.reader->GetU4();
+ //db.reader->IncPtr(-4);
}
//--------------------------------------------------------------------------------
const Structure& DNA :: operator [] (const std::string& ss) const
{
- std::map<std::string, size_t>::const_iterator it = indices.find(ss);
- if (it == indices.end()) {
- throw Error((Formatter::format(),
- "BlendDNA: Did not find a structure named `",ss,"`"
- ));
- }
-
- return structures[(*it).second];
+ std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+ if (it == indices.end()) {
+ throw Error((Formatter::format(),
+ "BlendDNA: Did not find a structure named `",ss,"`"
+ ));
+ }
+
+ return structures[(*it).second];
}
//--------------------------------------------------------------------------------
const Structure* DNA :: Get (const std::string& ss) const
{
- std::map<std::string, size_t>::const_iterator it = indices.find(ss);
- return it == indices.end() ? NULL : &structures[(*it).second];
+ std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+ return it == indices.end() ? NULL : &structures[(*it).second];
}
//--------------------------------------------------------------------------------
-const Structure& DNA :: operator [] (const size_t i) const
+const Structure& DNA :: operator [] (const size_t i) const
{
- if (i >= structures.size()) {
- throw Error((Formatter::format(),
- "BlendDNA: There is no structure with index `",i,"`"
- ));
- }
+ if (i >= structures.size()) {
+ throw Error((Formatter::format(),
+ "BlendDNA: There is no structure with index `",i,"`"
+ ));
+ }
- return structures[i];
+ return structures[i];
}
//--------------------------------------------------------------------------------
template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: get (
- const Structure& s,
- TOUT<T>& out,
- const Pointer& ptr
+ const Structure& s,
+ TOUT<T>& out,
+ const Pointer& ptr
) const {
- if(s.cache_idx == static_cast<size_t>(-1)) {
- s.cache_idx = db.next_cache_idx++;
- caches.resize(db.next_cache_idx);
- return;
- }
+ if(s.cache_idx == static_cast<size_t>(-1)) {
+ s.cache_idx = db.next_cache_idx++;
+ caches.resize(db.next_cache_idx);
+ return;
+ }
- typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
- if (it != caches[s.cache_idx].end()) {
- out = boost::static_pointer_cast<T>( (*it).second );
+ typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
+ if (it != caches[s.cache_idx].end()) {
+ out = std::static_pointer_cast<T>( (*it).second );
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().cache_hits;
+ ++db.stats().cache_hits;
#endif
- }
- // otherwise, out remains untouched
+ }
+ // otherwise, out remains untouched
}
//--------------------------------------------------------------------------------
template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: set (
- const Structure& s,
- const TOUT<T>& out,
- const Pointer& ptr
+ const Structure& s,
+ const TOUT<T>& out,
+ const Pointer& ptr
) {
- if(s.cache_idx == static_cast<size_t>(-1)) {
- s.cache_idx = db.next_cache_idx++;
- caches.resize(db.next_cache_idx);
- }
- caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out );
+ if(s.cache_idx == static_cast<size_t>(-1)) {
+ s.cache_idx = db.next_cache_idx++;
+ caches.resize(db.next_cache_idx);
+ }
+ caches[s.cache_idx][ptr] = std::static_pointer_cast<ElemBase>( out );
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- ++db.stats().cached_objects;
+ ++db.stats().cached_objects;
#endif
}
diff --git a/src/3rdparty/assimp/code/BlenderIntermediate.h b/src/3rdparty/assimp/code/BlenderIntermediate.h
index d2a179b31..e9aebf4bb 100644
--- a/src/3rdparty/assimp/code/BlenderIntermediate.h
+++ b/src/3rdparty/assimp/code/BlenderIntermediate.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,132 +49,150 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h"
#include "BlenderScene.h"
#include "BlenderSceneGen.h"
+#include <deque>
+#include "./../include/assimp/material.h"
-#define for_each(x,y) BOOST_FOREACH(x,y)
+struct aiTexture;
namespace Assimp {
namespace Blender {
- // --------------------------------------------------------------------
- /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
- // --------------------------------------------------------------------
- template <template <typename,typename> class TCLASS, typename T>
- struct TempArray {
- typedef TCLASS< T*,std::allocator<T*> > mywrap;
-
- TempArray() {
- }
-
- ~TempArray () {
- for_each(T* elem, arr) {
- delete elem;
- }
- }
-
- void dismiss() {
- arr.clear();
- }
-
- mywrap* operator -> () {
- return &arr;
- }
-
- operator mywrap& () {
- return arr;
- }
-
- operator const mywrap& () const {
- return arr;
- }
-
- mywrap& get () {
- return arr;
- }
-
- const mywrap& get () const {
- return arr;
- }
-
- T* operator[] (size_t idx) const {
- return arr[idx];
- }
-
- T*& operator[] (size_t idx) {
- return arr[idx];
- }
-
- private:
- // no copy semantics
- void operator= (const TempArray&) {
- }
-
- TempArray(const TempArray& arr) {
- }
-
- private:
- mywrap arr;
- };
-
+ // --------------------------------------------------------------------
+ /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
+ // --------------------------------------------------------------------
+ template <template <typename,typename> class TCLASS, typename T>
+ struct TempArray {
+ typedef TCLASS< T*,std::allocator<T*> > mywrap;
+
+ TempArray() {
+ }
+
+ ~TempArray () {
+ for(T* elem : arr) {
+ delete elem;
+ }
+ }
+
+ void dismiss() {
+ arr.clear();
+ }
+
+ mywrap* operator -> () {
+ return &arr;
+ }
+
+ operator mywrap& () {
+ return arr;
+ }
+
+ operator const mywrap& () const {
+ return arr;
+ }
+
+ mywrap& get () {
+ return arr;
+ }
+
+ const mywrap& get () const {
+ return arr;
+ }
+
+ T* operator[] (size_t idx) const {
+ return arr[idx];
+ }
+
+ T*& operator[] (size_t idx) {
+ return arr[idx];
+ }
+
+ private:
+ // no copy semantics
+ void operator= (const TempArray&) {
+ }
+
+ TempArray(const TempArray& arr) {
+ }
+
+ private:
+ mywrap arr;
+ };
+
#ifdef _MSC_VER
-# pragma warning(disable:4351)
+# pragma warning(disable:4351)
#endif
- // --------------------------------------------------------------------
- /** ConversionData acts as intermediate storage location for
- * the various ConvertXXX routines in BlenderImporter.*/
- // --------------------------------------------------------------------
- struct ConversionData
- {
- ConversionData(const FileDatabase& db)
- : sentinel_cnt()
- , next_texture()
- , db(db)
- {}
-
- std::set<const Object*> objects;
-
- TempArray <std::vector, aiMesh> meshes;
- TempArray <std::vector, aiCamera> cameras;
- TempArray <std::vector, aiLight> lights;
- TempArray <std::vector, aiMaterial> materials;
- TempArray <std::vector, aiTexture> textures;
-
- // set of all materials referenced by at least one mesh in the scene
- std::deque< boost::shared_ptr< Material > > materials_raw;
-
- // counter to name sentinel textures inserted as substitutes for procedural textures.
- unsigned int sentinel_cnt;
-
- // next texture ID for each texture type, respectively
- unsigned int next_texture[aiTextureType_UNKNOWN+1];
-
- // original file data
- const FileDatabase& db;
- };
+
+ struct ObjectCompare {
+ bool operator() (const Object* left, const Object* right) const {
+ return strcmp(left->id.name, right->id.name) == -1;
+ }
+ };
+
+ // When keeping objects in sets, sort them by their name.
+ typedef std::set<const Object*, ObjectCompare> ObjectSet;
+
+ // --------------------------------------------------------------------
+ /** ConversionData acts as intermediate storage location for
+ * the various ConvertXXX routines in BlenderImporter.*/
+ // --------------------------------------------------------------------
+ struct ConversionData
+ {
+ ConversionData(const FileDatabase& db)
+ : sentinel_cnt()
+ , next_texture()
+ , db(db)
+ {}
+
+ struct ObjectCompare {
+ bool operator() (const Object* left, const Object* right) const {
+ return strcmp(left->id.name, right->id.name) == -1;
+ }
+ };
+
+ ObjectSet objects;
+
+ TempArray <std::vector, aiMesh> meshes;
+ TempArray <std::vector, aiCamera> cameras;
+ TempArray <std::vector, aiLight> lights;
+ TempArray <std::vector, aiMaterial> materials;
+ TempArray <std::vector, aiTexture> textures;
+
+ // set of all materials referenced by at least one mesh in the scene
+ std::deque< std::shared_ptr< Material > > materials_raw;
+
+ // counter to name sentinel textures inserted as substitutes for procedural textures.
+ unsigned int sentinel_cnt;
+
+ // next texture ID for each texture type, respectively
+ unsigned int next_texture[aiTextureType_UNKNOWN+1];
+
+ // original file data
+ const FileDatabase& db;
+ };
#ifdef _MSC_VER
-# pragma warning(default:4351)
+# pragma warning(default:4351)
#endif
// ------------------------------------------------------------------------------------------------
inline const char* GetTextureTypeDisplayString(Tex::Type t)
{
- switch (t) {
- case Tex::Type_CLOUDS : return "Clouds";
- case Tex::Type_WOOD : return "Wood";
- case Tex::Type_MARBLE : return "Marble";
- case Tex::Type_MAGIC : return "Magic";
- case Tex::Type_BLEND : return "Blend";
- case Tex::Type_STUCCI : return "Stucci";
- case Tex::Type_NOISE : return "Noise";
- case Tex::Type_PLUGIN : return "Plugin";
- case Tex::Type_MUSGRAVE : return "Musgrave";
- case Tex::Type_VORONOI : return "Voronoi";
- case Tex::Type_DISTNOISE : return "DistortedNoise";
- case Tex::Type_ENVMAP : return "EnvMap";
- case Tex::Type_IMAGE : return "Image";
- default:
- break;
- }
- return "<Unknown>";
+ switch (t) {
+ case Tex::Type_CLOUDS : return "Clouds";
+ case Tex::Type_WOOD : return "Wood";
+ case Tex::Type_MARBLE : return "Marble";
+ case Tex::Type_MAGIC : return "Magic";
+ case Tex::Type_BLEND : return "Blend";
+ case Tex::Type_STUCCI : return "Stucci";
+ case Tex::Type_NOISE : return "Noise";
+ case Tex::Type_PLUGIN : return "Plugin";
+ case Tex::Type_MUSGRAVE : return "Musgrave";
+ case Tex::Type_VORONOI : return "Voronoi";
+ case Tex::Type_DISTNOISE : return "DistortedNoise";
+ case Tex::Type_ENVMAP : return "EnvMap";
+ case Tex::Type_IMAGE : return "Image";
+ default:
+ break;
+ }
+ return "<Unknown>";
}
} // ! Blender
diff --git a/src/3rdparty/assimp/code/BlenderLoader.cpp b/src/3rdparty/assimp/code/BlenderLoader.cpp
index 8f9b85b26..5bc358716 100644
--- a/src/3rdparty/assimp/code/BlenderLoader.cpp
+++ b/src/3rdparty/assimp/code/BlenderLoader.cpp
@@ -3,11 +3,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -24,16 +24,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderLoader.cpp
* @brief Implementation of the Blender3D importer class.
*/
-#include "AssimpPCH.h"
+
//#define ASSIMP_BUILD_NO_COMPRESSED_BLEND
// Uncomment this to disable support for (gzip)compressed .BLEND files
@@ -52,21 +52,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h"
#include "BlenderModifier.h"
#include "BlenderBMesh.h"
+#include "StringUtils.h"
+#include <assimp/scene.h>
+#include "StringComparison.h"
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
+#include <cctype>
+
-// zlib is needed for compressed blend files
+// zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
-# else
-# include "../contrib/zlib/zlib.h"
-# endif
+# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+# else
+# include "../contrib/zlib/zlib.h"
+# endif
#endif
namespace Assimp {
- template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
+ template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
}
using namespace Assimp;
@@ -74,16 +79,16 @@ using namespace Assimp::Blender;
using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = {
- "Blender 3D Importer \nhttp://www.blender3d.org",
- "",
- "",
- "No animation support yet",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 2,
- 50,
- "blend"
+ "Blender 3D Importer \nhttp://www.blender3d.org",
+ "",
+ "",
+ "No animation support yet",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 2,
+ 50,
+ "blend"
};
@@ -94,1055 +99,1208 @@ BlenderImporter::BlenderImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
BlenderImporter::~BlenderImporter()
{
- delete modifier_cache;
+ delete modifier_cache;
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string& extension = GetExtension(pFile);
- if (extension == "blend") {
- return true;
- }
-
- else if ((!extension.length() || checkSig) && pIOHandler) {
- // note: this won't catch compressed files
- const char* tokens[] = {"BLENDER"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string& extension = GetExtension(pFile);
+ if (extension == "blend") {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ // note: this won't catch compressed files
+ const char* tokens[] = {"BLENDER"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
-void BlenderImporter::GetExtensionList(std::set<std::string>& app)
+void BlenderImporter::GetExtensionList(std::set<std::string>& app)
{
- app.insert("blend");
+ app.insert("blend");
}
// ------------------------------------------------------------------------------------------------
// Loader registry entry
const aiImporterDesc* BlenderImporter::GetInfo () const
{
- return &blenderDesc;
+ return &blenderDesc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void BlenderImporter::SetupProperties(const Importer* /*pImp*/)
{
- // nothing to be done for the moment
+ // nothing to be done for the moment
}
struct free_it
{
- free_it(void* free) : free(free) {}
- ~free_it() {
- ::free(this->free);
- }
+ free_it(void* free) : free(free) {}
+ ~free_it() {
+ ::free(this->free);
+ }
- void* free;
+ void* free;
};
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void BlenderImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void BlenderImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
- Bytef* dest = NULL;
- free_it free_it_really(dest);
+ Bytef* dest = NULL;
+ free_it free_it_really(dest);
#endif
- FileDatabase file;
- boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
- if (!stream) {
- ThrowException("Could not open file for reading");
- }
-
- char magic[8] = {0};
- stream->Read(magic,7,1);
- if (strcmp(magic,"BLENDER")) {
- // Check for presence of the gzip header. If yes, assume it is a
- // compressed blend file and try uncompressing it, else fail. This is to
- // avoid uncompressing random files which our loader might end up with.
+ FileDatabase file;
+ std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
+ if (!stream) {
+ ThrowException("Could not open file for reading");
+ }
+
+ char magic[8] = {0};
+ stream->Read(magic,7,1);
+ if (strcmp(magic,"BLENDER")) {
+ // Check for presence of the gzip header. If yes, assume it is a
+ // compressed blend file and try uncompressing it, else fail. This is to
+ // avoid uncompressing random files which our loader might end up with.
#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
- ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
+ ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
#else
- if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
- ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
- }
+ if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
+ ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
+ }
- LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
- if (magic[2] != 8) {
- ThrowException("Unsupported GZIP compression method");
- }
+ LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
+ if (magic[2] != 8) {
+ ThrowException("Unsupported GZIP compression method");
+ }
- // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
- stream->Seek(0L,aiOrigin_SET);
- boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
+ // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
+ stream->Seek(0L,aiOrigin_SET);
+ std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
- // build a zlib stream
- z_stream zstream;
- zstream.opaque = Z_NULL;
- zstream.zalloc = Z_NULL;
- zstream.zfree = Z_NULL;
- zstream.data_type = Z_BINARY;
+ // build a zlib stream
+ 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
- inflateInit2(&zstream, 16+MAX_WBITS);
+ // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
+ inflateInit2(&zstream, 16+MAX_WBITS);
- zstream.next_in = reinterpret_cast<Bytef*>( reader->GetPtr() );
- zstream.avail_in = reader->GetRemainingSize();
+ zstream.next_in = reinterpret_cast<Bytef*>( reader->GetPtr() );
+ zstream.avail_in = reader->GetRemainingSize();
- size_t total = 0l;
+ size_t total = 0l;
- // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
+ // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
#define MYBLOCK 1024
- Bytef block[MYBLOCK];
- int ret;
- do {
- zstream.avail_out = MYBLOCK;
- zstream.next_out = block;
- ret = inflate(&zstream, Z_NO_FLUSH);
-
- if (ret != Z_STREAM_END && ret != Z_OK) {
- ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
- }
- const size_t have = MYBLOCK - zstream.avail_out;
- total += have;
- dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
- memcpy(dest + total - have,block,have);
- }
- while (ret != Z_STREAM_END);
-
- // terminate zlib
- inflateEnd(&zstream);
-
- // replace the input stream with a memory stream
- stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
-
- // .. and retry
- stream->Read(magic,7,1);
- if (strcmp(magic,"BLENDER")) {
- ThrowException("Found no BLENDER magic word in decompressed GZIP file");
- }
+ Bytef block[MYBLOCK];
+ int ret;
+ do {
+ zstream.avail_out = MYBLOCK;
+ zstream.next_out = block;
+ ret = inflate(&zstream, Z_NO_FLUSH);
+
+ if (ret != Z_STREAM_END && ret != Z_OK) {
+ ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
+ }
+ const size_t have = MYBLOCK - zstream.avail_out;
+ total += have;
+ dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
+ memcpy(dest + total - have,block,have);
+ }
+ while (ret != Z_STREAM_END);
+
+ // terminate zlib
+ inflateEnd(&zstream);
+
+ // replace the input stream with a memory stream
+ stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
+
+ // .. and retry
+ stream->Read(magic,7,1);
+ if (strcmp(magic,"BLENDER")) {
+ ThrowException("Found no BLENDER magic word in decompressed GZIP file");
+ }
#endif
- }
+ }
- file.i64bit = (stream->Read(magic,1,1),magic[0]=='-');
- file.little = (stream->Read(magic,1,1),magic[0]=='v');
+ file.i64bit = (stream->Read(magic,1,1),magic[0]=='-');
+ file.little = (stream->Read(magic,1,1),magic[0]=='v');
- stream->Read(magic,3,1);
- magic[3] = '\0';
+ stream->Read(magic,3,1);
+ magic[3] = '\0';
- LogInfo((format(),"Blender version is ",magic[0],".",magic+1,
- " (64bit: ",file.i64bit?"true":"false",
- ", little endian: ",file.little?"true":"false",")"
- ));
+ LogInfo((format(),"Blender version is ",magic[0],".",magic+1,
+ " (64bit: ",file.i64bit?"true":"false",
+ ", little endian: ",file.little?"true":"false",")"
+ ));
- ParseBlendFile(file,stream);
+ ParseBlendFile(file,stream);
- Scene scene;
- ExtractScene(scene,file);
+ Scene scene;
+ ExtractScene(scene,file);
- ConvertBlendFile(pScene,scene,file);
+ ConvertBlendFile(pScene,scene,file);
}
// ------------------------------------------------------------------------------------------------
-void BlenderImporter::ParseBlendFile(FileDatabase& out, boost::shared_ptr<IOStream> stream)
+void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr<IOStream> stream)
{
- out.reader = boost::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little));
-
- DNAParser dna_reader(out);
- const DNA* dna = NULL;
-
- out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks
- SectionParser parser(*out.reader.get(),out.i64bit);
-
- // first parse the file in search for the DNA and insert all other sections into the database
- while ((parser.Next(),1)) {
- const FileBlockHead& head = parser.GetCurrent();
-
- if (head.id == "ENDB") {
- break; // only valid end of the file
- }
- else if (head.id == "DNA1") {
- dna_reader.Parse();
- dna = &dna_reader.GetDNA();
- continue;
- }
-
- out.entries.push_back(head);
- }
- }
- if (!dna) {
- ThrowException("SDNA not found");
- }
-
- std::sort(out.entries.begin(),out.entries.end());
+ out.reader = std::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little));
+
+ DNAParser dna_reader(out);
+ const DNA* dna = NULL;
+
+ out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks
+ SectionParser parser(*out.reader.get(),out.i64bit);
+
+ // first parse the file in search for the DNA and insert all other sections into the database
+ while ((parser.Next(),1)) {
+ const FileBlockHead& head = parser.GetCurrent();
+
+ if (head.id == "ENDB") {
+ break; // only valid end of the file
+ }
+ else if (head.id == "DNA1") {
+ dna_reader.Parse();
+ dna = &dna_reader.GetDNA();
+ continue;
+ }
+
+ out.entries.push_back(head);
+ }
+ }
+ if (!dna) {
+ ThrowException("SDNA not found");
+ }
+
+ std::sort(out.entries.begin(),out.entries.end());
}
// ------------------------------------------------------------------------------------------------
-void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
+void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
{
- const FileBlockHead* block = NULL;
- std::map<std::string,size_t>::const_iterator it = file.dna.indices.find("Scene");
- if (it == file.dna.indices.end()) {
- ThrowException("There is no `Scene` structure record");
- }
+ const FileBlockHead* block = NULL;
+ std::map<std::string,size_t>::const_iterator it = file.dna.indices.find("Scene");
+ if (it == file.dna.indices.end()) {
+ ThrowException("There is no `Scene` structure record");
+ }
- const Structure& ss = file.dna.structures[(*it).second];
+ const Structure& ss = file.dna.structures[(*it).second];
- // we need a scene somewhere to start with.
- for_each(const FileBlockHead& bl,file.entries) {
+ // we need a scene somewhere to start with.
+ for(const FileBlockHead& bl :file.entries) {
- // Fix: using the DNA index is more reliable to locate scenes
- //if (bl.id == "SC") {
+ // Fix: using the DNA index is more reliable to locate scenes
+ //if (bl.id == "SC") {
- if (bl.dna_index == (*it).second) {
- block = &bl;
- break;
- }
- }
+ if (bl.dna_index == (*it).second) {
+ block = &bl;
+ break;
+ }
+ }
- if (!block) {
- ThrowException("There is not a single `Scene` record to load");
- }
+ if (!block) {
+ ThrowException("There is not a single `Scene` record to load");
+ }
- file.reader->SetCurrentPos(block->start);
- ss.Convert(out,file);
+ file.reader->SetCurrentPos(block->start);
+ ss.Convert(out,file);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
- DefaultLogger::get()->info((format(),
- "(Stats) Fields read: " ,file.stats().fields_read,
- ", pointers resolved: " ,file.stats().pointers_resolved,
- ", cache hits: " ,file.stats().cache_hits,
- ", cached objects: " ,file.stats().cached_objects
- ));
+ DefaultLogger::get()->info((format(),
+ "(Stats) Fields read: " ,file.stats().fields_read,
+ ", pointers resolved: " ,file.stats().pointers_resolved,
+ ", cache hits: " ,file.stats().cache_hits,
+ ", cached objects: " ,file.stats().cached_objects
+ ));
#endif
}
// ------------------------------------------------------------------------------------------------
-void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file)
+void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file)
{
- ConversionData conv(file);
-
- // FIXME it must be possible to take the hierarchy directly from
- // the file. This is terrible. Here, we're first looking for
- // all objects which don't have parent objects at all -
- std::deque<const Object*> no_parents;
- for (boost::shared_ptr<Base> cur = boost::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) {
- if (cur->object) {
- if(!cur->object->parent) {
- no_parents.push_back(cur->object.get());
- }
- else conv.objects.insert(cur->object.get());
- }
- }
- for (boost::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
- if (cur->object) {
- if(cur->object->parent) {
- conv.objects.insert(cur->object.get());
- }
- }
- }
-
- if (no_parents.empty()) {
- ThrowException("Expected at least one object with no parent");
- }
-
- aiNode* root = out->mRootNode = new aiNode("<BlenderRoot>");
-
- root->mNumChildren = static_cast<unsigned int>(no_parents.size());
- root->mChildren = new aiNode*[root->mNumChildren]();
- for (unsigned int i = 0; i < root->mNumChildren; ++i) {
- root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());
- root->mChildren[i]->mParent = root;
- }
-
- BuildMaterials(conv);
-
- if (conv.meshes->size()) {
- out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast<unsigned int>( conv.meshes->size() )];
- std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes);
- conv.meshes.dismiss();
- }
-
- if (conv.lights->size()) {
- out->mLights = new aiLight*[out->mNumLights = static_cast<unsigned int>( conv.lights->size() )];
- std::copy(conv.lights->begin(),conv.lights->end(),out->mLights);
- conv.lights.dismiss();
- }
-
- if (conv.cameras->size()) {
- out->mCameras = new aiCamera*[out->mNumCameras = static_cast<unsigned int>( conv.cameras->size() )];
- std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras);
- conv.cameras.dismiss();
- }
-
- if (conv.materials->size()) {
- out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast<unsigned int>( conv.materials->size() )];
- std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials);
- conv.materials.dismiss();
- }
-
- if (conv.textures->size()) {
- out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )];
- std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures);
- conv.textures.dismiss();
- }
-
- // acknowledge that the scene might come out incomplete
- // by Assimps definition of `complete`: blender scenes
- // can consist of thousands of cameras or lights with
- // not a single mesh between them.
- if (!out->mNumMeshes) {
- out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- }
+ ConversionData conv(file);
+
+ // FIXME it must be possible to take the hierarchy directly from
+ // the file. This is terrible. Here, we're first looking for
+ // all objects which don't have parent objects at all -
+ std::deque<const Object*> no_parents;
+ for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) {
+ if (cur->object) {
+ if(!cur->object->parent) {
+ no_parents.push_back(cur->object.get());
+ }
+ else conv.objects.insert(cur->object.get());
+ }
+ }
+ for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
+ if (cur->object) {
+ if(cur->object->parent) {
+ conv.objects.insert(cur->object.get());
+ }
+ }
+ }
+
+ if (no_parents.empty()) {
+ ThrowException("Expected at least one object with no parent");
+ }
+
+ aiNode* root = out->mRootNode = new aiNode("<BlenderRoot>");
+
+ root->mNumChildren = static_cast<unsigned int>(no_parents.size());
+ root->mChildren = new aiNode*[root->mNumChildren]();
+ for (unsigned int i = 0; i < root->mNumChildren; ++i) {
+ root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());
+ root->mChildren[i]->mParent = root;
+ }
+
+ BuildMaterials(conv);
+
+ if (conv.meshes->size()) {
+ out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast<unsigned int>( conv.meshes->size() )];
+ std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes);
+ conv.meshes.dismiss();
+ }
+
+ if (conv.lights->size()) {
+ out->mLights = new aiLight*[out->mNumLights = static_cast<unsigned int>( conv.lights->size() )];
+ std::copy(conv.lights->begin(),conv.lights->end(),out->mLights);
+ conv.lights.dismiss();
+ }
+
+ if (conv.cameras->size()) {
+ out->mCameras = new aiCamera*[out->mNumCameras = static_cast<unsigned int>( conv.cameras->size() )];
+ std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras);
+ conv.cameras.dismiss();
+ }
+
+ if (conv.materials->size()) {
+ out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast<unsigned int>( conv.materials->size() )];
+ std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials);
+ conv.materials.dismiss();
+ }
+
+ if (conv.textures->size()) {
+ out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )];
+ std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures);
+ conv.textures.dismiss();
+ }
+
+ // acknowledge that the scene might come out incomplete
+ // by Assimps definition of `complete`: blender scenes
+ // can consist of thousands of cameras or lights with
+ // not a single mesh between them.
+ if (!out->mNumMeshes) {
+ out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data)
{
- (void)mat; (void)tex; (void)conv_data;
- aiString name;
-
- // check if the file contents are bundled with the BLEND file
- if (img->packedfile) {
- name.data[0] = '*';
- name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size());
-
- conv_data.textures->push_back(new aiTexture());
- aiTexture* tex = conv_data.textures->back();
-
- // usually 'img->name' will be the original file name of the embedded textures,
- // so we can extract the file extension from it.
- const size_t nlen = strlen( img->name );
- const char* s = img->name+nlen, *e = s;
-
- while (s >= img->name && *s != '.')--s;
-
- tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
- tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
- tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
- tex->achFormatHint[3] = '\0';
-
- // tex->mHeight = 0;
- tex->mWidth = img->packedfile->size;
- uint8_t* ch = new uint8_t[tex->mWidth];
-
- conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
- conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
-
- tex->pcData = reinterpret_cast<aiTexel*>(ch);
-
- LogInfo("Reading embedded texture, original file was "+std::string(img->name));
- }
- else {
- name = aiString( img->name );
- }
-
- aiTextureType texture_type = aiTextureType_UNKNOWN;
- MTex::MapType map_type = tex->mapto;
-
- if (map_type & MTex::MapType_COL)
- texture_type = aiTextureType_DIFFUSE;
- else if (map_type & MTex::MapType_NORM) {
- if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
- texture_type = aiTextureType_NORMALS;
- }
- else {
- texture_type = aiTextureType_HEIGHT;
- }
- out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
- }
- else if (map_type & MTex::MapType_COLSPEC)
- texture_type = aiTextureType_SPECULAR;
- else if (map_type & MTex::MapType_COLMIR)
- texture_type = aiTextureType_REFLECTION;
- //else if (map_type & MTex::MapType_REF)
- else if (map_type & MTex::MapType_SPEC)
- texture_type = aiTextureType_SHININESS;
- else if (map_type & MTex::MapType_EMIT)
- texture_type = aiTextureType_EMISSIVE;
- //else if (map_type & MTex::MapType_ALPHA)
- //else if (map_type & MTex::MapType_HAR)
- //else if (map_type & MTex::MapType_RAYMIRR)
- //else if (map_type & MTex::MapType_TRANSLU)
- else if (map_type & MTex::MapType_AMB)
- texture_type = aiTextureType_AMBIENT;
- else if (map_type & MTex::MapType_DISPLACE)
- texture_type = aiTextureType_DISPLACEMENT;
- //else if (map_type & MTex::MapType_WARP)
-
- out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
- conv_data.next_texture[texture_type]++));
+ (void)mat; (void)tex; (void)conv_data;
+ aiString name;
+
+ // check if the file contents are bundled with the BLEND file
+ if (img->packedfile) {
+ name.data[0] = '*';
+ name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size());
+
+ conv_data.textures->push_back(new aiTexture());
+ aiTexture* tex = conv_data.textures->back();
+
+ // usually 'img->name' will be the original file name of the embedded textures,
+ // so we can extract the file extension from it.
+ const size_t nlen = strlen( img->name );
+ const char* s = img->name+nlen, *e = s;
+
+ while (s >= img->name && *s != '.')--s;
+
+ tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
+ tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
+ tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
+ tex->achFormatHint[3] = '\0';
+
+ // tex->mHeight = 0;
+ tex->mWidth = img->packedfile->size;
+ uint8_t* ch = new uint8_t[tex->mWidth];
+
+ conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
+ conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
+
+ tex->pcData = reinterpret_cast<aiTexel*>(ch);
+
+ LogInfo("Reading embedded texture, original file was "+std::string(img->name));
+ }
+ else {
+ name = aiString( img->name );
+ }
+
+ aiTextureType texture_type = aiTextureType_UNKNOWN;
+ MTex::MapType map_type = tex->mapto;
+
+ if (map_type & MTex::MapType_COL)
+ texture_type = aiTextureType_DIFFUSE;
+ else if (map_type & MTex::MapType_NORM) {
+ if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
+ texture_type = aiTextureType_NORMALS;
+ }
+ else {
+ texture_type = aiTextureType_HEIGHT;
+ }
+ out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
+ }
+ else if (map_type & MTex::MapType_COLSPEC)
+ texture_type = aiTextureType_SPECULAR;
+ else if (map_type & MTex::MapType_COLMIR)
+ texture_type = aiTextureType_REFLECTION;
+ //else if (map_type & MTex::MapType_REF)
+ else if (map_type & MTex::MapType_SPEC)
+ texture_type = aiTextureType_SHININESS;
+ else if (map_type & MTex::MapType_EMIT)
+ texture_type = aiTextureType_EMISSIVE;
+ //else if (map_type & MTex::MapType_ALPHA)
+ //else if (map_type & MTex::MapType_HAR)
+ //else if (map_type & MTex::MapType_RAYMIRR)
+ //else if (map_type & MTex::MapType_TRANSLU)
+ else if (map_type & MTex::MapType_AMB)
+ texture_type = aiTextureType_AMBIENT;
+ else if (map_type & MTex::MapType_DISPLACE)
+ texture_type = aiTextureType_DISPLACEMENT;
+ //else if (map_type & MTex::MapType_WARP)
+
+ out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
+ conv_data.next_texture[texture_type]++));
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::AddSentinelTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
{
- (void)mat; (void)tex; (void)conv_data;
-
- aiString name;
- name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
- GetTextureTypeDisplayString(tex->tex->type)
- );
- out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
- conv_data.next_texture[aiTextureType_DIFFUSE]++)
- );
+ (void)mat; (void)tex; (void)conv_data;
+
+ aiString name;
+ name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
+ GetTextureTypeDisplayString(tex->tex->type)
+ );
+ out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
+ conv_data.next_texture[aiTextureType_DIFFUSE]++)
+ );
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
{
- const Tex* rtex = tex->tex.get();
- if(!rtex || !rtex->type) {
- return;
- }
-
- // We can't support most of the texture types because they're mostly procedural.
- // These are substituted by a dummy texture.
- const char* dispnam = "";
- switch( rtex->type )
- {
- // these are listed in blender's UI
- case Tex::Type_CLOUDS :
- case Tex::Type_WOOD :
- case Tex::Type_MARBLE :
- case Tex::Type_MAGIC :
- case Tex::Type_BLEND :
- case Tex::Type_STUCCI :
- case Tex::Type_NOISE :
- case Tex::Type_PLUGIN :
- case Tex::Type_MUSGRAVE :
- case Tex::Type_VORONOI :
- case Tex::Type_DISTNOISE :
- case Tex::Type_ENVMAP :
-
- // these do no appear in the UI, why?
- case Tex::Type_POINTDENSITY :
- case Tex::Type_VOXELDATA :
-
- LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam);
- AddSentinelTexture(out, mat, tex, conv_data);
- break;
-
- case Tex::Type_IMAGE :
- if (!rtex->ima) {
- LogError("A texture claims to be an Image, but no image reference is given");
- break;
- }
- ResolveImage(out, mat, tex, rtex->ima.get(),conv_data);
- break;
-
- default:
- ai_assert(false);
- };
+ const Tex* rtex = tex->tex.get();
+ if(!rtex || !rtex->type) {
+ return;
+ }
+
+ // We can't support most of the texture types because they're mostly procedural.
+ // These are substituted by a dummy texture.
+ const char* dispnam = "";
+ switch( rtex->type )
+ {
+ // these are listed in blender's UI
+ case Tex::Type_CLOUDS :
+ case Tex::Type_WOOD :
+ case Tex::Type_MARBLE :
+ case Tex::Type_MAGIC :
+ case Tex::Type_BLEND :
+ case Tex::Type_STUCCI :
+ case Tex::Type_NOISE :
+ case Tex::Type_PLUGIN :
+ case Tex::Type_MUSGRAVE :
+ case Tex::Type_VORONOI :
+ case Tex::Type_DISTNOISE :
+ case Tex::Type_ENVMAP :
+
+ // these do no appear in the UI, why?
+ case Tex::Type_POINTDENSITY :
+ case Tex::Type_VOXELDATA :
+
+ LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam);
+ AddSentinelTexture(out, mat, tex, conv_data);
+ break;
+
+ case Tex::Type_IMAGE :
+ if (!rtex->ima) {
+ LogError("A texture claims to be an Image, but no image reference is given");
+ break;
+ }
+ ResolveImage(out, mat, tex, rtex->ima.get(),conv_data);
+ break;
+
+ default:
+ ai_assert(false);
+ };
}
// ------------------------------------------------------------------------------------------------
-void BlenderImporter::BuildMaterials(ConversionData& conv_data)
+void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data)
{
- conv_data.materials->reserve(conv_data.materials_raw.size());
-
- // add a default material if necessary
- unsigned int index = static_cast<unsigned int>( -1 );
- for_each( aiMesh* mesh, conv_data.meshes.get() ) {
- if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
-
- if (index == static_cast<unsigned int>( -1 )) {
-
- // ok, we need to add a dedicated default material for some poor material-less meshes
- boost::shared_ptr<Material> p(new Material());
- strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
-
- p->r = p->g = p->b = 0.6f;
- p->specr = p->specg = p->specb = 0.6f;
- p->ambr = p->ambg = p->ambb = 0.0f;
- p->mirr = p->mirg = p->mirb = 0.0f;
- p->emit = 0.f;
- p->alpha = 0.f;
-
- // XXX add more / or add default c'tor to Material
-
- index = static_cast<unsigned int>( conv_data.materials_raw.size() );
- conv_data.materials_raw.push_back(p);
-
- LogInfo("Adding default material ...");
- }
- mesh->mMaterialIndex = index;
- }
- }
-
- for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) {
-
- // reset per material global counters
- for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
- conv_data.next_texture[i] = 0 ;
- }
-
- aiMaterial* mout = new aiMaterial();
- conv_data.materials->push_back(mout);
-
- // set material name
- aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
- mout->AddProperty(&name,AI_MATKEY_NAME);
-
-
- // basic material colors
- aiColor3D col(mat->r,mat->g,mat->b);
- if (mat->r || mat->g || mat->b ) {
-
- // Usually, zero diffuse color means no diffuse color at all in the equation.
- // So we omit this member to express this intent.
- mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE);
-
- if (mat->emit) {
- aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b) ;
- mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE) ;
- }
- }
-
- col = aiColor3D(mat->specr,mat->specg,mat->specb);
- mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR);
-
- // is hardness/shininess set?
- if( mat->har ) {
- const float har = mat->har;
- mout->AddProperty(&har,1,AI_MATKEY_SHININESS);
- }
-
- col = aiColor3D(mat->ambr,mat->ambg,mat->ambb);
- mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
-
- col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
- mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
-
- for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) {
- if (!mat->mtex[i]) {
- continue;
- }
-
- ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
- }
- }
+ // add a default material if necessary
+ unsigned int index = static_cast<unsigned int>( -1 );
+ for( aiMesh* mesh : conv_data.meshes.get() ) {
+ if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
+
+ if (index == static_cast<unsigned int>( -1 )) {
+ // Setup a default material.
+ std::shared_ptr<Material> p(new Material());
+ ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
+ strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
+
+ // Note: MSVC11 does not zero-initialize Material here, although it should.
+ // Thus all relevant fields should be explicitly initialized. We cannot add
+ // a default constructor to Material since the DNA codegen does not support
+ // parsing it.
+ p->r = p->g = p->b = 0.6f;
+ p->specr = p->specg = p->specb = 0.6f;
+ p->ambr = p->ambg = p->ambb = 0.0f;
+ p->mirr = p->mirg = p->mirb = 0.0f;
+ p->emit = 0.f;
+ p->alpha = 0.f;
+ p->har = 0;
+
+ index = static_cast<unsigned int>( conv_data.materials_raw.size() );
+ conv_data.materials_raw.push_back(p);
+ LogInfo("Adding default material");
+ }
+ mesh->mMaterialIndex = index;
+ }
+ }
+}
+
+void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
+{
+ aiColor3D diffuseColor(source->r, source->g, source->b);
+ result->AddProperty(&diffuseColor, 1, "$mat.blend.diffuse.color", 0, 0);
+
+ float diffuseIntensity = source->ref;
+ result->AddProperty(&diffuseIntensity, 1, "$mat.blend.diffuse.intensity", 0, 0);
+
+ int diffuseShader = source->diff_shader;
+ result->AddProperty(&diffuseShader, 1, "$mat.blend.diffuse.shader", 0, 0);
+
+ int diffuseRamp = 0;
+ result->AddProperty(&diffuseRamp, 1, "$mat.blend.diffuse.ramp", 0, 0);
+
+
+ aiColor3D specularColor(source->specr, source->specg, source->specb);
+ result->AddProperty(&specularColor, 1, "$mat.blend.specular.color", 0, 0);
+
+ float specularIntensity = source->spec;
+ result->AddProperty(&specularIntensity, 1, "$mat.blend.specular.intensity", 0, 0);
+
+ int specularShader = source->spec_shader;
+ result->AddProperty(&specularShader, 1, "$mat.blend.specular.shader", 0, 0);
+
+ int specularRamp = 0;
+ result->AddProperty(&specularRamp, 1, "$mat.blend.specular.ramp", 0, 0);
+
+ int specularHardness = source->har;
+ result->AddProperty(&specularHardness, 1, "$mat.blend.specular.hardness", 0, 0);
+
+
+ int transparencyUse = source->mode & MA_TRANSPARENCY ? 1 : 0;
+ result->AddProperty(&transparencyUse, 1, "$mat.blend.transparency.use", 0, 0);
+
+ int transparencyMethod = source->mode & MA_RAYTRANSP ? 2 : (source->mode & MA_ZTRANSP ? 1 : 0);
+ result->AddProperty(&transparencyMethod, 1, "$mat.blend.transparency.method", 0, 0);
+
+ float transparencyAlpha = source->alpha;
+ result->AddProperty(&transparencyAlpha, 1, "$mat.blend.transparency.alpha", 0, 0);
+
+ float transparencySpecular = source->spectra;
+ result->AddProperty(&transparencySpecular, 1, "$mat.blend.transparency.specular", 0, 0);
+
+ float transparencyFresnel = source->fresnel_tra;
+ result->AddProperty(&transparencyFresnel, 1, "$mat.blend.transparency.fresnel", 0, 0);
+
+ float transparencyBlend = source->fresnel_tra_i;
+ result->AddProperty(&transparencyBlend, 1, "$mat.blend.transparency.blend", 0, 0);
+
+ float transparencyIor = source->ang;
+ result->AddProperty(&transparencyIor, 1, "$mat.blend.transparency.ior", 0, 0);
+
+ float transparencyFilter = source->filter;
+ result->AddProperty(&transparencyFilter, 1, "$mat.blend.transparency.filter", 0, 0);
+
+ float transparencyFalloff = source->tx_falloff;
+ result->AddProperty(&transparencyFalloff, 1, "$mat.blend.transparency.falloff", 0, 0);
+
+ float transparencyLimit = source->tx_limit;
+ result->AddProperty(&transparencyLimit, 1, "$mat.blend.transparency.limit", 0, 0);
+
+ int transparencyDepth = source->ray_depth_tra;
+ result->AddProperty(&transparencyDepth, 1, "$mat.blend.transparency.depth", 0, 0);
+
+ float transparencyGlossAmount = source->gloss_tra;
+ result->AddProperty(&transparencyGlossAmount, 1, "$mat.blend.transparency.glossAmount", 0, 0);
+
+ float transparencyGlossThreshold = source->adapt_thresh_tra;
+ result->AddProperty(&transparencyGlossThreshold, 1, "$mat.blend.transparency.glossThreshold", 0, 0);
+
+ int transparencyGlossSamples = source->samp_gloss_tra;
+ result->AddProperty(&transparencyGlossSamples, 1, "$mat.blend.transparency.glossSamples", 0, 0);
+
+
+ int mirrorUse = source->mode & MA_RAYMIRROR ? 1 : 0;
+ result->AddProperty(&mirrorUse, 1, "$mat.blend.mirror.use", 0, 0);
+
+ float mirrorReflectivity = source->ray_mirror;
+ result->AddProperty(&mirrorReflectivity, 1, "$mat.blend.mirror.reflectivity", 0, 0);
+
+ aiColor3D mirrorColor(source->mirr, source->mirg, source->mirb);
+ result->AddProperty(&mirrorColor, 1, "$mat.blend.mirror.color", 0, 0);
+
+ float mirrorFresnel = source->fresnel_mir;
+ result->AddProperty(&mirrorFresnel, 1, "$mat.blend.mirror.fresnel", 0, 0);
+
+ float mirrorBlend = source->fresnel_mir_i;
+ result->AddProperty(&mirrorBlend, 1, "$mat.blend.mirror.blend", 0, 0);
+
+ int mirrorDepth = source->ray_depth;
+ result->AddProperty(&mirrorDepth, 1, "$mat.blend.mirror.depth", 0, 0);
+
+ float mirrorMaxDist = source->dist_mir;
+ result->AddProperty(&mirrorMaxDist, 1, "$mat.blend.mirror.maxDist", 0, 0);
+
+ int mirrorFadeTo = source->fadeto_mir;
+ result->AddProperty(&mirrorFadeTo, 1, "$mat.blend.mirror.fadeTo", 0, 0);
+
+ float mirrorGlossAmount = source->gloss_mir;
+ result->AddProperty(&mirrorGlossAmount, 1, "$mat.blend.mirror.glossAmount", 0, 0);
+
+ float mirrorGlossThreshold = source->adapt_thresh_mir;
+ result->AddProperty(&mirrorGlossThreshold, 1, "$mat.blend.mirror.glossThreshold", 0, 0);
+
+ int mirrorGlossSamples = source->samp_gloss_mir;
+ result->AddProperty(&mirrorGlossSamples, 1, "$mat.blend.mirror.glossSamples", 0, 0);
+
+ float mirrorGlossAnisotropic = source->aniso_gloss_mir;
+ result->AddProperty(&mirrorGlossAnisotropic, 1, "$mat.blend.mirror.glossAnisotropic", 0, 0);
+}
+
+void BlenderImporter::BuildMaterials(ConversionData& conv_data)
+{
+ conv_data.materials->reserve(conv_data.materials_raw.size());
+
+ BuildDefaultMaterial(conv_data);
+
+ for(std::shared_ptr<Material> mat : conv_data.materials_raw) {
+
+ // reset per material global counters
+ for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
+ conv_data.next_texture[i] = 0 ;
+ }
+
+ aiMaterial* mout = new aiMaterial();
+ conv_data.materials->push_back(mout);
+ // For any new material field handled here, the default material above must be updated with an appropriate default value.
+
+ // set material name
+ aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
+ mout->AddProperty(&name,AI_MATKEY_NAME);
+
+ // basic material colors
+ aiColor3D col(mat->r,mat->g,mat->b);
+ if (mat->r || mat->g || mat->b ) {
+
+ // Usually, zero diffuse color means no diffuse color at all in the equation.
+ // So we omit this member to express this intent.
+ mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ if (mat->emit) {
+ aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b) ;
+ mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE) ;
+ }
+ }
+
+ col = aiColor3D(mat->specr,mat->specg,mat->specb);
+ mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR);
+
+ // is hardness/shininess set?
+ if( mat->har ) {
+ const float har = mat->har;
+ mout->AddProperty(&har,1,AI_MATKEY_SHININESS);
+ }
+
+ col = aiColor3D(mat->ambr,mat->ambg,mat->ambb);
+ mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
+
+ // is mirror enabled?
+ if( mat->mode & MA_RAYMIRROR ) {
+ const float ray_mirror = mat->ray_mirror;
+ mout->AddProperty(&ray_mirror,1,AI_MATKEY_REFLECTIVITY);
+ }
+
+ col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
+ mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
+
+ for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) {
+ if (!mat->mtex[i]) {
+ continue;
+ }
+
+ ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
+ }
+
+ AddBlendParams(mout, mat.get());
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::CheckActualType(const ElemBase* dt, const char* check)
{
- ai_assert(dt);
- if (strcmp(dt->dna_type,check)) {
- ThrowException((format(),
- "Expected object at ",std::hex,dt," to be of type `",check,
- "`, but it claims to be a `",dt->dna_type,"`instead"
- ));
- }
+ ai_assert(dt);
+ if (strcmp(dt->dna_type,check)) {
+ ThrowException((format(),
+ "Expected object at ",std::hex,dt," to be of type `",check,
+ "`, but it claims to be a `",dt->dna_type,"`instead"
+ ));
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::NotSupportedObjectType(const Object* obj, const char* type)
{
- LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" ));
+ LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" ));
}
// ------------------------------------------------------------------------------------------------
void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, const Mesh* mesh,
- ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
- )
+ ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
+ )
{
- BlenderBMeshConverter BMeshConverter( mesh );
- if ( BMeshConverter.ContainsBMesh( ) )
- {
- mesh = BMeshConverter.TriangulateBMesh( );
- }
-
- typedef std::pair<const int,size_t> MyPair;
- if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
- return;
- }
-
- // some sanity checks
- if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){
- ThrowException("Number of faces is larger than the corresponding array");
- }
-
- if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) {
- ThrowException("Number of vertices is larger than the corresponding array");
- }
-
- if (static_cast<size_t> ( mesh->totloop ) > mesh->mloop.size()) {
- ThrowException("Number of vertices is larger than the corresponding array");
- }
-
- // collect per-submesh numbers
- std::map<int,size_t> per_mat;
- std::map<int,size_t> per_mat_verts;
- for (int i = 0; i < mesh->totface; ++i) {
-
- const MFace& mf = mesh->mface[i];
- per_mat[ mf.mat_nr ]++;
- per_mat_verts[ mf.mat_nr ] += mf.v4?4:3;
- }
-
- for (int i = 0; i < mesh->totpoly; ++i) {
- const MPoly& mp = mesh->mpoly[i];
- per_mat[ mp.mat_nr ]++;
- per_mat_verts[ mp.mat_nr ] += mp.totloop;
- }
-
- // ... and allocate the corresponding meshes
- const size_t old = temp->size();
- temp->reserve(temp->size() + per_mat.size());
-
- std::map<size_t,size_t> mat_num_to_mesh_idx;
- for_each(MyPair& it, per_mat) {
-
- mat_num_to_mesh_idx[it.first] = temp->size();
- temp->push_back(new aiMesh());
-
- aiMesh* out = temp->back();
- out->mVertices = new aiVector3D[per_mat_verts[it.first]];
- out->mNormals = new aiVector3D[per_mat_verts[it.first]];
-
- //out->mNumFaces = 0
- //out->mNumVertices = 0
- out->mFaces = new aiFace[it.second]();
-
- // all submeshes created from this mesh are named equally. this allows
- // curious users to recover the original adjacency.
- out->mName = aiString(mesh->id.name+2);
- // skip over the name prefix 'ME'
-
- // resolve the material reference and add this material to the set of
- // output materials. The (temporary) material index is the index
- // of the material entry within the list of resolved materials.
- if (mesh->mat) {
-
- if (static_cast<size_t> ( it.first ) >= mesh->mat.size() ) {
- ThrowException("Material index is out of range");
- }
-
- boost::shared_ptr<Material> mat = mesh->mat[it.first];
- const std::deque< boost::shared_ptr<Material> >::iterator has = std::find(
- conv_data.materials_raw.begin(),
- conv_data.materials_raw.end(),mat
- );
-
- if (has != conv_data.materials_raw.end()) {
- out->mMaterialIndex = static_cast<unsigned int>( std::distance(conv_data.materials_raw.begin(),has));
- }
- else {
- out->mMaterialIndex = static_cast<unsigned int>( conv_data.materials_raw.size() );
- conv_data.materials_raw.push_back(mat);
- }
- }
- else out->mMaterialIndex = static_cast<unsigned int>( -1 );
- }
-
- for (int i = 0; i < mesh->totface; ++i) {
-
- const MFace& mf = mesh->mface[i];
-
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
- aiFace& f = out->mFaces[out->mNumFaces++];
-
- f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ];
- aiVector3D* vo = out->mVertices + out->mNumVertices;
- aiVector3D* vn = out->mNormals + out->mNumVertices;
-
- // XXX we can't fold this easily, because we are restricted
- // to the member names from the BLEND file (v1,v2,v3,v4)
- // which are assigned by the genblenddna.py script and
- // cannot be changed without breaking the entire
- // import process.
-
- if (mf.v1 >= mesh->totvert) {
- ThrowException("Vertex index v1 out of range");
- }
- const MVert* v = &mesh->mvert[mf.v1];
- vo->x = v->co[0];
- vo->y = v->co[1];
- vo->z = v->co[2];
- vn->x = v->no[0];
- vn->y = v->no[1];
- vn->z = v->no[2];
- f.mIndices[0] = out->mNumVertices++;
- ++vo;
- ++vn;
-
- // if (f.mNumIndices >= 2) {
- if (mf.v2 >= mesh->totvert) {
- ThrowException("Vertex index v2 out of range");
- }
- v = &mesh->mvert[mf.v2];
- vo->x = v->co[0];
- vo->y = v->co[1];
- vo->z = v->co[2];
- vn->x = v->no[0];
- vn->y = v->no[1];
- vn->z = v->no[2];
- f.mIndices[1] = out->mNumVertices++;
- ++vo;
- ++vn;
-
- if (mf.v3 >= mesh->totvert) {
- ThrowException("Vertex index v3 out of range");
- }
- // if (f.mNumIndices >= 3) {
- v = &mesh->mvert[mf.v3];
- vo->x = v->co[0];
- vo->y = v->co[1];
- vo->z = v->co[2];
- vn->x = v->no[0];
- vn->y = v->no[1];
- vn->z = v->no[2];
- f.mIndices[2] = out->mNumVertices++;
- ++vo;
- ++vn;
-
- if (mf.v4 >= mesh->totvert) {
- ThrowException("Vertex index v4 out of range");
- }
- // if (f.mNumIndices >= 4) {
- if (mf.v4) {
- v = &mesh->mvert[mf.v4];
- vo->x = v->co[0];
- vo->y = v->co[1];
- vo->z = v->co[2];
- vn->x = v->no[0];
- vn->y = v->no[1];
- vn->z = v->no[2];
- f.mIndices[3] = out->mNumVertices++;
- ++vo;
- ++vn;
-
- out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- }
- else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-
- // }
- // }
- // }
- }
-
- for (int i = 0; i < mesh->totpoly; ++i) {
-
- const MPoly& mf = mesh->mpoly[i];
-
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
- aiFace& f = out->mFaces[out->mNumFaces++];
-
- f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ];
- aiVector3D* vo = out->mVertices + out->mNumVertices;
- aiVector3D* vn = out->mNormals + out->mNumVertices;
-
- // XXX we can't fold this easily, because we are restricted
- // to the member names from the BLEND file (v1,v2,v3,v4)
- // which are assigned by the genblenddna.py script and
- // cannot be changed without breaking the entire
- // import process.
- for (int j = 0;j < mf.totloop; ++j)
- {
- const MLoop& loop = mesh->mloop[mf.loopstart + j];
-
- if (loop.v >= mesh->totvert) {
- ThrowException("Vertex index out of range");
- }
-
- const MVert& v = mesh->mvert[loop.v];
-
- vo->x = v.co[0];
- vo->y = v.co[1];
- vo->z = v.co[2];
- vn->x = v.no[0];
- vn->y = v.no[1];
- vn->z = v.no[2];
- f.mIndices[j] = out->mNumVertices++;
-
- ++vo;
- ++vn;
-
- }
- if (mf.totloop == 3)
- {
- out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- }
- else
- {
- out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- }
- }
-
- // collect texture coordinates, they're stored in a separate per-face buffer
- if (mesh->mtface || mesh->mloopuv) {
- if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
- ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
- }
- for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
- ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
- (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
- (*it)->mNumFaces = (*it)->mNumVertices = 0;
- }
-
- for (int i = 0; i < mesh->totface; ++i) {
- const MTFace* v = &mesh->mtface[i];
-
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
- const aiFace& f = out->mFaces[out->mNumFaces++];
-
- aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
- for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
- vo->x = v->uv[i][0];
- vo->y = v->uv[i][1];
- }
- }
-
- for (int i = 0; i < mesh->totpoly; ++i) {
- const MPoly& v = mesh->mpoly[i];
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
- const aiFace& f = out->mFaces[out->mNumFaces++];
-
- aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
- for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
- const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
- vo->x = uv.uv[0];
- vo->y = uv.uv[1];
- }
-
- }
- }
-
- // collect texture coordinates, old-style (marked as deprecated in current blender sources)
- if (mesh->tface) {
- if (mesh->totface > static_cast<int> ( mesh->tface.size())) {
- ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
- }
- for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
- ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
- (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
- (*it)->mNumFaces = (*it)->mNumVertices = 0;
- }
-
- for (int i = 0; i < mesh->totface; ++i) {
- const TFace* v = &mesh->tface[i];
-
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
- const aiFace& f = out->mFaces[out->mNumFaces++];
-
- aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
- for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
- vo->x = v->uv[i][0];
- vo->y = v->uv[i][1];
- }
- }
- }
-
- // collect vertex colors, stored separately as well
- if (mesh->mcol || mesh->mloopcol) {
- if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) {
- ThrowException("Number of faces is larger than the corresponding color face array");
- }
- for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
- ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
- (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices];
- (*it)->mNumFaces = (*it)->mNumVertices = 0;
- }
-
- for (int i = 0; i < mesh->totface; ++i) {
-
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
- const aiFace& f = out->mFaces[out->mNumFaces++];
-
- aiColor4D* vo = &out->mColors[0][out->mNumVertices];
- for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) {
- const MCol* col = &mesh->mcol[(i<<2)+n];
-
- vo->r = col->r;
- vo->g = col->g;
- vo->b = col->b;
- vo->a = col->a;
- }
- for (unsigned int n = f.mNumIndices; n < 4; ++n);
- }
-
- for (int i = 0; i < mesh->totpoly; ++i) {
- const MPoly& v = mesh->mpoly[i];
- aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
- const aiFace& f = out->mFaces[out->mNumFaces++];
-
- aiColor4D* vo = &out->mColors[0][out->mNumVertices];
- for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
- const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
- vo->r = col.r;
- vo->g = col.g;
- vo->b = col.b;
- vo->a = col.a;
- }
-
- }
-
- }
-
- return;
+ // TODO: Resolve various problems with BMesh triangluation before re-enabling.
+ // See issues #400, #373, #318 #315 and #132.
+#if defined(TODO_FIX_BMESH_CONVERSION)
+ BlenderBMeshConverter BMeshConverter( mesh );
+ if ( BMeshConverter.ContainsBMesh( ) )
+ {
+ mesh = BMeshConverter.TriangulateBMesh( );
+ }
+#endif
+
+ typedef std::pair<const int,size_t> MyPair;
+ if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
+ return;
+ }
+
+ // some sanity checks
+ if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){
+ ThrowException("Number of faces is larger than the corresponding array");
+ }
+
+ if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) {
+ ThrowException("Number of vertices is larger than the corresponding array");
+ }
+
+ if (static_cast<size_t> ( mesh->totloop ) > mesh->mloop.size()) {
+ ThrowException("Number of vertices is larger than the corresponding array");
+ }
+
+ // collect per-submesh numbers
+ std::map<int,size_t> per_mat;
+ std::map<int,size_t> per_mat_verts;
+ for (int i = 0; i < mesh->totface; ++i) {
+
+ const MFace& mf = mesh->mface[i];
+ per_mat[ mf.mat_nr ]++;
+ per_mat_verts[ mf.mat_nr ] += mf.v4?4:3;
+ }
+
+ for (int i = 0; i < mesh->totpoly; ++i) {
+ const MPoly& mp = mesh->mpoly[i];
+ per_mat[ mp.mat_nr ]++;
+ per_mat_verts[ mp.mat_nr ] += mp.totloop;
+ }
+
+ // ... and allocate the corresponding meshes
+ const size_t old = temp->size();
+ temp->reserve(temp->size() + per_mat.size());
+
+ std::map<size_t,size_t> mat_num_to_mesh_idx;
+ for(MyPair& it : per_mat) {
+
+ mat_num_to_mesh_idx[it.first] = temp->size();
+ temp->push_back(new aiMesh());
+
+ aiMesh* out = temp->back();
+ out->mVertices = new aiVector3D[per_mat_verts[it.first]];
+ out->mNormals = new aiVector3D[per_mat_verts[it.first]];
+
+ //out->mNumFaces = 0
+ //out->mNumVertices = 0
+ out->mFaces = new aiFace[it.second]();
+
+ // all submeshes created from this mesh are named equally. this allows
+ // curious users to recover the original adjacency.
+ out->mName = aiString(mesh->id.name+2);
+ // skip over the name prefix 'ME'
+
+ // resolve the material reference and add this material to the set of
+ // output materials. The (temporary) material index is the index
+ // of the material entry within the list of resolved materials.
+ if (mesh->mat) {
+
+ if (static_cast<size_t> ( it.first ) >= mesh->mat.size() ) {
+ ThrowException("Material index is out of range");
+ }
+
+ std::shared_ptr<Material> mat = mesh->mat[it.first];
+ const std::deque< std::shared_ptr<Material> >::iterator has = std::find(
+ conv_data.materials_raw.begin(),
+ conv_data.materials_raw.end(),mat
+ );
+
+ if (has != conv_data.materials_raw.end()) {
+ out->mMaterialIndex = static_cast<unsigned int>( std::distance(conv_data.materials_raw.begin(),has));
+ }
+ else {
+ out->mMaterialIndex = static_cast<unsigned int>( conv_data.materials_raw.size() );
+ conv_data.materials_raw.push_back(mat);
+ }
+ }
+ else out->mMaterialIndex = static_cast<unsigned int>( -1 );
+ }
+
+ for (int i = 0; i < mesh->totface; ++i) {
+
+ const MFace& mf = mesh->mface[i];
+
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
+ aiFace& f = out->mFaces[out->mNumFaces++];
+
+ f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ];
+ aiVector3D* vo = out->mVertices + out->mNumVertices;
+ aiVector3D* vn = out->mNormals + out->mNumVertices;
+
+ // XXX we can't fold this easily, because we are restricted
+ // to the member names from the BLEND file (v1,v2,v3,v4)
+ // which are assigned by the genblenddna.py script and
+ // cannot be changed without breaking the entire
+ // import process.
+
+ if (mf.v1 >= mesh->totvert) {
+ ThrowException("Vertex index v1 out of range");
+ }
+ const MVert* v = &mesh->mvert[mf.v1];
+ vo->x = v->co[0];
+ vo->y = v->co[1];
+ vo->z = v->co[2];
+ vn->x = v->no[0];
+ vn->y = v->no[1];
+ vn->z = v->no[2];
+ f.mIndices[0] = out->mNumVertices++;
+ ++vo;
+ ++vn;
+
+ // if (f.mNumIndices >= 2) {
+ if (mf.v2 >= mesh->totvert) {
+ ThrowException("Vertex index v2 out of range");
+ }
+ v = &mesh->mvert[mf.v2];
+ vo->x = v->co[0];
+ vo->y = v->co[1];
+ vo->z = v->co[2];
+ vn->x = v->no[0];
+ vn->y = v->no[1];
+ vn->z = v->no[2];
+ f.mIndices[1] = out->mNumVertices++;
+ ++vo;
+ ++vn;
+
+ if (mf.v3 >= mesh->totvert) {
+ ThrowException("Vertex index v3 out of range");
+ }
+ // if (f.mNumIndices >= 3) {
+ v = &mesh->mvert[mf.v3];
+ vo->x = v->co[0];
+ vo->y = v->co[1];
+ vo->z = v->co[2];
+ vn->x = v->no[0];
+ vn->y = v->no[1];
+ vn->z = v->no[2];
+ f.mIndices[2] = out->mNumVertices++;
+ ++vo;
+ ++vn;
+
+ if (mf.v4 >= mesh->totvert) {
+ ThrowException("Vertex index v4 out of range");
+ }
+ // if (f.mNumIndices >= 4) {
+ if (mf.v4) {
+ v = &mesh->mvert[mf.v4];
+ vo->x = v->co[0];
+ vo->y = v->co[1];
+ vo->z = v->co[2];
+ vn->x = v->no[0];
+ vn->y = v->no[1];
+ vn->z = v->no[2];
+ f.mIndices[3] = out->mNumVertices++;
+ ++vo;
+ ++vn;
+
+ out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+ else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+
+ // }
+ // }
+ // }
+ }
+
+ for (int i = 0; i < mesh->totpoly; ++i) {
+
+ const MPoly& mf = mesh->mpoly[i];
+
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
+ aiFace& f = out->mFaces[out->mNumFaces++];
+
+ f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ];
+ aiVector3D* vo = out->mVertices + out->mNumVertices;
+ aiVector3D* vn = out->mNormals + out->mNumVertices;
+
+ // XXX we can't fold this easily, because we are restricted
+ // to the member names from the BLEND file (v1,v2,v3,v4)
+ // which are assigned by the genblenddna.py script and
+ // cannot be changed without breaking the entire
+ // import process.
+ for (int j = 0;j < mf.totloop; ++j)
+ {
+ const MLoop& loop = mesh->mloop[mf.loopstart + j];
+
+ if (loop.v >= mesh->totvert) {
+ ThrowException("Vertex index out of range");
+ }
+
+ const MVert& v = mesh->mvert[loop.v];
+
+ vo->x = v.co[0];
+ vo->y = v.co[1];
+ vo->z = v.co[2];
+ vn->x = v.no[0];
+ vn->y = v.no[1];
+ vn->z = v.no[2];
+ f.mIndices[j] = out->mNumVertices++;
+
+ ++vo;
+ ++vn;
+
+ }
+ if (mf.totloop == 3)
+ {
+ out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ }
+ else
+ {
+ out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+ }
+
+ // collect texture coordinates, they're stored in a separate per-face buffer
+ if (mesh->mtface || mesh->mloopuv) {
+ if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
+ ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
+ }
+ for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+ ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+ (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+ (*it)->mNumFaces = (*it)->mNumVertices = 0;
+ }
+
+ for (int i = 0; i < mesh->totface; ++i) {
+ const MTFace* v = &mesh->mtface[i];
+
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+ const aiFace& f = out->mFaces[out->mNumFaces++];
+
+ aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+ for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
+ vo->x = v->uv[i][0];
+ vo->y = v->uv[i][1];
+ }
+ }
+
+ for (int i = 0; i < mesh->totpoly; ++i) {
+ const MPoly& v = mesh->mpoly[i];
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
+ const aiFace& f = out->mFaces[out->mNumFaces++];
+
+ aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+ for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
+ const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
+ vo->x = uv.uv[0];
+ vo->y = uv.uv[1];
+ }
+
+ }
+ }
+
+ // collect texture coordinates, old-style (marked as deprecated in current blender sources)
+ if (mesh->tface) {
+ if (mesh->totface > static_cast<int> ( mesh->tface.size())) {
+ ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
+ }
+ for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+ ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+ (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+ (*it)->mNumFaces = (*it)->mNumVertices = 0;
+ }
+
+ for (int i = 0; i < mesh->totface; ++i) {
+ const TFace* v = &mesh->tface[i];
+
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+ const aiFace& f = out->mFaces[out->mNumFaces++];
+
+ aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+ for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
+ vo->x = v->uv[i][0];
+ vo->y = v->uv[i][1];
+ }
+ }
+ }
+
+ // collect vertex colors, stored separately as well
+ if (mesh->mcol || mesh->mloopcol) {
+ if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) {
+ ThrowException("Number of faces is larger than the corresponding color face array");
+ }
+ for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+ ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+ (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices];
+ (*it)->mNumFaces = (*it)->mNumVertices = 0;
+ }
+
+ for (int i = 0; i < mesh->totface; ++i) {
+
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+ const aiFace& f = out->mFaces[out->mNumFaces++];
+
+ aiColor4D* vo = &out->mColors[0][out->mNumVertices];
+ for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) {
+ const MCol* col = &mesh->mcol[(i<<2)+n];
+
+ vo->r = col->r;
+ vo->g = col->g;
+ vo->b = col->b;
+ vo->a = col->a;
+ }
+ for (unsigned int n = f.mNumIndices; n < 4; ++n);
+ }
+
+ for (int i = 0; i < mesh->totpoly; ++i) {
+ const MPoly& v = mesh->mpoly[i];
+ aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
+ const aiFace& f = out->mFaces[out->mNumFaces++];
+
+ aiColor4D* vo = &out->mColors[0][out->mNumVertices];
+ for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
+ const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
+ vo->r = col.r;
+ vo->g = col.g;
+ vo->b = col.b;
+ vo->a = col.a;
+ }
+
+ }
+
+ }
+
+ return;
}
// ------------------------------------------------------------------------------------------------
-aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
+aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/)
{
- ScopeGuard<aiCamera> out(new aiCamera());
- out->mName = obj->id.name+2;
- out->mPosition = aiVector3D(0.f, 0.f, 0.f);
- out->mUp = aiVector3D(0.f, 1.f, 0.f);
- out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
- return out.dismiss();
+ ScopeGuard<aiCamera> out(new aiCamera());
+ out->mName = obj->id.name+2;
+ out->mPosition = aiVector3D(0.f, 0.f, 0.f);
+ out->mUp = aiVector3D(0.f, 1.f, 0.f);
+ out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
+ if (cam->sensor_x && cam->lens) {
+ out->mHorizontalFOV = atan2(cam->sensor_x, 2.f * cam->lens);
+ }
+ out->mClipPlaneNear = cam->clipsta;
+ out->mClipPlaneFar = cam->clipend;
+
+ return out.dismiss();
}
// ------------------------------------------------------------------------------------------------
-aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
+aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
{
- ScopeGuard<aiLight> out(new aiLight());
- out->mName = obj->id.name+2;
-
- switch (lamp->type)
- {
- case Lamp::Type_Local:
- out->mType = aiLightSource_POINT;
- break;
- case Lamp::Type_Sun:
- out->mType = aiLightSource_DIRECTIONAL;
-
- // blender orients directional lights as facing toward -z
- out->mDirection = aiVector3D(0.f, 0.f, -1.f);
- break;
- default:
- break;
- }
-
- out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
- out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
- out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
- return out.dismiss();
+ ScopeGuard<aiLight> out(new aiLight());
+ out->mName = obj->id.name+2;
+
+ switch (lamp->type)
+ {
+ case Lamp::Type_Local:
+ out->mType = aiLightSource_POINT;
+ break;
+ case Lamp::Type_Sun:
+ out->mType = aiLightSource_DIRECTIONAL;
+
+ // blender orients directional lights as facing toward -z
+ out->mDirection = aiVector3D(0.f, 0.f, -1.f);
+ out->mUp = aiVector3D(0.f, 1.f, 0.f);
+ break;
+
+ case Lamp::Type_Area:
+ out->mType = aiLightSource_AREA;
+
+ if (lamp->area_shape == 0) {
+ out->mSize = aiVector2D(lamp->area_size, lamp->area_size);
+ }
+ else {
+ out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey);
+ }
+
+ // blender orients directional lights as facing toward -z
+ out->mDirection = aiVector3D(0.f, 0.f, -1.f);
+ out->mUp = aiVector3D(0.f, 1.f, 0.f);
+ break;
+
+ default:
+ break;
+ }
+
+ out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+ out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+ out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
+ return out.dismiss();
}
// ------------------------------------------------------------------------------------------------
aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
{
- std::deque<const Object*> children;
- for(std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
- const Object* object = *it;
- if (object->parent == obj) {
- children.push_back(object);
-
- conv_data.objects.erase(it++);
- continue;
- }
- ++it;
- }
-
- ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
- if (obj->data) {
- switch (obj->type)
- {
- case Object :: Type_EMPTY:
- break; // do nothing
-
-
- // supported object types
- case Object :: Type_MESH: {
- const size_t old = conv_data.meshes->size();
-
- CheckActualType(obj->data.get(),"Mesh");
- ConvertMesh(in,obj,static_cast<const Mesh*>(obj->data.get()),conv_data,conv_data.meshes);
-
- if (conv_data.meshes->size() > old) {
- node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)];
- for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
- node->mMeshes[i] = i + old;
- }
- }}
- break;
- case Object :: Type_LAMP: {
- CheckActualType(obj->data.get(),"Lamp");
- aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>(
- obj->data.get()),conv_data);
-
- if (mesh) {
- conv_data.lights->push_back(mesh);
- }}
- break;
- case Object :: Type_CAMERA: {
- CheckActualType(obj->data.get(),"Camera");
- aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>(
- obj->data.get()),conv_data);
-
- if (mesh) {
- conv_data.cameras->push_back(mesh);
- }}
- break;
-
-
- // unsupported object types / log, but do not break
- case Object :: Type_CURVE:
- NotSupportedObjectType(obj,"Curve");
- break;
- case Object :: Type_SURF:
- NotSupportedObjectType(obj,"Surface");
- break;
- case Object :: Type_FONT:
- NotSupportedObjectType(obj,"Font");
- break;
- case Object :: Type_MBALL:
- NotSupportedObjectType(obj,"MetaBall");
- break;
- case Object :: Type_WAVE:
- NotSupportedObjectType(obj,"Wave");
- break;
- case Object :: Type_LATTICE:
- NotSupportedObjectType(obj,"Lattice");
- break;
-
- // invalid or unknown type
- default:
- break;
- }
- }
-
- for(unsigned int x = 0; x < 4; ++x) {
- for(unsigned int y = 0; y < 4; ++y) {
- node->mTransformation[y][x] = obj->obmat[x][y];
- }
- }
-
- aiMatrix4x4 m = parentTransform;
- m = m.Inverse();
-
- node->mTransformation = m*node->mTransformation;
-
- if (children.size()) {
- node->mNumChildren = static_cast<unsigned int>(children.size());
- aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
- for_each (const Object* nobj,children) {
- *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
- (*nd++)->mParent = node;
- }
- }
-
- // apply modifiers
- modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
-
- return node.dismiss();
+ std::deque<const Object*> children;
+ for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
+ const Object* object = *it;
+ if (object->parent == obj) {
+ children.push_back(object);
+
+ conv_data.objects.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+
+ ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
+ if (obj->data) {
+ switch (obj->type)
+ {
+ case Object :: Type_EMPTY:
+ break; // do nothing
+
+
+ // supported object types
+ case Object :: Type_MESH: {
+ const size_t old = conv_data.meshes->size();
+
+ CheckActualType(obj->data.get(),"Mesh");
+ ConvertMesh(in,obj,static_cast<const Mesh*>(obj->data.get()),conv_data,conv_data.meshes);
+
+ if (conv_data.meshes->size() > old) {
+ node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)];
+ for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+ node->mMeshes[i] = i + old;
+ }
+ }}
+ break;
+ case Object :: Type_LAMP: {
+ CheckActualType(obj->data.get(),"Lamp");
+ aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>(
+ obj->data.get()),conv_data);
+
+ if (mesh) {
+ conv_data.lights->push_back(mesh);
+ }}
+ break;
+ case Object :: Type_CAMERA: {
+ CheckActualType(obj->data.get(),"Camera");
+ aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>(
+ obj->data.get()),conv_data);
+
+ if (mesh) {
+ conv_data.cameras->push_back(mesh);
+ }}
+ break;
+
+
+ // unsupported object types / log, but do not break
+ case Object :: Type_CURVE:
+ NotSupportedObjectType(obj,"Curve");
+ break;
+ case Object :: Type_SURF:
+ NotSupportedObjectType(obj,"Surface");
+ break;
+ case Object :: Type_FONT:
+ NotSupportedObjectType(obj,"Font");
+ break;
+ case Object :: Type_MBALL:
+ NotSupportedObjectType(obj,"MetaBall");
+ break;
+ case Object :: Type_WAVE:
+ NotSupportedObjectType(obj,"Wave");
+ break;
+ case Object :: Type_LATTICE:
+ NotSupportedObjectType(obj,"Lattice");
+ break;
+
+ // invalid or unknown type
+ default:
+ break;
+ }
+ }
+
+ for(unsigned int x = 0; x < 4; ++x) {
+ for(unsigned int y = 0; y < 4; ++y) {
+ node->mTransformation[y][x] = obj->obmat[x][y];
+ }
+ }
+
+ aiMatrix4x4 m = parentTransform;
+ m = m.Inverse();
+
+ node->mTransformation = m*node->mTransformation;
+
+ if (children.size()) {
+ node->mNumChildren = static_cast<unsigned int>(children.size());
+ aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
+ for (const Object* nobj :children) {
+ *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
+ (*nd++)->mParent = node;
+ }
+ }
+
+ // apply modifiers
+ modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
+
+ return node.dismiss();
}
diff --git a/src/3rdparty/assimp/code/BlenderLoader.h b/src/3rdparty/assimp/code/BlenderLoader.h
index f7c1a08dc..c964eee32 100644
--- a/src/3rdparty/assimp/code/BlenderLoader.h
+++ b/src/3rdparty/assimp/code/BlenderLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,44 +46,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "LogAux.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;
- }
-
- // BlenderDNA.h
- namespace Blender {
- class FileDatabase;
- struct ElemBase;
- }
-
- // BlenderScene.h
- namespace Blender {
- struct Scene;
- struct Object;
- struct Mesh;
- struct Camera;
- struct Lamp;
- struct MTex;
- struct Image;
- struct Material;
- }
-
- // BlenderIntermediate.h
- namespace Blender {
- struct ConversionData;
- template <template <typename,typename> class TCLASS, typename T> struct TempArray;
- }
-
- // BlenderModifier.h
- namespace Blender {
- class BlenderModifierShowcase;
- class BlenderModifier;
- }
+#include <memory>
+
+struct aiNode;
+struct aiMesh;
+struct aiLight;
+struct aiCamera;
+struct aiMaterial;
+
+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;
+ }
+
+ // BlenderDNA.h
+ namespace Blender {
+ class FileDatabase;
+ struct ElemBase;
+ }
+
+ // BlenderScene.h
+ namespace Blender {
+ struct Scene;
+ struct Object;
+ struct Mesh;
+ struct Camera;
+ struct Lamp;
+ struct MTex;
+ struct Image;
+ struct Material;
+ }
+
+ // BlenderIntermediate.h
+ namespace Blender {
+ struct ConversionData;
+ template <template <typename,typename> class TCLASS, typename T> struct TempArray;
+ }
+
+ // BlenderModifier.h
+ namespace Blender {
+ class BlenderModifierShowcase;
+ class BlenderModifier;
+ }
@@ -95,127 +102,136 @@ namespace Assimp {
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
{
public:
- BlenderImporter();
- ~BlenderImporter();
+ BlenderImporter();
+ ~BlenderImporter();
public:
- // --------------------
- bool CanRead( const std::string& pFile,
- IOSystem* pIOHandler,
- bool checkSig
- ) const;
+ // --------------------
+ bool CanRead( const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const;
protected:
- // --------------------
- const aiImporterDesc* GetInfo () const;
+ // --------------------
+ const aiImporterDesc* GetInfo () const;
- // --------------------
- void GetExtensionList(std::set<std::string>& app);
+ // --------------------
+ void GetExtensionList(std::set<std::string>& app);
- // --------------------
- void SetupProperties(const Importer* pImp);
+ // --------------------
+ void SetupProperties(const Importer* pImp);
- // --------------------
- void InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler
- );
+ // --------------------
+ void InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ );
- // --------------------
- void ParseBlendFile(Blender::FileDatabase& out,
- boost::shared_ptr<IOStream> stream
- );
+ // --------------------
+ void ParseBlendFile(Blender::FileDatabase& out,
+ std::shared_ptr<IOStream> stream
+ );
- // --------------------
- void ExtractScene(Blender::Scene& out,
- const Blender::FileDatabase& file
- );
+ // --------------------
+ void ExtractScene(Blender::Scene& out,
+ const Blender::FileDatabase& file
+ );
- // --------------------
- void ConvertBlendFile(aiScene* out,
- const Blender::Scene& in,
- const Blender::FileDatabase& file
- );
+ // --------------------
+ void ConvertBlendFile(aiScene* out,
+ const Blender::Scene& in,
+ const Blender::FileDatabase& file
+ );
private:
- // --------------------
- aiNode* ConvertNode(const Blender::Scene& in,
- const Blender::Object* obj,
- Blender::ConversionData& conv_info,
- const aiMatrix4x4& parentTransform
- );
-
- // --------------------
- void ConvertMesh(const Blender::Scene& in,
- const Blender::Object* obj,
- const Blender::Mesh* mesh,
- Blender::ConversionData& conv_data,
- Blender::TempArray<std::vector,aiMesh>& temp
- );
-
- // --------------------
- aiLight* ConvertLight(const Blender::Scene& in,
- const Blender::Object* obj,
- const Blender::Lamp* mesh,
- Blender::ConversionData& conv_data
- );
-
- // --------------------
- aiCamera* ConvertCamera(const Blender::Scene& in,
- const Blender::Object* obj,
- const Blender::Camera* mesh,
- Blender::ConversionData& conv_data
- );
-
- // --------------------
- void BuildMaterials(
- Blender::ConversionData& conv_data
- ) ;
-
- // --------------------
- void ResolveTexture(
- aiMaterial* out,
- const Blender::Material* mat,
- const Blender::MTex* tex,
- Blender::ConversionData& conv_data
- );
-
- // --------------------
- void ResolveImage(
- aiMaterial* out,
- const Blender::Material* mat,
- const Blender::MTex* tex,
- const Blender::Image* img,
- Blender::ConversionData& conv_data
- );
-
- void AddSentinelTexture(
- aiMaterial* out,
- const Blender::Material* mat,
- const Blender::MTex* tex,
- Blender::ConversionData& conv_data
- );
+ // --------------------
+ aiNode* ConvertNode(const Blender::Scene& in,
+ const Blender::Object* obj,
+ Blender::ConversionData& conv_info,
+ const aiMatrix4x4& parentTransform
+ );
+
+ // --------------------
+ void ConvertMesh(const Blender::Scene& in,
+ const Blender::Object* obj,
+ const Blender::Mesh* mesh,
+ Blender::ConversionData& conv_data,
+ Blender::TempArray<std::vector,aiMesh>& temp
+ );
+
+ // --------------------
+ aiLight* ConvertLight(const Blender::Scene& in,
+ const Blender::Object* obj,
+ const Blender::Lamp* mesh,
+ Blender::ConversionData& conv_data
+ );
+
+ // --------------------
+ aiCamera* ConvertCamera(const Blender::Scene& in,
+ const Blender::Object* obj,
+ const Blender::Camera* mesh,
+ Blender::ConversionData& conv_data
+ );
+
+ // --------------------
+ void BuildDefaultMaterial(
+ Blender::ConversionData& conv_data
+ );
+
+ void AddBlendParams(
+ aiMaterial* result,
+ const Blender::Material* source
+ );
+
+ void BuildMaterials(
+ Blender::ConversionData& conv_data
+ );
+
+ // --------------------
+ void ResolveTexture(
+ aiMaterial* out,
+ const Blender::Material* mat,
+ const Blender::MTex* tex,
+ Blender::ConversionData& conv_data
+ );
+
+ // --------------------
+ void ResolveImage(
+ aiMaterial* out,
+ const Blender::Material* mat,
+ const Blender::MTex* tex,
+ const Blender::Image* img,
+ Blender::ConversionData& conv_data
+ );
+
+ void AddSentinelTexture(
+ aiMaterial* out,
+ const Blender::Material* mat,
+ const Blender::MTex* tex,
+ Blender::ConversionData& conv_data
+ );
private: // static stuff, mostly logging and error reporting.
- // --------------------
- static void CheckActualType(const Blender::ElemBase* dt,
- const char* check
- );
+ // --------------------
+ static void CheckActualType(const Blender::ElemBase* dt,
+ const char* check
+ );
- // --------------------
- static void NotSupportedObjectType(const Blender::Object* obj,
- const char* type
- );
+ // --------------------
+ static void NotSupportedObjectType(const Blender::Object* obj,
+ const char* type
+ );
private:
- Blender::BlenderModifierShowcase* modifier_cache;
+ Blender::BlenderModifierShowcase* modifier_cache;
}; // !class BlenderImporter
diff --git a/src/3rdparty/assimp/code/BlenderModifier.cpp b/src/3rdparty/assimp/code/BlenderModifier.cpp
index 6ed31271c..24aed25d0 100644
--- a/src/3rdparty/assimp/code/BlenderModifier.cpp
+++ b/src/3rdparty/assimp/code/BlenderModifier.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,12 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderModifier.cpp
* @brief Implementation of some blender modifiers (i.e subdivision, mirror).
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderModifier.h"
#include "SceneCombiner.h"
#include "Subdivision.h"
+#include <assimp/scene.h>
+#include <memory>
#include <functional>
@@ -54,120 +56,120 @@ using namespace Assimp;
using namespace Assimp::Blender;
template <typename T> BlenderModifier* god() {
- return new T();
+ return new T();
}
// add all available modifiers here
typedef BlenderModifier* (*fpCreateModifier)();
static const fpCreateModifier creators[] = {
- &god<BlenderModifier_Mirror>,
- &god<BlenderModifier_Subdivision>,
+ &god<BlenderModifier_Mirror>,
+ &god<BlenderModifier_Subdivision>,
- NULL // sentinel
+ NULL // sentinel
};
// ------------------------------------------------------------------------------------------------
// just testing out some new macros to simplify logging
#define ASSIMP_LOG_WARN_F(string,...)\
- DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
+ DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_ERROR_F(string,...)\
- DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
+ DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_DEBUG_F(string,...)\
- DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
+ DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_INFO_F(string,...)\
- DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
+ DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_WARN(string)\
- DefaultLogger::get()->warn(string)
+ DefaultLogger::get()->warn(string)
#define ASSIMP_LOG_ERROR(string)\
- DefaultLogger::get()->error(string)
+ DefaultLogger::get()->error(string)
#define ASSIMP_LOG_DEBUG(string)\
- DefaultLogger::get()->debug(string)
+ DefaultLogger::get()->debug(string)
#define ASSIMP_LOG_INFO(string)\
- DefaultLogger::get()->info(string)
+ DefaultLogger::get()->info(string)
// ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase
{
- ModifierData modifier;
+ ModifierData modifier;
};
// ------------------------------------------------------------------------------------------------
-void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
+void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
{
- size_t cnt = 0u, ful = 0u;
-
- // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
- // we're allowed to dereference the pointers without risking to crash. We might still be
- // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
- // structures is at offset sizeof(vftable) with no padding.
- const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() );
- for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) {
- ai_assert(cur->dna_type);
-
- const Structure* s = conv_data.db.dna.Get( cur->dna_type );
- if (!s) {
- ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
- continue;
- }
-
- // this is a common trait of all XXXMirrorData structures in BlenderDNA
- const Field* f = s->Get("modifier");
- if (!f || f->offset != 0) {
- ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
- continue;
- }
-
- s = conv_data.db.dna.Get( f->type );
- if (!s || s->name != "ModifierData") {
- ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
- continue;
- }
-
- // now, we can be sure that we should be fine to dereference *cur* as
- // ModifierData (with the above note).
- const ModifierData& dat = cur->modifier;
-
- const fpCreateModifier* curgod = creators;
- std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
-
- for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
- if (curmod == endmod) {
- cached_modifiers->push_back((*curgod)());
-
- endmod = cached_modifiers->end();
- curmod = endmod-1;
- }
-
- BlenderModifier* const modifier = *curmod;
- if(modifier->IsActive(dat)) {
- modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object);
- cnt++;
-
- curgod = NULL;
- break;
- }
- }
- if (curgod) {
- ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
- }
- }
-
- // Even though we managed to resolve some or all of the modifiers on this
- // object, we still can't say whether our modifier implementations were
- // able to fully do their job.
- if (ful) {
- ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
- "`, check log messages above for errors");
- }
+ size_t cnt = 0u, ful = 0u;
+
+ // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
+ // we're allowed to dereference the pointers without risking to crash. We might still be
+ // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
+ // structures is at offset sizeof(vftable) with no padding.
+ const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
+ for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
+ ai_assert(cur->dna_type);
+
+ const Structure* s = conv_data.db.dna.Get( cur->dna_type );
+ if (!s) {
+ ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
+ continue;
+ }
+
+ // this is a common trait of all XXXMirrorData structures in BlenderDNA
+ const Field* f = s->Get("modifier");
+ if (!f || f->offset != 0) {
+ ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
+ continue;
+ }
+
+ s = conv_data.db.dna.Get( f->type );
+ if (!s || s->name != "ModifierData") {
+ ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
+ continue;
+ }
+
+ // now, we can be sure that we should be fine to dereference *cur* as
+ // ModifierData (with the above note).
+ const ModifierData& dat = cur->modifier;
+
+ const fpCreateModifier* curgod = creators;
+ std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
+
+ for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
+ if (curmod == endmod) {
+ cached_modifiers->push_back((*curgod)());
+
+ endmod = cached_modifiers->end();
+ curmod = endmod-1;
+ }
+
+ BlenderModifier* const modifier = *curmod;
+ if(modifier->IsActive(dat)) {
+ modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
+ cnt++;
+
+ curgod = NULL;
+ break;
+ }
+ }
+ if (curgod) {
+ ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
+ }
+ }
+
+ // Even though we managed to resolve some or all of the modifiers on this
+ // object, we still can't say whether our modifier implementations were
+ // able to fully do their job.
+ if (ful) {
+ ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
+ "`, check log messages above for errors");
+ }
}
@@ -175,102 +177,102 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
{
- return modin.type == ModifierData::eModifierType_Mirror;
+ return modin.type == ModifierData::eModifierType_Mirror;
}
// ------------------------------------------------------------------------------------------------
-void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
- const Scene& /*in*/,
- const Object& orig_object )
+void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
+ const Scene& /*in*/,
+ const Object& orig_object )
{
- // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
- const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
- ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
-
- conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
-
- // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
-
- // take all input meshes and clone them
- for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
- aiMesh* mesh;
- SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
-
- const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
- const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
- const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
-
- if (mir.mirror_ob) {
- const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mVertices[i];
-
- v.x = center.x + xs*(center.x - v.x);
- v.y = center.y + ys*(center.y - v.y);
- v.z = center.z + zs*(center.z - v.z);
- }
- }
- else {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mVertices[i];
- v.x *= xs;v.y *= ys;v.z *= zs;
- }
- }
-
- if (mesh->mNormals) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mNormals[i];
- v.x *= xs;v.y *= ys;v.z *= zs;
- }
- }
-
- if (mesh->mTangents) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mTangents[i];
- v.x *= xs;v.y *= ys;v.z *= zs;
- }
- }
-
- if (mesh->mBitangents) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mBitangents[i];
- v.x *= xs;v.y *= ys;v.z *= zs;
- }
- }
-
- const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
- const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
-
- for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- aiVector3D& v = mesh->mTextureCoords[n][i];
- v.x *= us;v.y *= vs;
- }
- }
-
- // Only reverse the winding order if an odd number of axes were mirrored.
- if (xs * ys * zs < 0) {
- for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
- aiFace& face = mesh->mFaces[i];
- for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
- std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
- }
- }
-
- conv_data.meshes->push_back(mesh);
- }
- unsigned int* nind = new unsigned int[out.mNumMeshes*2];
-
- std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
- std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
- std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
-
- delete[] out.mMeshes;
- out.mMeshes = nind;
- out.mNumMeshes *= 2;
-
- ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
- orig_object.id.name,"`");
+ // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
+ const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
+ ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
+
+ conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
+
+ // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
+
+ // take all input meshes and clone them
+ for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
+ aiMesh* mesh;
+ SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
+
+ const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
+ const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
+ const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
+
+ if (mir.mirror_ob) {
+ const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mVertices[i];
+
+ v.x = center.x + xs*(center.x - v.x);
+ v.y = center.y + ys*(center.y - v.y);
+ v.z = center.z + zs*(center.z - v.z);
+ }
+ }
+ else {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mVertices[i];
+ v.x *= xs;v.y *= ys;v.z *= zs;
+ }
+ }
+
+ if (mesh->mNormals) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mNormals[i];
+ v.x *= xs;v.y *= ys;v.z *= zs;
+ }
+ }
+
+ if (mesh->mTangents) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mTangents[i];
+ v.x *= xs;v.y *= ys;v.z *= zs;
+ }
+ }
+
+ if (mesh->mBitangents) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mBitangents[i];
+ v.x *= xs;v.y *= ys;v.z *= zs;
+ }
+ }
+
+ const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
+ const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
+
+ for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ aiVector3D& v = mesh->mTextureCoords[n][i];
+ v.x *= us;v.y *= vs;
+ }
+ }
+
+ // Only reverse the winding order if an odd number of axes were mirrored.
+ if (xs * ys * zs < 0) {
+ for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
+ aiFace& face = mesh->mFaces[i];
+ for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
+ std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
+ }
+ }
+
+ conv_data.meshes->push_back(mesh);
+ }
+ unsigned int* nind = new unsigned int[out.mNumMeshes*2];
+
+ std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
+ std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
+ std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
+
+ delete[] out.mMeshes;
+ out.mMeshes = nind;
+ out.mNumMeshes *= 2;
+
+ ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
+ orig_object.id.name,"`");
}
@@ -279,46 +281,46 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{
- return modin.type == ModifierData::eModifierType_Subsurf;
+ return modin.type == ModifierData::eModifierType_Subsurf;
}
// ------------------------------------------------------------------------------------------------
-void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
- const Scene& /*in*/,
- const Object& orig_object )
+void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
+ const Scene& /*in*/,
+ const Object& orig_object )
{
- // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
- const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
- ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
-
- Subdivider::Algorithm algo;
- switch (mir.subdivType)
- {
- case SubsurfModifierData::TYPE_CatmullClarke:
- algo = Subdivider::CATMULL_CLARKE;
- break;
-
- case SubsurfModifierData::TYPE_Simple:
- ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
- algo = Subdivider::CATMULL_CLARKE;
- break;
-
- default:
- ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
- return;
- };
-
- boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo));
- ai_assert(subd);
-
- aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
- boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]());
-
- subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
- std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
-
- ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
- orig_object.id.name,"`");
+ // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
+ const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
+ ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
+
+ Subdivider::Algorithm algo;
+ switch (mir.subdivType)
+ {
+ case SubsurfModifierData::TYPE_CatmullClarke:
+ algo = Subdivider::CATMULL_CLARKE;
+ break;
+
+ case SubsurfModifierData::TYPE_Simple:
+ ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
+ algo = Subdivider::CATMULL_CLARKE;
+ break;
+
+ default:
+ ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
+ return;
+ };
+
+ std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
+ ai_assert(subd);
+
+ aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
+ std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
+
+ subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
+ std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
+
+ ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
+ orig_object.id.name,"`");
}
#endif
diff --git a/src/3rdparty/assimp/code/BlenderModifier.h b/src/3rdparty/assimp/code/BlenderModifier.h
index 6646d6161..1d176756e 100644
--- a/src/3rdparty/assimp/code/BlenderModifier.h
+++ b/src/3rdparty/assimp/code/BlenderModifier.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,41 +46,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h"
#include "TinyFormatter.h"
+
namespace Assimp {
- namespace Blender {
+namespace Blender {
// -------------------------------------------------------------------------------------------
/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
* they should be stateless and not try to cache model data. */
// -------------------------------------------------------------------------------------------
-class BlenderModifier
+class BlenderModifier
{
public:
-
- virtual ~BlenderModifier() {
- }
+ virtual ~BlenderModifier() {
+ // empty
+ }
public:
- // --------------------
- /** Check if *this* modifier is active, given a ModifierData& block.*/
- virtual bool IsActive( const ModifierData& /*modin*/) {
- return false;
- }
-
- // --------------------
- /** Apply the modifier to a given output node. The original data used
- * to construct the node is given as well. Not called unless IsActive()
- * was called and gave positive response. */
- virtual void DoIt(aiNode& /*out*/,
- ConversionData& /*conv_data*/,
- const ElemBase& orig_modifier,
- const Scene& /*in*/,
- const Object& /*orig_object*/
- ) {
- DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
- return;
- }
+ // --------------------
+ /** Check if *this* modifier is active, given a ModifierData& block.*/
+ virtual bool IsActive( const ModifierData& /*modin*/) {
+ return false;
+ }
+
+ // --------------------
+ /** Apply the modifier to a given output node. The original data used
+ * to construct the node is given as well. Not called unless IsActive()
+ * was called and gave positive response. */
+ virtual void DoIt(aiNode& /*out*/,
+ ConversionData& /*conv_data*/,
+ const ElemBase& orig_modifier,
+ const Scene& /*in*/,
+ const Object& /*orig_object*/
+ ) {
+ DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
+ return;
+ }
};
@@ -91,17 +92,17 @@ class BlenderModifierShowcase
{
public:
- // --------------------
- /** Apply all requested modifiers provided we support them. */
- void ApplyModifiers(aiNode& out,
- ConversionData& conv_data,
- const Scene& in,
- const Object& orig_object
- );
+ // --------------------
+ /** Apply all requested modifiers provided we support them. */
+ void ApplyModifiers(aiNode& out,
+ ConversionData& conv_data,
+ const Scene& in,
+ const Object& orig_object
+ );
private:
- TempArray< std::vector,BlenderModifier > cached_modifiers;
+ TempArray< std::vector,BlenderModifier > cached_modifiers;
};
@@ -119,16 +120,16 @@ class BlenderModifier_Mirror : public BlenderModifier
{
public:
- // --------------------
- virtual bool IsActive( const ModifierData& modin);
-
- // --------------------
- virtual void DoIt(aiNode& out,
- ConversionData& conv_data,
- const ElemBase& orig_modifier,
- const Scene& in,
- const Object& orig_object
- ) ;
+ // --------------------
+ virtual bool IsActive( const ModifierData& modin);
+
+ // --------------------
+ virtual void DoIt(aiNode& out,
+ ConversionData& conv_data,
+ const ElemBase& orig_modifier,
+ const Scene& in,
+ const Object& orig_object
+ ) ;
};
// -------------------------------------------------------------------------------------------
@@ -138,16 +139,16 @@ class BlenderModifier_Subdivision : public BlenderModifier
{
public:
- // --------------------
- virtual bool IsActive( const ModifierData& modin);
-
- // --------------------
- virtual void DoIt(aiNode& out,
- ConversionData& conv_data,
- const ElemBase& orig_modifier,
- const Scene& in,
- const Object& orig_object
- ) ;
+ // --------------------
+ virtual bool IsActive( const ModifierData& modin);
+
+ // --------------------
+ virtual void DoIt(aiNode& out,
+ ConversionData& conv_data,
+ const ElemBase& orig_modifier,
+ const Scene& in,
+ const Object& orig_object
+ ) ;
};
diff --git a/src/3rdparty/assimp/code/BlenderScene.cpp b/src/3rdparty/assimp/code/BlenderScene.cpp
index 39b57a508..f4d07662e 100644
--- a/src/3rdparty/assimp/code/BlenderScene.cpp
+++ b/src/3rdparty/assimp/code/BlenderScene.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
-Copyright (c) 2006-2010, ASSIMP Development Team
+Copyright (c) 2006-2016, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderScene.cpp
* @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderDNA.h"
@@ -56,7 +56,7 @@ template <> void Structure :: Convert<Object> (
Object& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
@@ -64,7 +64,7 @@ template <> void Structure :: Convert<Object> (
ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
{
- boost::shared_ptr<Object> parent;
+ std::shared_ptr<Object> parent;
ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db);
dest.parent = parent.get();
}
@@ -76,7 +76,7 @@ template <> void Structure :: Convert<Object> (
ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -84,13 +84,13 @@ template <> void Structure :: Convert<Group> (
Group& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -98,7 +98,7 @@ template <> void Structure :: Convert<MTex> (
MTex& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Igno>((short&)dest.mapto,"mapto",db);
ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
@@ -129,7 +129,7 @@ template <> void Structure :: Convert<MTex> (
ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -137,7 +137,7 @@ template <> void Structure :: Convert<TFace> (
TFace& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db);
@@ -146,7 +146,7 @@ template <> void Structure :: Convert<TFace> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -154,7 +154,7 @@ template <> void Structure :: Convert<SubsurfModifierData> (
SubsurfModifierData& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
ReadField<ErrorPolicy_Warn>(dest.subdivType,"subdivType",db);
@@ -162,7 +162,7 @@ template <> void Structure :: Convert<SubsurfModifierData> (
ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -170,7 +170,7 @@ template <> void Structure :: Convert<MFace> (
MFace& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
@@ -179,7 +179,7 @@ template <> void Structure :: Convert<MFace> (
ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -187,7 +187,7 @@ template <> void Structure :: Convert<Lamp> (
Lamp& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
@@ -206,8 +206,12 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
+ ReadField<ErrorPolicy_Igno>(dest.area_size,"area_size",db);
+ ReadField<ErrorPolicy_Igno>(dest.area_sizey,"area_sizey",db);
+ ReadField<ErrorPolicy_Igno>(dest.area_sizez,"area_sizez",db);
+ ReadField<ErrorPolicy_Igno>(dest.area_shape,"area_shape",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -215,12 +219,12 @@ template <> void Structure :: Convert<MDeformWeight> (
MDeformWeight& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -228,13 +232,13 @@ template <> void Structure :: Convert<PackedFile> (
PackedFile& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -242,37 +246,37 @@ template <> void Structure :: Convert<Base> (
Base& dest,
const FileDatabase& db
) const
-{
- // note: as per https://github.com/assimp/assimp/issues/128,
- // reading the Object linked list recursively is prone to stack overflow.
- // This structure converter is therefore an hand-written exception that
- // does it iteratively.
+{
+ // note: as per https://github.com/assimp/assimp/issues/128,
+ // reading the Object linked list recursively is prone to stack overflow.
+ // This structure converter is therefore an hand-written exception that
+ // does it iteratively.
+
+ const int initial_pos = db.reader->GetCurrentPos();
- const int initial_pos = db.reader->GetCurrentPos();
+ std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
+ for ( ;; ) {
- std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
- for ( ;; ) {
-
- Base& cur_dest = *todo.first;
- db.reader->SetCurrentPos(todo.second);
+ Base& cur_dest = *todo.first;
+ db.reader->SetCurrentPos(todo.second);
- // we know that this is a double-linked, circular list which we never
- // traverse backwards, so don't bother resolving the back links.
- cur_dest.prev = NULL;
+ // we know that this is a double-linked, circular list which we never
+ // traverse backwards, so don't bother resolving the back links.
+ cur_dest.prev = NULL;
- ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+ ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+
+ // the return value of ReadFieldPtr indicates whether the object
+ // was already cached. In this case, we don't need to resolve
+ // it again.
+ if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
+ todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
+ continue;
+ }
+ break;
+ }
- // the return value of ReadFieldPtr indicates whether the object
- // was already cached. In this case, we don't need to resolve
- // it again.
- if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
- todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
- continue;
- }
- break;
- }
-
- db.reader->SetCurrentPos(initial_pos + size);
+ db.reader->SetCurrentPos(initial_pos + size);
}
//--------------------------------------------------------------------------------
@@ -280,7 +284,7 @@ template <> void Structure :: Convert<MTFace> (
MTFace& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
@@ -288,7 +292,7 @@ template <> void Structure :: Convert<MTFace> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -296,8 +300,7 @@ template <> void Structure :: Convert<Material> (
Material& dest,
const FileDatabase& db
) const
-{
-
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
@@ -313,9 +316,11 @@ template <> void Structure :: Convert<Material> (
ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db);
ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db);
ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db);
+ ReadField<ErrorPolicy_Igno>(dest.ray_mirror,"ray_mirror",db);
ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db);
ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db);
ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db);
+ ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db);
ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db);
ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db);
@@ -324,7 +329,92 @@ template <> void Structure :: Convert<Material> (
ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
- db.reader->IncPtr(size);
+
+ ReadField<ErrorPolicy_Igno>(dest.amb, "amb", db);
+ ReadField<ErrorPolicy_Igno>(dest.ang, "ang", db);
+ ReadField<ErrorPolicy_Igno>(dest.spectra, "spectra", db);
+ ReadField<ErrorPolicy_Igno>(dest.spec, "spec", db);
+ ReadField<ErrorPolicy_Igno>(dest.zoffs, "zoffs", db);
+ ReadField<ErrorPolicy_Igno>(dest.add, "add", db);
+ ReadField<ErrorPolicy_Igno>(dest.fresnel_mir, "fresnel_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.fresnel_mir_i, "fresnel_mir_i", db);
+ ReadField<ErrorPolicy_Igno>(dest.fresnel_tra, "fresnel_tra", db);
+ ReadField<ErrorPolicy_Igno>(dest.fresnel_tra_i, "fresnel_tra_i", db);
+ ReadField<ErrorPolicy_Igno>(dest.filter, "filter", db);
+ ReadField<ErrorPolicy_Igno>(dest.tx_limit, "tx_limit", db);
+ ReadField<ErrorPolicy_Igno>(dest.tx_falloff, "tx_falloff", db);
+ ReadField<ErrorPolicy_Igno>(dest.gloss_mir, "gloss_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.gloss_tra, "gloss_tra", db);
+ ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_mir, "adapt_thresh_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_tra, "adapt_thresh_tra", db);
+ ReadField<ErrorPolicy_Igno>(dest.aniso_gloss_mir, "aniso_gloss_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.dist_mir, "dist_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.hasize, "hasize", db);
+ ReadField<ErrorPolicy_Igno>(dest.flaresize, "flaresize", db);
+ ReadField<ErrorPolicy_Igno>(dest.subsize, "subsize", db);
+ ReadField<ErrorPolicy_Igno>(dest.flareboost, "flareboost", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_sta, "strand_sta", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_end, "strand_end", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_ease, "strand_ease", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_surfnor, "strand_surfnor", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_min, "strand_min", db);
+ ReadField<ErrorPolicy_Igno>(dest.strand_widthfade, "strand_widthfade", db);
+ ReadField<ErrorPolicy_Igno>(dest.sbias, "sbias", db);
+ ReadField<ErrorPolicy_Igno>(dest.lbias, "lbias", db);
+ ReadField<ErrorPolicy_Igno>(dest.shad_alpha, "shad_alpha", db);
+ ReadField<ErrorPolicy_Igno>(dest.param, "param", db);
+ ReadField<ErrorPolicy_Igno>(dest.rms, "rms", db);
+ ReadField<ErrorPolicy_Igno>(dest.rampfac_col, "rampfac_col", db);
+ ReadField<ErrorPolicy_Igno>(dest.rampfac_spec, "rampfac_spec", db);
+ ReadField<ErrorPolicy_Igno>(dest.friction, "friction", db);
+ ReadField<ErrorPolicy_Igno>(dest.fh, "fh", db);
+ ReadField<ErrorPolicy_Igno>(dest.reflect, "reflect", db);
+ ReadField<ErrorPolicy_Igno>(dest.fhdist, "fhdist", db);
+ ReadField<ErrorPolicy_Igno>(dest.xyfrict, "xyfrict", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_radius, "sss_radius", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_col, "sss_col", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_error, "sss_error", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_scale, "sss_scale", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_ior, "sss_ior", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_colfac, "sss_colfac", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_texfac, "sss_texfac", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_front, "sss_front", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_back, "sss_back", db);
+
+ ReadField<ErrorPolicy_Igno>(dest.material_type, "material_type", db);
+ ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
+ ReadField<ErrorPolicy_Igno>(dest.ray_depth, "ray_depth", db);
+ ReadField<ErrorPolicy_Igno>(dest.ray_depth_tra, "ray_depth_tra", db);
+ ReadField<ErrorPolicy_Igno>(dest.samp_gloss_mir, "samp_gloss_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.samp_gloss_tra, "samp_gloss_tra", db);
+ ReadField<ErrorPolicy_Igno>(dest.fadeto_mir, "fadeto_mir", db);
+ ReadField<ErrorPolicy_Igno>(dest.shade_flag, "shade_flag", db);
+ ReadField<ErrorPolicy_Igno>(dest.flarec, "flarec", db);
+ ReadField<ErrorPolicy_Igno>(dest.starc, "starc", db);
+ ReadField<ErrorPolicy_Igno>(dest.linec, "linec", db);
+ ReadField<ErrorPolicy_Igno>(dest.ringc, "ringc", db);
+ ReadField<ErrorPolicy_Igno>(dest.pr_lamp, "pr_lamp", db);
+ ReadField<ErrorPolicy_Igno>(dest.pr_texture, "pr_texture", db);
+ ReadField<ErrorPolicy_Igno>(dest.ml_flag, "ml_flag", db);
+ ReadField<ErrorPolicy_Igno>(dest.diff_shader, "diff_shader", db);
+ ReadField<ErrorPolicy_Igno>(dest.spec_shader, "spec_shader", db);
+ ReadField<ErrorPolicy_Igno>(dest.texco, "texco", db);
+ ReadField<ErrorPolicy_Igno>(dest.mapto, "mapto", db);
+ ReadField<ErrorPolicy_Igno>(dest.ramp_show, "ramp_show", db);
+ ReadField<ErrorPolicy_Igno>(dest.pad3, "pad3", db);
+ ReadField<ErrorPolicy_Igno>(dest.dynamode, "dynamode", db);
+ ReadField<ErrorPolicy_Igno>(dest.pad2, "pad2", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_flag, "sss_flag", db);
+ ReadField<ErrorPolicy_Igno>(dest.sss_preset, "sss_preset", db);
+ ReadField<ErrorPolicy_Igno>(dest.shadowonly_flag, "shadowonly_flag", db);
+ ReadField<ErrorPolicy_Igno>(dest.index, "index", db);
+ ReadField<ErrorPolicy_Igno>(dest.vcol_alpha, "vcol_alpha", db);
+ ReadField<ErrorPolicy_Igno>(dest.pad4, "pad4", db);
+
+ ReadField<ErrorPolicy_Igno>(dest.seed1, "seed1", db);
+ ReadField<ErrorPolicy_Igno>(dest.seed2, "seed2", db);
+
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -332,10 +422,10 @@ template <> void Structure :: Convert<MTexPoly> (
MTexPoly& dest,
const FileDatabase& db
) const
-{
+{
{
- boost::shared_ptr<Image> tpage;
+ std::shared_ptr<Image> tpage;
ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
dest.tpage = tpage.get();
}
@@ -345,7 +435,7 @@ template <> void Structure :: Convert<MTexPoly> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -353,7 +443,7 @@ template <> void Structure :: Convert<Mesh> (
Mesh& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
@@ -379,7 +469,7 @@ template <> void Structure :: Convert<Mesh> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -387,12 +477,12 @@ template <> void Structure :: Convert<MDeformVert> (
MDeformVert& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -400,11 +490,11 @@ template <> void Structure :: Convert<World> (
World& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -412,14 +502,14 @@ template <> void Structure :: Convert<MLoopCol> (
MLoopCol& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -427,7 +517,7 @@ template <> void Structure :: Convert<MVert> (
MVert& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
@@ -435,7 +525,7 @@ template <> void Structure :: Convert<MVert> (
ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -443,7 +533,7 @@ template <> void Structure :: Convert<MEdge> (
MEdge& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
@@ -451,7 +541,7 @@ template <> void Structure :: Convert<MEdge> (
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -459,12 +549,12 @@ template <> void Structure :: Convert<MLoopUV> (
MLoopUV& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -472,13 +562,13 @@ template <> void Structure :: Convert<GroupObject> (
GroupObject& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -486,12 +576,12 @@ template <> void Structure :: Convert<ListBase> (
ListBase& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -499,12 +589,12 @@ template <> void Structure :: Convert<MLoop> (
MLoop& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -512,7 +602,7 @@ template <> void Structure :: Convert<ModifierData> (
ModifierData& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db);
@@ -520,7 +610,7 @@ template <> void Structure :: Convert<ModifierData> (
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -528,12 +618,12 @@ template <> void Structure :: Convert<ID> (
ID& dest,
const FileDatabase& db
) const
-{
+{
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -541,14 +631,14 @@ template <> void Structure :: Convert<MCol> (
MCol& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.r,"r",db);
ReadField<ErrorPolicy_Fail>(dest.g,"g",db);
ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -556,14 +646,14 @@ template <> void Structure :: Convert<MPoly> (
MPoly& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -571,7 +661,7 @@ template <> void Structure :: Convert<Scene> (
Scene& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db);
@@ -579,7 +669,7 @@ template <> void Structure :: Convert<Scene> (
ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -587,14 +677,14 @@ template <> void Structure :: Convert<Library> (
Library& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -602,12 +692,12 @@ template <> void Structure :: Convert<Tex> (
Tex& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Igno>((short&)dest.imaflag,"imaflag",db);
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -615,14 +705,17 @@ template <> void Structure :: Convert<Camera> (
Camera& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
- ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db);
+ ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
+ ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
+ ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);
+ ReadField<ErrorPolicy_Igno>(dest.clipend,"clipend",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -630,7 +723,7 @@ template <> void Structure :: Convert<MirrorModifierData> (
MirrorModifierData& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db);
@@ -638,7 +731,7 @@ template <> void Structure :: Convert<MirrorModifierData> (
ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
@@ -646,7 +739,7 @@ template <> void Structure :: Convert<Image> (
Image& dest,
const FileDatabase& db
) const
-{
+{
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
@@ -671,7 +764,7 @@ template <> void Structure :: Convert<Image> (
ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
- db.reader->IncPtr(size);
+ db.reader->IncPtr(size);
}
//--------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/BlenderScene.h b/src/3rdparty/assimp/code/BlenderScene.h
index 37ad282f3..187557765 100644
--- a/src/3rdparty/assimp/code/BlenderScene.h
+++ b/src/3rdparty/assimp/code/BlenderScene.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,8 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BLEND_SCENE_H
#define INCLUDED_AI_BLEND_SCENE_H
-namespace Assimp {
- namespace Blender {
+#include "BlenderDNA.h"
+
+namespace Assimp {
+namespace Blender {
// Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory.
@@ -56,14 +58,14 @@ namespace Assimp {
// this file serves as input data to the `./scripts/genblenddna.py`
// script. This script generates the actual binding code to read a
// blender file with a possibly different DNA into our structures.
-// Only `struct` declarations are considered and the following
+// Only `struct` declarations are considered and the following
// rules must be obeyed in order for the script to work properly:
//
// * C++ style comments only
//
// * Structures may include the primitive types char, int, short,
-// float, double. Signedness specifiers are not allowed on
-// integers. Enum types are allowed, but they must have been
+// float, double. Signedness specifiers are not allowed on
+// integers. Enum types are allowed, but they must have been
// defined in this header.
//
// * Structures may aggregate other structures, unless not defined
@@ -71,7 +73,7 @@ namespace Assimp {
//
// * Pointers to other structures or primitive types are allowed.
// No references or double pointers or arrays of pointers.
-// A pointer to a T is normally written as boost::shared_ptr, while a
+// A pointer to a T is normally written as std::shared_ptr, while a
// pointer to an array of elements is written as boost::
// shared_array. To avoid cyclic pointers, use raw pointers in
// one direction.
@@ -85,7 +87,7 @@ namespace Assimp {
// * One of WARN, FAIL can be appended to the declaration (
// prior to the semiolon to specifiy the error handling policy if
// this field is missing in the input DNA). If none of those
-// is specified the default policy is to subtitute a default
+// is specified the default policy is to substitute a default
// value for the field.
//
@@ -96,20 +98,22 @@ struct Object;
struct MTex;
struct Image;
+#include <memory>
+
#define AI_BLEND_MESH_MAX_VERTS 2000000000L
// -------------------------------------------------------------------------------
struct ID : ElemBase {
- char name[24] WARN;
- short flag;
+ char name[1024] WARN;
+ short flag;
};
// -------------------------------------------------------------------------------
struct ListBase : ElemBase {
-
- boost::shared_ptr<ElemBase> first;
- boost::shared_ptr<ElemBase> last;
+
+ std::shared_ptr<ElemBase> first;
+ std::shared_ptr<ElemBase> last;
};
@@ -117,37 +121,37 @@ struct ListBase : ElemBase {
struct PackedFile : ElemBase {
int size WARN;
int seek WARN;
- boost::shared_ptr< FileOffset > data WARN;
+ std::shared_ptr< FileOffset > data WARN;
};
// -------------------------------------------------------------------------------
struct GroupObject : ElemBase {
-
- boost::shared_ptr<GroupObject> prev,next FAIL;
- boost::shared_ptr<Object> ob;
+
+ std::shared_ptr<GroupObject> prev,next FAIL;
+ std::shared_ptr<Object> ob;
};
// -------------------------------------------------------------------------------
struct Group : ElemBase {
- ID id FAIL;
- int layer;
+ ID id FAIL;
+ int layer;
- boost::shared_ptr<GroupObject> gobject;
+ std::shared_ptr<GroupObject> gobject;
};
// -------------------------------------------------------------------------------
struct World : ElemBase {
- ID id FAIL;
-
+ ID id FAIL;
+
};
// -------------------------------------------------------------------------------
struct MVert : ElemBase {
- float co[3] FAIL;
- float no[3] FAIL;
- char flag;
- int mat_nr WARN;
- int bweight;
+ float co[3] FAIL;
+ float no[3] FAIL;
+ char flag;
+ int mat_nr WARN;
+ int bweight;
};
// -------------------------------------------------------------------------------
@@ -159,68 +163,68 @@ struct MEdge : ElemBase {
// -------------------------------------------------------------------------------
struct MLoop : ElemBase {
- int v, e;
+ int v, e;
};
// -------------------------------------------------------------------------------
struct MLoopUV : ElemBase {
- float uv[2];
- int flag;
+ float uv[2];
+ int flag;
};
// -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase {
- char r, g, b, a;
+ char r, g, b, a;
};
// -------------------------------------------------------------------------------
struct MPoly : ElemBase {
- int loopstart;
- int totloop;
- short mat_nr;
- char flag;
+ int loopstart;
+ int totloop;
+ short mat_nr;
+ char flag;
};
// -------------------------------------------------------------------------------
struct MTexPoly : ElemBase {
- Image* tpage;
- char flag, transp;
- short mode, tile, pad;
+ Image* tpage;
+ char flag, transp;
+ short mode, tile, pad;
};
// -------------------------------------------------------------------------------
struct MCol : ElemBase {
- char r,g,b,a FAIL;
+ char r,g,b,a FAIL;
};
// -------------------------------------------------------------------------------
struct MFace : ElemBase {
- int v1,v2,v3,v4 FAIL;
- int mat_nr FAIL;
- char flag;
+ int v1,v2,v3,v4 FAIL;
+ int mat_nr FAIL;
+ char flag;
};
// -------------------------------------------------------------------------------
struct TFace : ElemBase {
- float uv[4][2] FAIL;
- int col[4] FAIL;
- char flag;
- short mode;
- short tile;
- short unwrap;
+ float uv[4][2] FAIL;
+ int col[4] FAIL;
+ char flag;
+ short mode;
+ short tile;
+ short unwrap;
};
// -------------------------------------------------------------------------------
struct MTFace : ElemBase {
- float uv[4][2] FAIL;
- char flag;
- short mode;
- short tile;
- short unwrap;
+ float uv[4][2] FAIL;
+ char flag;
+ short mode;
+ short tile;
+ short unwrap;
- // boost::shared_ptr<Image> tpage;
+ // std::shared_ptr<Image> tpage;
};
// -------------------------------------------------------------------------------
@@ -232,185 +236,267 @@ struct MDeformWeight : ElemBase {
// -------------------------------------------------------------------------------
struct MDeformVert : ElemBase {
- vector<MDeformWeight> dw WARN;
- int totweight;
+ vector<MDeformWeight> dw WARN;
+ int totweight;
};
// -------------------------------------------------------------------------------
-struct Material : ElemBase {
- ID id FAIL;
+#define MA_RAYMIRROR 0x40000
+#define MA_TRANSPARENCY 0x10000
+#define MA_RAYTRANSP 0x20000
+#define MA_ZTRANSP 0x00040
- float r,g,b WARN;
- float specr,specg,specb WARN;
- short har;
- float ambr,ambg,ambb WARN;
- float mirr,mirg,mirb;
- float emit WARN;
- float alpha WARN;
- float ref;
- float translucency;
- float roughness;
- float darkness;
- float refrac;
-
- boost::shared_ptr<Group> group;
-
- short diff_shader WARN;
- short spec_shader WARN;
-
- boost::shared_ptr<MTex> mtex[18];
+struct Material : ElemBase {
+ ID id FAIL;
+
+ float r,g,b WARN;
+ float specr,specg,specb WARN;
+ short har;
+ float ambr,ambg,ambb WARN;
+ float mirr,mirg,mirb;
+ float emit WARN;
+ float ray_mirror;
+ float alpha WARN;
+ float ref;
+ float translucency;
+ int mode;
+ float roughness;
+ float darkness;
+ float refrac;
+
+
+ float amb;
+ float ang;
+ float spectra;
+ float spec;
+ float zoffs;
+ float add;
+ float fresnel_mir;
+ float fresnel_mir_i;
+ float fresnel_tra;
+ float fresnel_tra_i;
+ float filter;
+ float tx_limit;
+ float tx_falloff;
+ float gloss_mir;
+ float gloss_tra;
+ float adapt_thresh_mir;
+ float adapt_thresh_tra;
+ float aniso_gloss_mir;
+ float dist_mir;
+ float hasize;
+ float flaresize;
+ float subsize;
+ float flareboost;
+ float strand_sta;
+ float strand_end;
+ float strand_ease;
+ float strand_surfnor;
+ float strand_min;
+ float strand_widthfade;
+ float sbias;
+ float lbias;
+ float shad_alpha;
+ float param;
+ float rms;
+ float rampfac_col;
+ float rampfac_spec;
+ float friction;
+ float fh;
+ float reflect;
+ float fhdist;
+ float xyfrict;
+ float sss_radius;
+ float sss_col;
+ float sss_error;
+ float sss_scale;
+ float sss_ior;
+ float sss_colfac;
+ float sss_texfac;
+ float sss_front;
+ float sss_back;
+
+ short material_type;
+ short flag;
+ short ray_depth;
+ short ray_depth_tra;
+ short samp_gloss_mir;
+ short samp_gloss_tra;
+ short fadeto_mir;
+ short shade_flag;
+ short flarec;
+ short starc;
+ short linec;
+ short ringc;
+ short pr_lamp;
+ short pr_texture;
+ short ml_flag;
+ short texco;
+ short mapto;
+ short ramp_show;
+ short pad3;
+ short dynamode;
+ short pad2;
+ short sss_flag;
+ short sss_preset;
+ short shadowonly_flag;
+ short index;
+ short vcol_alpha;
+ short pad4;
+
+ char seed1;
+ char seed2;
+
+ std::shared_ptr<Group> group;
+
+ short diff_shader WARN;
+ short spec_shader WARN;
+
+ std::shared_ptr<MTex> mtex[18];
};
// -------------------------------------------------------------------------------
struct Mesh : ElemBase {
- ID id FAIL;
+ ID id FAIL;
- int totface FAIL;
- int totedge FAIL;
- int totvert FAIL;
- int totloop;
- int totpoly;
+ int totface FAIL;
+ int totedge FAIL;
+ int totvert FAIL;
+ int totloop;
+ int totpoly;
- short subdiv;
- short subdivr;
- short subsurftype;
- short smoothresh;
+ short subdiv;
+ short subdivr;
+ short subsurftype;
+ short smoothresh;
- vector<MFace> mface FAIL;
- vector<MTFace> mtface;
- vector<TFace> tface;
- vector<MVert> mvert FAIL;
- vector<MEdge> medge WARN;
- vector<MLoop> mloop;
- vector<MLoopUV> mloopuv;
- vector<MLoopCol> mloopcol;
- vector<MPoly> mpoly;
- vector<MTexPoly> mtpoly;
- vector<MDeformVert> dvert;
- vector<MCol> mcol;
+ vector<MFace> mface FAIL;
+ vector<MTFace> mtface;
+ vector<TFace> tface;
+ vector<MVert> mvert FAIL;
+ vector<MEdge> medge WARN;
+ vector<MLoop> mloop;
+ vector<MLoopUV> mloopuv;
+ vector<MLoopCol> mloopcol;
+ vector<MPoly> mpoly;
+ vector<MTexPoly> mtpoly;
+ vector<MDeformVert> dvert;
+ vector<MCol> mcol;
- vector< boost::shared_ptr<Material> > mat FAIL;
+ vector< std::shared_ptr<Material> > mat FAIL;
};
// -------------------------------------------------------------------------------
struct Library : ElemBase {
- ID id FAIL;
-
- char name[240] WARN;
- char filename[240] FAIL;
- boost::shared_ptr<Library> parent WARN;
+ ID id FAIL;
+
+ char name[240] WARN;
+ char filename[240] FAIL;
+ std::shared_ptr<Library> parent WARN;
};
// -------------------------------------------------------------------------------
struct Camera : ElemBase {
- enum Type {
- Type_PERSP = 0
- ,Type_ORTHO = 1
- };
-
- ID id FAIL;
+ enum Type {
+ Type_PERSP = 0
+ ,Type_ORTHO = 1
+ };
- // struct AnimData *adt;
+ ID id FAIL;
- Type type,flag WARN;
- float angle WARN;
- //float passepartalpha, angle;
- //float clipsta, clipend;
- //float lens, ortho_scale, drawsize;
- //float shiftx, shifty;
-
- //float YF_dofdist, YF_aperture;
- //short YF_bkhtype, YF_bkhbias;
- //float YF_bkhrot;
+ Type type,flag WARN;
+ float lens WARN;
+ float sensor_x WARN;
+ float clipsta, clipend;
};
// -------------------------------------------------------------------------------
struct Lamp : ElemBase {
- enum FalloffType {
- FalloffType_Constant = 0x0
- ,FalloffType_InvLinear = 0x1
- ,FalloffType_InvSquare = 0x2
- //,FalloffType_Curve = 0x3
- //,FalloffType_Sliders = 0x4
- };
-
- enum Type {
- Type_Local = 0x0
- ,Type_Sun = 0x1
- ,Type_Spot = 0x2
- ,Type_Hemi = 0x3
- ,Type_Area = 0x4
- //,Type_YFPhoton = 0x5
- };
+ enum FalloffType {
+ FalloffType_Constant = 0x0
+ ,FalloffType_InvLinear = 0x1
+ ,FalloffType_InvSquare = 0x2
+ //,FalloffType_Curve = 0x3
+ //,FalloffType_Sliders = 0x4
+ };
+
+ enum Type {
+ Type_Local = 0x0
+ ,Type_Sun = 0x1
+ ,Type_Spot = 0x2
+ ,Type_Hemi = 0x3
+ ,Type_Area = 0x4
+ //,Type_YFPhoton = 0x5
+ };
ID id FAIL;
- //AnimData *adt;
-
+ //AnimData *adt;
+
Type type FAIL;
- short flags;
+ short flags;
//int mode;
-
+
short colormodel, totex;
float r,g,b,k WARN;
//float shdwr, shdwg, shdwb;
-
+
float energy, dist, spotsize, spotblend;
//float haint;
-
- float att1, att2;
+
+ float att1, att2;
//struct CurveMapping *curfalloff;
FalloffType falloff_type;
-
+
//float clipsta, clipend, shadspotsize;
//float bias, soft, compressthresh;
//short bufsize, samp, buffers, filtertype;
//char bufflag, buftype;
-
+
//short ray_samp, ray_sampy, ray_sampz;
//short ray_samp_type;
- //short area_shape;
- //float area_size, area_sizey, area_sizez;
- //float adapt_thresh;
- //short ray_samp_method;
-
- //short texact, shadhalostep;
-
- //short sun_effect_type;
- //short skyblendtype;
- //float horizon_brightness;
- //float spread;
- float sun_brightness;
- //float sun_size;
- //float backscattered_light;
- //float sun_intensity;
- //float atm_turbidity;
- //float atm_inscattering_factor;
- //float atm_extinction_factor;
- //float atm_distance_factor;
- //float skyblendfac;
- //float sky_exposure;
- //short sky_colorspace;
-
- // int YF_numphotons, YF_numsearch;
- // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
- // float YF_causticblur, YF_ltradius;
-
- // float YF_glowint, YF_glowofs;
+ short area_shape;
+ float area_size, area_sizey, area_sizez;
+ //float adapt_thresh;
+ //short ray_samp_method;
+
+ //short texact, shadhalostep;
+
+ //short sun_effect_type;
+ //short skyblendtype;
+ //float horizon_brightness;
+ //float spread;
+ float sun_brightness;
+ //float sun_size;
+ //float backscattered_light;
+ //float sun_intensity;
+ //float atm_turbidity;
+ //float atm_inscattering_factor;
+ //float atm_extinction_factor;
+ //float atm_distance_factor;
+ //float skyblendfac;
+ //float sky_exposure;
+ //short sky_colorspace;
+
+ // int YF_numphotons, YF_numsearch;
+ // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
+ // float YF_causticblur, YF_ltradius;
+
+ // float YF_glowint, YF_glowofs;
// short YF_glowtype, YF_pad2;
-
- //struct Ipo *ipo;
- //struct MTex *mtex[18];
+
+ //struct Ipo *ipo;
+ //struct MTex *mtex[18];
// short pr_texture;
-
+
//struct PreviewImage *preview;
};
// -------------------------------------------------------------------------------
struct ModifierData : ElemBase {
- enum ModifierType {
+ enum ModifierType {
eModifierType_None = 0,
eModifierType_Subsurf,
eModifierType_Lattice,
@@ -444,314 +530,314 @@ struct ModifierData : ElemBase {
eModifierType_Surface,
eModifierType_Smoke,
eModifierType_ShapeKey
- };
+ };
- boost::shared_ptr<ElemBase> next WARN;
- boost::shared_ptr<ElemBase> prev WARN;
+ std::shared_ptr<ElemBase> next WARN;
+ std::shared_ptr<ElemBase> prev WARN;
- int type, mode;
- char name[32];
+ int type, mode;
+ char name[32];
};
// -------------------------------------------------------------------------------
struct SubsurfModifierData : ElemBase {
- enum Type {
-
- TYPE_CatmullClarke = 0x0,
- TYPE_Simple = 0x1
- };
+ enum Type {
- enum Flags {
- // some omitted
- FLAGS_SubsurfUV =1<<3
- };
+ TYPE_CatmullClarke = 0x0,
+ TYPE_Simple = 0x1
+ };
- ModifierData modifier FAIL;
- short subdivType WARN;
- short levels FAIL;
- short renderLevels ;
- short flags;
+ enum Flags {
+ // some omitted
+ FLAGS_SubsurfUV =1<<3
+ };
+
+ ModifierData modifier FAIL;
+ short subdivType WARN;
+ short levels FAIL;
+ short renderLevels ;
+ short flags;
};
// -------------------------------------------------------------------------------
struct MirrorModifierData : ElemBase {
- enum Flags {
- Flags_CLIPPING =1<<0,
- Flags_MIRROR_U =1<<1,
- Flags_MIRROR_V =1<<2,
- Flags_AXIS_X =1<<3,
- Flags_AXIS_Y =1<<4,
- Flags_AXIS_Z =1<<5,
- Flags_VGROUP =1<<6
- };
+ enum Flags {
+ Flags_CLIPPING =1<<0,
+ Flags_MIRROR_U =1<<1,
+ Flags_MIRROR_V =1<<2,
+ Flags_AXIS_X =1<<3,
+ Flags_AXIS_Y =1<<4,
+ Flags_AXIS_Z =1<<5,
+ Flags_VGROUP =1<<6
+ };
- ModifierData modifier FAIL;
+ ModifierData modifier FAIL;
- short axis, flag;
- float tolerance;
- boost::shared_ptr<Object> mirror_ob;
+ short axis, flag;
+ float tolerance;
+ std::shared_ptr<Object> mirror_ob;
};
// -------------------------------------------------------------------------------
struct Object : ElemBase {
- ID id FAIL;
+ ID id FAIL;
+
+ enum Type {
+ Type_EMPTY = 0
+ ,Type_MESH = 1
+ ,Type_CURVE = 2
+ ,Type_SURF = 3
+ ,Type_FONT = 4
+ ,Type_MBALL = 5
- enum Type {
- Type_EMPTY = 0
- ,Type_MESH = 1
- ,Type_CURVE = 2
- ,Type_SURF = 3
- ,Type_FONT = 4
- ,Type_MBALL = 5
+ ,Type_LAMP = 10
+ ,Type_CAMERA = 11
- ,Type_LAMP = 10
- ,Type_CAMERA = 11
+ ,Type_WAVE = 21
+ ,Type_LATTICE = 22
+ };
- ,Type_WAVE = 21
- ,Type_LATTICE = 22
- };
+ Type type FAIL;
+ float obmat[4][4] WARN;
+ float parentinv[4][4] WARN;
+ char parsubstr[32] WARN;
- Type type FAIL;
- float obmat[4][4] WARN;
- float parentinv[4][4] WARN;
- char parsubstr[32] WARN;
-
- Object* parent WARN;
- boost::shared_ptr<Object> track WARN;
+ Object* parent WARN;
+ std::shared_ptr<Object> track WARN;
- boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
- boost::shared_ptr<Group> dup_group WARN;
- boost::shared_ptr<ElemBase> data FAIL;
+ std::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
+ std::shared_ptr<Group> dup_group WARN;
+ std::shared_ptr<ElemBase> data FAIL;
- ListBase modifiers;
+ ListBase modifiers;
};
// -------------------------------------------------------------------------------
struct Base : ElemBase {
- Base* prev WARN;
- boost::shared_ptr<Base> next WARN;
- boost::shared_ptr<Object> object WARN;
+ Base* prev WARN;
+ std::shared_ptr<Base> next WARN;
+ std::shared_ptr<Object> object WARN;
};
// -------------------------------------------------------------------------------
struct Scene : ElemBase {
- ID id FAIL;
+ ID id FAIL;
- boost::shared_ptr<Object> camera WARN;
- boost::shared_ptr<World> world WARN;
- boost::shared_ptr<Base> basact WARN;
+ std::shared_ptr<Object> camera WARN;
+ std::shared_ptr<World> world WARN;
+ std::shared_ptr<Base> basact WARN;
- ListBase base;
+ ListBase base;
};
// -------------------------------------------------------------------------------
struct Image : ElemBase {
- ID id FAIL;
+ ID id FAIL;
- char name[240] WARN;
+ char name[240] WARN;
- //struct anim *anim;
+ //struct anim *anim;
- short ok, flag;
- short source, type, pad, pad1;
- int lastframe;
+ short ok, flag;
+ short source, type, pad, pad1;
+ int lastframe;
- short tpageflag, totbind;
- short xrep, yrep;
- short twsta, twend;
- //unsigned int bindcode;
- //unsigned int *repbind;
+ short tpageflag, totbind;
+ short xrep, yrep;
+ short twsta, twend;
+ //unsigned int bindcode;
+ //unsigned int *repbind;
- boost::shared_ptr<PackedFile> packedfile;
- //struct PreviewImage * preview;
+ std::shared_ptr<PackedFile> packedfile;
+ //struct PreviewImage * preview;
- float lastupdate;
- int lastused;
- short animspeed;
+ float lastupdate;
+ int lastused;
+ short animspeed;
- short gen_x, gen_y, gen_type;
+ short gen_x, gen_y, gen_type;
};
// -------------------------------------------------------------------------------
struct Tex : ElemBase {
- // actually, the only texture type we support is Type_IMAGE
- enum Type {
- Type_CLOUDS = 1
- ,Type_WOOD = 2
- ,Type_MARBLE = 3
- ,Type_MAGIC = 4
- ,Type_BLEND = 5
- ,Type_STUCCI = 6
- ,Type_NOISE = 7
- ,Type_IMAGE = 8
- ,Type_PLUGIN = 9
- ,Type_ENVMAP = 10
- ,Type_MUSGRAVE = 11
- ,Type_VORONOI = 12
- ,Type_DISTNOISE = 13
- ,Type_POINTDENSITY = 14
- ,Type_VOXELDATA = 15
- };
-
- enum ImageFlags {
- ImageFlags_INTERPOL = 1
- ,ImageFlags_USEALPHA = 2
- ,ImageFlags_MIPMAP = 4
- ,ImageFlags_IMAROT = 16
- ,ImageFlags_CALCALPHA = 32
- ,ImageFlags_NORMALMAP = 2048
- ,ImageFlags_GAUSS_MIP = 4096
- ,ImageFlags_FILTER_MIN = 8192
- ,ImageFlags_DERIVATIVEMAP = 16384
- };
-
- ID id FAIL;
- // AnimData *adt;
-
- //float noisesize, turbul;
- //float bright, contrast, rfac, gfac, bfac;
- //float filtersize;
-
- //float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
- //float dist_amount, ns_outscale;
-
- //float vn_w1;
- //float vn_w2;
- //float vn_w3;
- //float vn_w4;
- //float vn_mexp;
- //short vn_distm, vn_coltype;
-
- //short noisedepth, noisetype;
- //short noisebasis, noisebasis2;
-
- //short flag;
- ImageFlags imaflag;
- Type type FAIL;
- //short stype;
-
- //float cropxmin, cropymin, cropxmax, cropymax;
- //int texfilter;
- //int afmax;
- //short xrepeat, yrepeat;
- //short extend;
-
- //short fie_ima;
- //int len;
- //int frames, offset, sfra;
-
- //float checkerdist, nabla;
- //float norfac;
-
- //ImageUser iuser;
-
- //bNodeTree *nodetree;
- //Ipo *ipo;
- boost::shared_ptr<Image> ima WARN;
- //PluginTex *plugin;
- //ColorBand *coba;
- //EnvMap *env;
- //PreviewImage * preview;
- //PointDensity *pd;
- //VoxelData *vd;
-
- //char use_nodes;
+ // actually, the only texture type we support is Type_IMAGE
+ enum Type {
+ Type_CLOUDS = 1
+ ,Type_WOOD = 2
+ ,Type_MARBLE = 3
+ ,Type_MAGIC = 4
+ ,Type_BLEND = 5
+ ,Type_STUCCI = 6
+ ,Type_NOISE = 7
+ ,Type_IMAGE = 8
+ ,Type_PLUGIN = 9
+ ,Type_ENVMAP = 10
+ ,Type_MUSGRAVE = 11
+ ,Type_VORONOI = 12
+ ,Type_DISTNOISE = 13
+ ,Type_POINTDENSITY = 14
+ ,Type_VOXELDATA = 15
+ };
+
+ enum ImageFlags {
+ ImageFlags_INTERPOL = 1
+ ,ImageFlags_USEALPHA = 2
+ ,ImageFlags_MIPMAP = 4
+ ,ImageFlags_IMAROT = 16
+ ,ImageFlags_CALCALPHA = 32
+ ,ImageFlags_NORMALMAP = 2048
+ ,ImageFlags_GAUSS_MIP = 4096
+ ,ImageFlags_FILTER_MIN = 8192
+ ,ImageFlags_DERIVATIVEMAP = 16384
+ };
+
+ ID id FAIL;
+ // AnimData *adt;
+
+ //float noisesize, turbul;
+ //float bright, contrast, rfac, gfac, bfac;
+ //float filtersize;
+
+ //float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
+ //float dist_amount, ns_outscale;
+
+ //float vn_w1;
+ //float vn_w2;
+ //float vn_w3;
+ //float vn_w4;
+ //float vn_mexp;
+ //short vn_distm, vn_coltype;
+
+ //short noisedepth, noisetype;
+ //short noisebasis, noisebasis2;
+
+ //short flag;
+ ImageFlags imaflag;
+ Type type FAIL;
+ //short stype;
+
+ //float cropxmin, cropymin, cropxmax, cropymax;
+ //int texfilter;
+ //int afmax;
+ //short xrepeat, yrepeat;
+ //short extend;
+
+ //short fie_ima;
+ //int len;
+ //int frames, offset, sfra;
+
+ //float checkerdist, nabla;
+ //float norfac;
+
+ //ImageUser iuser;
+
+ //bNodeTree *nodetree;
+ //Ipo *ipo;
+ std::shared_ptr<Image> ima WARN;
+ //PluginTex *plugin;
+ //ColorBand *coba;
+ //EnvMap *env;
+ //PreviewImage * preview;
+ //PointDensity *pd;
+ //VoxelData *vd;
+
+ //char use_nodes;
};
// -------------------------------------------------------------------------------
struct MTex : ElemBase {
- enum Projection {
- Proj_N = 0
- ,Proj_X = 1
- ,Proj_Y = 2
- ,Proj_Z = 3
- };
-
- enum Flag {
- Flag_RGBTOINT = 0x1
- ,Flag_STENCIL = 0x2
- ,Flag_NEGATIVE = 0x4
- ,Flag_ALPHAMIX = 0x8
- ,Flag_VIEWSPACE = 0x10
- };
-
- enum BlendType {
- BlendType_BLEND = 0
- ,BlendType_MUL = 1
- ,BlendType_ADD = 2
- ,BlendType_SUB = 3
- ,BlendType_DIV = 4
- ,BlendType_DARK = 5
- ,BlendType_DIFF = 6
- ,BlendType_LIGHT = 7
- ,BlendType_SCREEN = 8
- ,BlendType_OVERLAY = 9
- ,BlendType_BLEND_HUE = 10
- ,BlendType_BLEND_SAT = 11
- ,BlendType_BLEND_VAL = 12
- ,BlendType_BLEND_COLOR = 13
- };
-
- enum MapType {
- MapType_COL = 1
- ,MapType_NORM = 2
- ,MapType_COLSPEC = 4
- ,MapType_COLMIR = 8
- ,MapType_REF = 16
- ,MapType_SPEC = 32
- ,MapType_EMIT = 64
- ,MapType_ALPHA = 128
- ,MapType_HAR = 256
- ,MapType_RAYMIRR = 512
- ,MapType_TRANSLU = 1024
- ,MapType_AMB = 2048
- ,MapType_DISPLACE = 4096
- ,MapType_WARP = 8192
- };
-
- // short texco, maptoneg;
- MapType mapto;
-
- BlendType blendtype;
- boost::shared_ptr<Object> object;
- boost::shared_ptr<Tex> tex;
- char uvname[32];
-
- Projection projx,projy,projz;
- char mapping;
- float ofs[3], size[3], rot;
-
- int texflag;
- short colormodel, pmapto, pmaptoneg;
- //short normapspace, which_output;
- //char brush_map_mode;
- float r,g,b,k WARN;
- //float def_var, rt;
-
- //float colfac, varfac;
-
- float norfac;
- //float dispfac, warpfac;
- float colspecfac, mirrfac, alphafac;
- float difffac, specfac, emitfac, hardfac;
- //float raymirrfac, translfac, ambfac;
- //float colemitfac, colreflfac, coltransfac;
- //float densfac, scatterfac, reflfac;
-
- //float timefac, lengthfac, clumpfac;
- //float kinkfac, roughfac, padensfac;
- //float lifefac, sizefac, ivelfac, pvelfac;
- //float shadowfac;
- //float zenupfac, zendownfac, blendfac;
-};
-
-
- }
+ enum Projection {
+ Proj_N = 0
+ ,Proj_X = 1
+ ,Proj_Y = 2
+ ,Proj_Z = 3
+ };
+
+ enum Flag {
+ Flag_RGBTOINT = 0x1
+ ,Flag_STENCIL = 0x2
+ ,Flag_NEGATIVE = 0x4
+ ,Flag_ALPHAMIX = 0x8
+ ,Flag_VIEWSPACE = 0x10
+ };
+
+ enum BlendType {
+ BlendType_BLEND = 0
+ ,BlendType_MUL = 1
+ ,BlendType_ADD = 2
+ ,BlendType_SUB = 3
+ ,BlendType_DIV = 4
+ ,BlendType_DARK = 5
+ ,BlendType_DIFF = 6
+ ,BlendType_LIGHT = 7
+ ,BlendType_SCREEN = 8
+ ,BlendType_OVERLAY = 9
+ ,BlendType_BLEND_HUE = 10
+ ,BlendType_BLEND_SAT = 11
+ ,BlendType_BLEND_VAL = 12
+ ,BlendType_BLEND_COLOR = 13
+ };
+
+ enum MapType {
+ MapType_COL = 1
+ ,MapType_NORM = 2
+ ,MapType_COLSPEC = 4
+ ,MapType_COLMIR = 8
+ ,MapType_REF = 16
+ ,MapType_SPEC = 32
+ ,MapType_EMIT = 64
+ ,MapType_ALPHA = 128
+ ,MapType_HAR = 256
+ ,MapType_RAYMIRR = 512
+ ,MapType_TRANSLU = 1024
+ ,MapType_AMB = 2048
+ ,MapType_DISPLACE = 4096
+ ,MapType_WARP = 8192
+ };
+
+ // short texco, maptoneg;
+ MapType mapto;
+
+ BlendType blendtype;
+ std::shared_ptr<Object> object;
+ std::shared_ptr<Tex> tex;
+ char uvname[32];
+
+ Projection projx,projy,projz;
+ char mapping;
+ float ofs[3], size[3], rot;
+
+ int texflag;
+ short colormodel, pmapto, pmaptoneg;
+ //short normapspace, which_output;
+ //char brush_map_mode;
+ float r,g,b,k WARN;
+ //float def_var, rt;
+
+ //float colfac, varfac;
+
+ float norfac;
+ //float dispfac, warpfac;
+ float colspecfac, mirrfac, alphafac;
+ float difffac, specfac, emitfac, hardfac;
+ //float raymirrfac, translfac, ambfac;
+ //float colemitfac, colreflfac, coltransfac;
+ //float densfac, scatterfac, reflfac;
+
+ //float timefac, lengthfac, clumpfac;
+ //float kinkfac, roughfac, padensfac;
+ //float lifefac, sizefac, ivelfac, pvelfac;
+ //float shadowfac;
+ //float zenupfac, zendownfac, blendfac;
+};
+
+
+ }
}
#endif
diff --git a/src/3rdparty/assimp/code/BlenderSceneGen.h b/src/3rdparty/assimp/code/BlenderSceneGen.h
index b8e0b6b22..92c727eb2 100644
--- a/src/3rdparty/assimp/code/BlenderSceneGen.h
+++ b/src/3rdparty/assimp/code/BlenderSceneGen.h
@@ -2,11 +2,11 @@
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
-Copyright (c) 2006-2010, ASSIMP Development Team
+Copyright (c) 2006-2016, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,9 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BLEND_SCENEGEN_H
#define INCLUDED_AI_BLEND_SCENEGEN_H
-namespace Assimp {
- namespace Blender {
+#include "BlenderDNA.h"
+#include "BlenderScene.h"
+namespace Assimp {
+namespace Blender {
template <> void Structure :: Convert<Object> (
Object& dest,
@@ -247,7 +249,7 @@ template <> void Structure :: Convert<Image> (
;
- }
+ }
}
#endif
diff --git a/src/3rdparty/assimp/code/BlenderTessellator.cpp b/src/3rdparty/assimp/code/BlenderTessellator.cpp
index 8a7e274a3..bea00e228 100644
--- a/src/3rdparty/assimp/code/BlenderTessellator.cpp
+++ b/src/3rdparty/assimp/code/BlenderTessellator.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2013, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief A simple tessellation wrapper
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
@@ -51,13 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderBMesh.h"
#include "BlenderTessellator.h"
+#include <stddef.h>
+
static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
namspace Assimp
{
- template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
+ template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
}
using namespace Assimp;
@@ -69,7 +70,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------
BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
- converter( &converter )
+ converter( &converter )
{
}
@@ -81,167 +82,167 @@ BlenderTessellatorGL::~BlenderTessellatorGL( )
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{
- AssertVertexCount( vertexCount );
+ AssertVertexCount( vertexCount );
- std::vector< VertexGL > polyLoopGL;
- GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
+ std::vector< VertexGL > polyLoopGL;
+ GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
- TessDataGL tessData;
- Tesssellate( polyLoopGL, tessData );
+ TessDataGL tessData;
+ Tesssellate( polyLoopGL, tessData );
- TriangulateDrawCalls( tessData );
+ TriangulateDrawCalls( tessData );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
{
- if ( vertexCount <= 4 )
- {
- ThrowException( "Expected more than 4 vertices for tessellation" );
- }
+ if ( vertexCount <= 4 )
+ {
+ ThrowException( "Expected more than 4 vertices for tessellation" );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{
- for ( int i = 0; i < vertexCount; ++i )
- {
- const MLoop& loopItem = polyLoop[ i ];
- const MVert& vertex = vertices[ loopItem.v ];
- polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
- }
+ for ( int i = 0; i < vertexCount; ++i )
+ {
+ const MLoop& loopItem = polyLoop[ i ];
+ const MVert& vertex = vertices[ loopItem.v ];
+ polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
{
- GLUtesselator* tessellator = gluNewTess( );
- gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
- gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
- gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
- gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
- gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
- gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
- gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
+ GLUtesselator* tessellator = gluNewTess( );
+ gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
+ gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
+ gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
+ gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
+ gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
+ gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
+ gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
- gluTessBeginPolygon( tessellator, &tessData );
- gluTessBeginContour( tessellator );
+ gluTessBeginPolygon( tessellator, &tessData );
+ gluTessBeginContour( tessellator );
- for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
- {
- gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
- }
+ for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
+ {
+ gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
+ }
- gluTessEndContour( tessellator );
- gluTessEndPolygon( tessellator );
+ gluTessEndContour( tessellator );
+ gluTessEndPolygon( tessellator );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
{
- // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
- // need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
- // GLU tessellate changes or tristrips and fans are wanted.
- // See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
- for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
- {
- const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
+ // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
+ // need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
+ // GLU tessellate changes or tri-strips and fans are wanted.
+ // See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
+ for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
+ {
+ const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
- if ( drawCallGL.drawMode == GL_TRIANGLES )
- {
- MakeFacesFromTris( vertices, drawCallGL.vertexCount );
- }
- else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
- {
- MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
- }
- else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
- {
- MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
- }
- }
+ if ( drawCallGL.drawMode == GL_TRIANGLES )
+ {
+ MakeFacesFromTris( vertices, drawCallGL.vertexCount );
+ }
+ else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
+ {
+ MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
+ }
+ else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
+ {
+ MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
{
- int triangleCount = vertexCount / 3;
- for ( int i = 0; i < triangleCount; ++i )
- {
- int vertexBase = i * 3;
- converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
- }
+ const int triangleCount = vertexCount / 3;
+ for ( int i = 0; i < triangleCount; ++i )
+ {
+ int vertexBase = i * 3;
+ converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
{
- int triangleCount = vertexCount - 2;
- for ( int i = 0; i < triangleCount; ++i )
- {
- int vertexBase = i;
- converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
- }
+ const int triangleCount = vertexCount - 2;
+ for ( int i = 0; i < triangleCount; ++i )
+ {
+ int vertexBase = i;
+ converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
{
- int triangleCount = vertexCount - 2;
- for ( int i = 0; i < triangleCount; ++i )
- {
- int vertexBase = i;
- converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
- }
+ const int triangleCount = vertexCount - 2;
+ for ( int i = 0; i < triangleCount; ++i )
+ {
+ int vertexBase = i;
+ converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
{
- TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
- tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
+ TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
+ tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEnd( void* )
{
- // Do nothing
+ // Do nothing
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
{
- TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
+ TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
- const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
- if ( vertex.magic != BLEND_TESS_MAGIC )
- {
- ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
- }
- tessData.vertices.push_back( vertex );
- if ( tessData.drawCalls.size( ) == 0 )
- {
- ThrowException( "\"Vertex\" callback received before \"Begin\"" );
- }
- ++( tessData.drawCalls.back( ).vertexCount );
+ const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
+ if ( vertex.magic != BLEND_TESS_MAGIC )
+ {
+ ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
+ }
+ tessData.vertices.push_back( vertex );
+ if ( tessData.drawCalls.size( ) == 0 )
+ {
+ ThrowException( "\"Vertex\" callback received before \"Begin\"" );
+ }
+ ++( tessData.drawCalls.back( ).vertexCount );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
{
- ThrowException( "Intersected polygon loops are not yet supported" );
+ ThrowException( "Intersected polygon loops are not yet supported" );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
{
- // Do nothing
+ // Do nothing
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
{
- ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
+ ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
}
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@@ -250,7 +251,7 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
namespace Assimp
{
- template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
+ template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
}
using namespace Assimp;
@@ -258,7 +259,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------
BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
- converter( &converter )
+ converter( &converter )
{
}
@@ -270,178 +271,173 @@ BlenderTessellatorP2T::~BlenderTessellatorP2T( )
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{
- AssertVertexCount( vertexCount );
+ AssertVertexCount( vertexCount );
- // NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
- // There may be some triangulation artifacts if they are wildly different.
+ // NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
+ // There may be some triangulation artifacts if they are wildly different.
- std::vector< PointP2T > points;
- Copy3DVertices( polyLoop, vertexCount, vertices, points );
+ std::vector< PointP2T > points;
+ Copy3DVertices( polyLoop, vertexCount, vertices, points );
- PlaneP2T plane = FindLLSQPlane( points );
+ PlaneP2T plane = FindLLSQPlane( points );
- aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
+ aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
- TransformAndFlattenVectices( transform, points );
+ TransformAndFlattenVectices( transform, points );
- std::vector< p2t::Point* > pointRefs;
- ReferencePoints( points, pointRefs );
+ std::vector< p2t::Point* > pointRefs;
+ ReferencePoints( points, pointRefs );
- p2t::CDT cdt( pointRefs );
+ p2t::CDT cdt( pointRefs );
- cdt.Triangulate( );
- std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
+ cdt.Triangulate( );
+ std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
- MakeFacesFromTriangles( triangles );
+ MakeFacesFromTriangles( triangles );
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
{
- if ( vertexCount <= 4 )
- {
- ThrowException( "Expected more than 4 vertices for tessellation" );
- }
+ if ( vertexCount <= 4 )
+ {
+ ThrowException( "Expected more than 4 vertices for tessellation" );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
{
- points.resize( vertexCount );
- for ( int i = 0; i < vertexCount; ++i )
- {
- const MLoop& loop = polyLoop[ i ];
- const MVert& vert = vertices[ loop.v ];
+ points.resize( vertexCount );
+ for ( int i = 0; i < vertexCount; ++i )
+ {
+ const MLoop& loop = polyLoop[ i ];
+ const MVert& vert = vertices[ loop.v ];
- PointP2T& point = points[ i ];
- point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
- point.index = loop.v;
- point.magic = BLEND_TESS_MAGIC;
- }
+ PointP2T& point = points[ i ];
+ point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
+ point.index = loop.v;
+ point.magic = BLEND_TESS_MAGIC;
+ }
}
// ------------------------------------------------------------------------------------------------
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
{
- aiVector3D sideA( 1.0f, 0.0f, 0.0f );
- if ( std::fabs( plane.normal * sideA ) > 0.999f )
- {
- sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
- }
-
- aiVector3D sideB( plane.normal ^ sideA );
- sideB.Normalize( );
- sideA = sideB ^ plane.normal;
-
- aiMatrix4x4 result;
- result.a1 = sideA.x;
- result.a2 = sideA.y;
- result.a3 = sideA.z;
- result.b1 = sideB.x;
- result.b2 = sideB.y;
- result.b3 = sideB.z;
- result.c1 = plane.normal.x;
- result.c2 = plane.normal.y;
- result.c3 = plane.normal.z;
- result.a4 = plane.centre.x;
- result.b4 = plane.centre.y;
- result.c4 = plane.centre.z;
- result.Inverse( );
-
- return result;
+ aiVector3D sideA( 1.0f, 0.0f, 0.0f );
+ if ( std::fabs( plane.normal * sideA ) > 0.999f )
+ {
+ sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
+ }
+
+ aiVector3D sideB( plane.normal ^ sideA );
+ sideB.Normalize( );
+ sideA = sideB ^ plane.normal;
+
+ aiMatrix4x4 result;
+ result.a1 = sideA.x;
+ result.a2 = sideA.y;
+ result.a3 = sideA.z;
+ result.b1 = sideB.x;
+ result.b2 = sideB.y;
+ result.b3 = sideB.z;
+ result.c1 = plane.normal.x;
+ result.c2 = plane.normal.y;
+ result.c3 = plane.normal.z;
+ result.a4 = plane.centre.x;
+ result.b4 = plane.centre.y;
+ result.c4 = plane.centre.z;
+ result.Inverse( );
+
+ return result;
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
{
- for ( unsigned int i = 0; i < vertices.size( ); ++i )
- {
- PointP2T& point = vertices[ i ];
- point.point3D = transform * point.point3D;
- point.point2D.set( point.point3D.y, point.point3D.z );
- }
+ for ( size_t i = 0; i < vertices.size( ); ++i )
+ {
+ PointP2T& point = vertices[ i ];
+ point.point3D = transform * point.point3D;
+ point.point2D.set( point.point3D.y, point.point3D.z );
+ }
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
{
- pointRefs.resize( points.size( ) );
- for ( unsigned int i = 0; i < points.size( ); ++i )
- {
- pointRefs[ i ] = &points[ i ].point2D;
- }
+ pointRefs.resize( points.size( ) );
+ for ( size_t i = 0; i < points.size( ); ++i )
+ {
+ pointRefs[ i ] = &points[ i ].point2D;
+ }
}
// ------------------------------------------------------------------------------------------------
-// Yes this is filthy... but we have no choice
-#define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \
- reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
- static_cast<uint8_t*>(NULL) ) )
-
inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
{
- unsigned int pointOffset = OffsetOf( PointP2T, point2D );
- PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
- if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
- {
- ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
- }
- return pointStruct;
+ unsigned int pointOffset = offsetof( PointP2T, point2D );
+ PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
+ if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
+ {
+ ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
+ }
+ return pointStruct;
}
// ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
{
- for ( unsigned int i = 0; i < triangles.size( ); ++i )
- {
- p2t::Triangle& Triangle = *triangles[ i ];
+ for ( size_t i = 0; i < triangles.size( ); ++i )
+ {
+ p2t::Triangle& Triangle = *triangles[ i ];
- PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
- PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
- PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
+ PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
+ PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
+ PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
- converter->AddFace( pointA.index, pointB.index, pointC.index );
- }
+ converter->AddFace( pointA.index, pointB.index, pointC.index );
+ }
}
// ------------------------------------------------------------------------------------------------
inline float p2tMax( float a, float b )
{
- return a > b ? a : b;
+ return a > b ? a : b;
}
// ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
{
- float result = 0.0f;
+ float result = 0.0f;
- for ( int x = 0; x < 3; ++x )
- {
- for ( int y = 0; y < 3; ++y )
- {
- result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
- }
- }
+ for ( size_t x = 0; x < 3; ++x )
+ {
+ for ( size_t y = 0; y < 3; ++y )
+ {
+ result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
+ }
+ }
- return result;
+ return result;
}
// ------------------------------------------------------------------------------------------------
-// Aparently Assimp doesn't have matrix scaling
+// Apparently Assimp doesn't have matrix scaling
aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
{
- aiMatrix3x3 result;
+ aiMatrix3x3 result;
- for ( int x = 0; x < 3; ++x )
- {
- for ( int y = 0; y < 3; ++y )
- {
- result[ x ][ y ] = mtx[ x ][ y ] * scale;
- }
- }
+ for ( size_t x = 0; x < 3; ++x )
+ {
+ for ( size_t y = 0; y < 3; ++y )
+ {
+ result[ x ][ y ] = mtx[ x ][ y ] * scale;
+ }
+ }
- return result;
+ return result;
}
@@ -449,70 +445,70 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
{
- float scale = FindLargestMatrixElem( mtx );
- aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
- mc = mc * mc * mc;
-
- aiVector3D v( 1.0f );
- aiVector3D lastV = v;
- for ( int i = 0; i < 100; ++i )
- {
- v = mc * v;
- v.Normalize( );
- if ( ( v - lastV ).SquareLength( ) < 1e-16f )
- {
- break;
- }
- lastV = v;
- }
- return v;
-}
+ const float scale = FindLargestMatrixElem( mtx );
+ aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
+ mc = mc * mc * mc;
+
+ aiVector3D v( 1.0f );
+ aiVector3D lastV = v;
+ for ( int i = 0; i < 100; ++i )
+ {
+ v = mc * v;
+ v.Normalize( );
+ if ( ( v - lastV ).SquareLength( ) < 1e-16f )
+ {
+ break;
+ }
+ lastV = v;
+ }
+ return v;
+}
// ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
{
- PlaneP2T result;
-
- aiVector3D sum( 0.0f );
- for ( unsigned int i = 0; i < points.size( ); ++i )
- {
- sum += points[ i ].point3D;
- }
- result.centre = sum * ( 1.0f / points.size( ) );
-
- float sumXX = 0.0f;
- float sumXY = 0.0f;
- float sumXZ = 0.0f;
- float sumYY = 0.0f;
- float sumYZ = 0.0f;
- float sumZZ = 0.0f;
- for ( unsigned int i = 0; i < points.size( ); ++i )
- {
- aiVector3D offset = points[ i ].point3D - result.centre;
- sumXX += offset.x * offset.x;
- sumXY += offset.x * offset.y;
- sumXZ += offset.x * offset.z;
- sumYY += offset.y * offset.y;
- sumYZ += offset.y * offset.z;
- sumZZ += offset.z * offset.z;
- }
-
- aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
-
- float det = mtx.Determinant( );
- if ( det == 0.0f )
- {
- result.normal = aiVector3D( 0.0f );
- }
- else
- {
- aiMatrix3x3 invMtx = mtx;
- invMtx.Inverse( );
- result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
- }
-
- return result;
+ PlaneP2T result;
+
+ aiVector3D sum( 0.0f );
+ for ( size_t i = 0; i < points.size( ); ++i )
+ {
+ sum += points[ i ].point3D;
+ }
+ result.centre = sum * ( 1.0f / points.size( ) );
+
+ float sumXX = 0.0f;
+ float sumXY = 0.0f;
+ float sumXZ = 0.0f;
+ float sumYY = 0.0f;
+ float sumYZ = 0.0f;
+ float sumZZ = 0.0f;
+ for ( size_t i = 0; i < points.size( ); ++i )
+ {
+ aiVector3D offset = points[ i ].point3D - result.centre;
+ sumXX += offset.x * offset.x;
+ sumXY += offset.x * offset.y;
+ sumXZ += offset.x * offset.z;
+ sumYY += offset.y * offset.y;
+ sumYZ += offset.y * offset.z;
+ sumZZ += offset.z * offset.z;
+ }
+
+ aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
+
+ const float det = mtx.Determinant( );
+ if ( det == 0.0f )
+ {
+ result.normal = aiVector3D( 0.0f );
+ }
+ else
+ {
+ aiMatrix3x3 invMtx = mtx;
+ invMtx.Inverse( );
+ result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
+ }
+
+ return result;
}
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
diff --git a/src/3rdparty/assimp/code/BlenderTessellator.h b/src/3rdparty/assimp/code/BlenderTessellator.h
index 0d85e404b..530bd2c3e 100644
--- a/src/3rdparty/assimp/code/BlenderTessellator.h
+++ b/src/3rdparty/assimp/code/BlenderTessellator.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2013, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,15 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Use these to toggle between GLU Tessellate or poly2tri
// Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
-// assimp needs to be linked against GLU, which is currently not yet
+// assimp needs to be linked against GLU, which is currently not yet
// made configurable in CMake and potentially not wanted by most users
// as it requires a Gl environment.
#ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
-# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
+# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
#endif
#ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
-# define ASSIMP_BLEND_WITH_POLY_2_TRI 1
+# define ASSIMP_BLEND_WITH_POLY_2_TRI 1
#endif
#include "LogAux.h"
@@ -68,74 +68,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
- class BlenderBMeshConverter;
-
- // 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;
- }
-
- // BlenderScene.h
- namespace Blender
- {
- struct MLoop;
- struct MVert;
-
- struct VertexGL
- {
- GLdouble X;
- GLdouble Y;
- GLdouble Z;
- int index;
- int magic;
-
- VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
- };
-
- struct DrawCallGL
- {
- GLenum drawMode;
- int baseVertex;
- int vertexCount;
-
- DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
- };
-
- struct TessDataGL
- {
- std::vector< DrawCallGL > drawCalls;
- std::vector< VertexGL > vertices;
- };
- }
-
- class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
- {
- public:
- BlenderTessellatorGL( BlenderBMeshConverter& converter );
- ~BlenderTessellatorGL( );
-
- void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
-
- private:
- void AssertVertexCount( int vertexCount );
- void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
- void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
- void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
- void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
- void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
- void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
-
- static void TessellateBegin( GLenum drawModeGL, void* userData );
- static void TessellateEnd( void* userData );
- static void TessellateVertex( const void* vtxData, void* userData );
- static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
- static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
- static void TessellateError( GLenum errorCode, void* userData );
-
- BlenderBMeshConverter* converter;
- };
+ class BlenderBMeshConverter;
+
+ // 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;
+ }
+
+ // BlenderScene.h
+ namespace Blender
+ {
+ struct MLoop;
+ struct MVert;
+
+ struct VertexGL
+ {
+ GLdouble X;
+ GLdouble Y;
+ GLdouble Z;
+ int index;
+ int magic;
+
+ VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
+ };
+
+ struct DrawCallGL
+ {
+ GLenum drawMode;
+ int baseVertex;
+ int vertexCount;
+
+ DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
+ };
+
+ struct TessDataGL
+ {
+ std::vector< DrawCallGL > drawCalls;
+ std::vector< VertexGL > vertices;
+ };
+ }
+
+ class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
+ {
+ public:
+ BlenderTessellatorGL( BlenderBMeshConverter& converter );
+ ~BlenderTessellatorGL( );
+
+ void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+
+ private:
+ void AssertVertexCount( int vertexCount );
+ void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+ void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
+ void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
+ void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
+ void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
+ void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
+
+ static void TessellateBegin( GLenum drawModeGL, void* userData );
+ static void TessellateEnd( void* userData );
+ static void TessellateVertex( const void* vtxData, void* userData );
+ static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
+ static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
+ static void TessellateError( GLenum errorCode, void* userData );
+
+ BlenderBMeshConverter* converter;
+ };
} // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@@ -146,61 +146,61 @@ namespace Assimp
namespace Assimp
{
- class BlenderBMeshConverter;
-
- // 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;
- }
-
- // BlenderScene.h
- namespace Blender
- {
- struct MLoop;
- struct MVert;
-
- struct PointP2T
- {
- aiVector3D point3D;
- p2t::Point point2D;
- int magic;
- int index;
- };
-
- struct PlaneP2T
- {
- aiVector3D centre;
- aiVector3D normal;
- };
- }
-
- class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
- {
- public:
- BlenderTessellatorP2T( BlenderBMeshConverter& converter );
- ~BlenderTessellatorP2T( );
-
- void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
-
- private:
- void AssertVertexCount( int vertexCount );
- void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
- aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
- void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
- void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
- inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
- void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
-
- // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
- float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
- aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
- aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
- Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
-
- BlenderBMeshConverter* converter;
- };
+ class BlenderBMeshConverter;
+
+ // 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;
+ }
+
+ // BlenderScene.h
+ namespace Blender
+ {
+ struct MLoop;
+ struct MVert;
+
+ struct PointP2T
+ {
+ aiVector3D point3D;
+ p2t::Point point2D;
+ int magic;
+ int index;
+ };
+
+ struct PlaneP2T
+ {
+ aiVector3D centre;
+ aiVector3D normal;
+ };
+ }
+
+ class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
+ {
+ public:
+ BlenderTessellatorP2T( BlenderBMeshConverter& converter );
+ ~BlenderTessellatorP2T( );
+
+ void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+
+ private:
+ void AssertVertexCount( int vertexCount );
+ void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
+ aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
+ void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
+ void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
+ inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
+ void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
+
+ // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
+ float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
+ aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
+ aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
+ Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
+
+ BlenderBMeshConverter* converter;
+ };
} // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
diff --git a/src/3rdparty/assimp/code/BlobIOSystem.h b/src/3rdparty/assimp/code/BlobIOSystem.h
index 655768c33..6cd014254 100644
--- a/src/3rdparty/assimp/code/BlobIOSystem.h
+++ b/src/3rdparty/assimp/code/BlobIOSystem.h
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -45,8 +45,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BLOBIOSYSTEM_H_INCLUDED
#define AI_BLOBIOSYSTEM_H_INCLUDED
-namespace Assimp {
- class BlobIOSystem;
+#include "./../include/assimp/IOStream.hpp"
+#include "./../include/assimp/cexport.h"
+#include "./../include/assimp/IOSystem.hpp"
+#include "./../include/assimp/DefaultLogger.hpp"
+#include <stdint.h>
+#include <set>
+#include <vector>
+
+namespace Assimp {
+ class BlobIOSystem;
// --------------------------------------------------------------------------------------------
/** Redirect IOStream to a blob */
@@ -55,142 +63,144 @@ class BlobIOStream : public IOStream
{
public:
- BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
- : buffer()
- , cur_size()
- , file_size()
- , cursor()
- , initial(initial)
- , file(file)
- , creator(creator)
- {
- }
+ BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
+ : buffer()
+ , cur_size()
+ , file_size()
+ , cursor()
+ , initial(initial)
+ , file(file)
+ , creator(creator)
+ {
+ }
- virtual ~BlobIOStream();
+ virtual ~BlobIOStream();
public:
- // -------------------------------------------------------------------
- aiExportDataBlob* GetBlob()
- {
- aiExportDataBlob* blob = new aiExportDataBlob();
- blob->size = file_size;
- blob->data = buffer;
+ // -------------------------------------------------------------------
+ aiExportDataBlob* GetBlob()
+ {
+ aiExportDataBlob* blob = new aiExportDataBlob();
+ blob->size = file_size;
+ blob->data = buffer;
- buffer = NULL;
+ buffer = NULL;
- return blob;
- }
+ return blob;
+ }
public:
- // -------------------------------------------------------------------
- virtual size_t Read( void *,
- size_t,
- size_t )
- {
- return 0;
- }
-
- // -------------------------------------------------------------------
- virtual size_t Write(const void* pvBuffer,
- size_t pSize,
- size_t pCount)
- {
- pSize *= pCount;
- if (cursor + pSize > cur_size) {
- Grow(cursor + pSize);
- }
-
- memcpy(buffer+cursor, pvBuffer, pSize);
- cursor += pSize;
-
- file_size = std::max(file_size,cursor);
- return pCount;
- }
-
- // -------------------------------------------------------------------
- virtual aiReturn Seek(size_t pOffset,
- aiOrigin pOrigin)
- {
- switch(pOrigin)
- {
- case aiOrigin_CUR:
- cursor += pOffset;
-
- case aiOrigin_END:
- cursor = file_size - pOffset;
-
- case aiOrigin_SET:
- cursor = pOffset;
- break;
-
- default:
- return AI_FAILURE;
- }
-
- if (cursor > file_size) {
- Grow(cursor);
- }
-
- file_size = std::max(cursor,file_size);
- return AI_SUCCESS;
- }
-
- // -------------------------------------------------------------------
+ // -------------------------------------------------------------------
+ virtual size_t Read( void *,
+ size_t,
+ size_t )
+ {
+ return 0;
+ }
+
+ // -------------------------------------------------------------------
+ virtual size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount)
+ {
+ pSize *= pCount;
+ if (cursor + pSize > cur_size) {
+ Grow(cursor + pSize);
+ }
+
+ memcpy(buffer+cursor, pvBuffer, pSize);
+ cursor += pSize;
+
+ file_size = std::max(file_size,cursor);
+ return pCount;
+ }
+
+ // -------------------------------------------------------------------
+ virtual aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin)
+ {
+ switch(pOrigin)
+ {
+ case aiOrigin_CUR:
+ cursor += pOffset;
+ break;
+
+ case aiOrigin_END:
+ cursor = file_size - pOffset;
+ break;
+
+ case aiOrigin_SET:
+ cursor = pOffset;
+ break;
+
+ default:
+ return AI_FAILURE;
+ }
+
+ if (cursor > file_size) {
+ Grow(cursor);
+ }
+
+ file_size = std::max(cursor,file_size);
+ return AI_SUCCESS;
+ }
+
+ // -------------------------------------------------------------------
virtual size_t Tell() const
- {
- return cursor;
- }
+ {
+ return cursor;
+ }
- // -------------------------------------------------------------------
- virtual size_t FileSize() const
- {
- return file_size;
- }
+ // -------------------------------------------------------------------
+ virtual size_t FileSize() const
+ {
+ return file_size;
+ }
- // -------------------------------------------------------------------
- virtual void Flush()
- {
- // ignore
- }
+ // -------------------------------------------------------------------
+ virtual void Flush()
+ {
+ // ignore
+ }
private:
- // -------------------------------------------------------------------
- void Grow(size_t need = 0)
- {
- // 1.5 and phi are very heap-friendly growth factors (the first
- // allows for frequent re-use of heap blocks, the second
- // forms a fibonacci sequence with similar characteristics -
- // since this heavily depends on the heap implementation
- // and other factors as well, i'll just go with 1.5 since
- // it is quicker to compute).
- size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+ // -------------------------------------------------------------------
+ void Grow(size_t need = 0)
+ {
+ // 1.5 and phi are very heap-friendly growth factors (the first
+ // allows for frequent re-use of heap blocks, the second
+ // forms a fibonacci sequence with similar characteristics -
+ // since this heavily depends on the heap implementation
+ // and other factors as well, i'll just go with 1.5 since
+ // it is quicker to compute).
+ size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
- const uint8_t* const old = buffer;
- buffer = new uint8_t[new_size];
+ const uint8_t* const old = buffer;
+ buffer = new uint8_t[new_size];
- if (old) {
- memcpy(buffer,old,cur_size);
- delete[] old;
- }
+ if (old) {
+ memcpy(buffer,old,cur_size);
+ delete[] old;
+ }
- cur_size = new_size;
- }
+ cur_size = new_size;
+ }
private:
- uint8_t* buffer;
- size_t cur_size,file_size, cursor, initial;
+ uint8_t* buffer;
+ size_t cur_size,file_size, cursor, initial;
- const std::string file;
- BlobIOSystem* const creator;
+ const std::string file;
+ BlobIOSystem* const creator;
};
@@ -202,125 +212,125 @@ private:
class BlobIOSystem : public IOSystem
{
- friend class BlobIOStream;
- typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
+ friend class BlobIOStream;
+ typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
public:
- BlobIOSystem()
- {
- }
+ BlobIOSystem()
+ {
+ }
- virtual ~BlobIOSystem()
- {
- BOOST_FOREACH(BlobEntry& blobby, blobs) {
- delete blobby.second;
- }
- }
+ virtual ~BlobIOSystem()
+ {
+ for(BlobEntry& blobby : blobs) {
+ delete blobby.second;
+ }
+ }
public:
- // -------------------------------------------------------------------
- const char* GetMagicFileName() const
- {
- return AI_BLOBIO_MAGIC;
- }
-
-
- // -------------------------------------------------------------------
- aiExportDataBlob* GetBlobChain()
- {
- // one must be the master
- aiExportDataBlob* master = NULL, *cur;
- BOOST_FOREACH(const BlobEntry& blobby, blobs) {
- if (blobby.first == AI_BLOBIO_MAGIC) {
- master = blobby.second;
- break;
- }
- }
- if (!master) {
- DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
- return NULL;
- }
-
- master->name.Set("");
-
- cur = master;
- BOOST_FOREACH(const BlobEntry& blobby, blobs) {
- if (blobby.second == master) {
- continue;
- }
-
- cur->next = blobby.second;
- cur = cur->next;
-
- // extract the file extension from the file written
- const std::string::size_type s = blobby.first.find_first_of('.');
- cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
- }
-
- // give up blob ownership
- blobs.clear();
- return master;
- }
+ // -------------------------------------------------------------------
+ const char* GetMagicFileName() const
+ {
+ return AI_BLOBIO_MAGIC;
+ }
+
+
+ // -------------------------------------------------------------------
+ aiExportDataBlob* GetBlobChain()
+ {
+ // one must be the master
+ aiExportDataBlob* master = NULL, *cur;
+ for(const BlobEntry& blobby : blobs) {
+ if (blobby.first == AI_BLOBIO_MAGIC) {
+ master = blobby.second;
+ break;
+ }
+ }
+ if (!master) {
+ DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
+ return NULL;
+ }
+
+ master->name.Set("");
+
+ cur = master;
+ for(const BlobEntry& blobby : blobs) {
+ if (blobby.second == master) {
+ continue;
+ }
+
+ cur->next = blobby.second;
+ cur = cur->next;
+
+ // extract the file extension from the file written
+ const std::string::size_type s = blobby.first.find_first_of('.');
+ cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
+ }
+
+ // give up blob ownership
+ blobs.clear();
+ return master;
+ }
public:
- // -------------------------------------------------------------------
- virtual bool Exists( const char* pFile) const {
- return created.find(std::string(pFile)) != created.end();
- }
+ // -------------------------------------------------------------------
+ virtual bool Exists( const char* pFile) const {
+ return created.find(std::string(pFile)) != created.end();
+ }
- // -------------------------------------------------------------------
- virtual char getOsSeparator() const {
- return '/';
- }
+ // -------------------------------------------------------------------
+ virtual char getOsSeparator() const {
+ return '/';
+ }
- // -------------------------------------------------------------------
- virtual IOStream* Open(const char* pFile,
- const char* pMode)
- {
- if (pMode[0] != 'w') {
- return NULL;
- }
+ // -------------------------------------------------------------------
+ virtual IOStream* Open(const char* pFile,
+ const char* pMode)
+ {
+ if (pMode[0] != 'w') {
+ return NULL;
+ }
- created.insert(std::string(pFile));
- return new BlobIOStream(this,std::string(pFile));
- }
+ created.insert(std::string(pFile));
+ return new BlobIOStream(this,std::string(pFile));
+ }
- // -------------------------------------------------------------------
- virtual void Close( IOStream* pFile)
- {
- delete pFile;
- }
+ // -------------------------------------------------------------------
+ virtual void Close( IOStream* pFile)
+ {
+ delete pFile;
+ }
private:
- // -------------------------------------------------------------------
- void OnDestruct(const std::string& filename, BlobIOStream* child)
- {
- // we don't know in which the files are closed, so we
- // can't reliably say that the first must be the master
- // file ...
- blobs.push_back( BlobEntry(filename,child->GetBlob()) );
- }
+ // -------------------------------------------------------------------
+ void OnDestruct(const std::string& filename, BlobIOStream* child)
+ {
+ // we don't know in which the files are closed, so we
+ // can't reliably say that the first must be the master
+ // file ...
+ blobs.push_back( BlobEntry(filename,child->GetBlob()) );
+ }
private:
- std::set<std::string> created;
- std::vector< BlobEntry > blobs;
+ std::set<std::string> created;
+ std::vector< BlobEntry > blobs;
};
// --------------------------------------------------------------------------------------------
-BlobIOStream :: ~BlobIOStream()
+BlobIOStream :: ~BlobIOStream()
{
- creator->OnDestruct(file,this);
- delete[] buffer;
+ creator->OnDestruct(file,this);
+ delete[] buffer;
}
-
+
} // end Assimp
#endif
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt b/src/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt
deleted file mode 100644
index 127a5bc39..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp
deleted file mode 100644
index 404d325c6..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-
-#ifndef BOOST_FOREACH
-
-///////////////////////////////////////////////////////////////////////////////
-// A stripped down version of FOREACH for
-// illustration purposes. NOT FOR GENERAL USE.
-// For a complete implementation, see BOOST_FOREACH at
-// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
-//
-// Copyright 2004 Eric Niebler.
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// Adapted to Assimp November 29th, 2008 (Alexander Gessler).
-// Added code to handle both const and non-const iterators, simplified some
-// parts.
-///////////////////////////////////////////////////////////////////////////////
-
-namespace boost {
-namespace foreach_detail {
-
-///////////////////////////////////////////////////////////////////////////////
-// auto_any
-
-struct auto_any_base
-{
- operator bool() const { return false; }
-};
-
-template<typename T>
-struct auto_any : auto_any_base
-{
- auto_any(T const& t) : item(t) {}
- mutable T item;
-};
-
-template<typename T>
-T& auto_any_cast(auto_any_base const& any)
-{
- return static_cast<auto_any<T> const&>(any).item;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// FOREACH helper function
-
-template<typename T>
-auto_any<typename T::const_iterator> begin(T const& t)
-{
- return t.begin();
-}
-
-template<typename T>
-auto_any<typename T::const_iterator> end(T const& t)
-{
- return t.end();
-}
-
-// iterator
-template<typename T>
-bool done(auto_any_base const& cur, auto_any_base const& end, T&)
-{
- typedef typename T::iterator iter_type;
- return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
-}
-
-template<typename T>
-void next(auto_any_base const& cur, T&)
-{
- ++auto_any_cast<typename T::iterator>(cur);
-}
-
-template<typename T>
-typename T::reference deref(auto_any_base const& cur, T&)
-{
- return *auto_any_cast<typename T::iterator>(cur);
-}
-
-template<typename T>
-typename T::const_reference deref(auto_any_base const& cur, const T&)
-{
- return *auto_any_cast<typename T::iterator>(cur);
-}
-
-} // end foreach_detail
-
-///////////////////////////////////////////////////////////////////////////////
-// FOREACH
-
-#define BOOST_FOREACH(item, container) \
- if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \
- if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \
- for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \
- if (bool ugly_and_unique_break = false) {} else \
- for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true)
-
-} // end boost
-
-#endif
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp
deleted file mode 100644
index d250c5533..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-/* DEPRECATED! - use code/TinyFormatter.h instead.
- *
- *
- * */
-
-#ifndef AI_BOOST_FORMAT_DUMMY_INCLUDED
-#define AI_BOOST_FORMAT_DUMMY_INCLUDED
-
-#if (!defined BOOST_FORMAT_HPP) || (defined ASSIMP_FORCE_NOBOOST)
-
-#include <string>
-#include <vector>
-
-namespace boost
-{
-
-
- class format
- {
- public:
- format (const std::string& _d)
- : d(_d)
- {
- }
-
- template <typename T>
- format& operator % (T in)
- {
- // XXX add replacement for boost::lexical_cast?
-
- std::ostringstream ss;
- ss << in; // note: ss cannot be an rvalue, or the global operator << (const char*) is not called for T == const char*.
- chunks.push_back( ss.str());
- return *this;
- }
-
-
- operator std::string () const {
- std::string res; // pray for NRVO to kick in
-
- size_t start = 0, last = 0;
-
- std::vector<std::string>::const_iterator chunkin = chunks.begin();
-
- for ( start = d.find('%');start != std::string::npos; start = d.find('%',last)) {
- res += d.substr(last,start-last);
- last = start+2;
- if (d[start+1] == '%') {
- res += "%";
- continue;
- }
-
- if (chunkin == chunks.end()) {
- break;
- }
-
- res += *chunkin++;
- }
- res += d.substr(last);
- return res;
- }
-
- private:
- std::string d;
- std::vector<std::string> chunks;
- };
-
- inline std::string str(const std::string& s) {
- return s;
- }
-}
-
-
-#else
-# error "format.h was already included"
-#endif //
-#endif // !! AI_BOOST_FORMAT_DUMMY_INCLUDED
-
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp
deleted file mode 100644
index af91b011f..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-/// A quick replacement for boost::lexical_cast for all the Boost haters out there
-
-#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST
-#define __AI_BOOST_WORKAROUND_LEXICAL_CAST
-
-#include <sstream>
-
-namespace boost
-{
-
- /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle
- template <typename TargetType, typename SourceType>
- TargetType lexical_cast( const SourceType& source)
- {
- std::stringstream stream;
- TargetType result;
-
- stream << source;
- stream >> result;
- return result;
- }
-
-} // namespace boost
-
-#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST
-
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/make_shared.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/make_shared.hpp
deleted file mode 100644
index d1abb1be6..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/make_shared.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-
-// please note that this replacement implementation does not
-// provide the performance benefit of the original, which
-// makes only one allocation as opposed to two allocations
-// (smart pointer counter and payload) which are usually
-// required if object and smart pointer are constructed
-// independently.
-
-#ifndef INCLUDED_AI_BOOST_MAKE_SHARED
-#define INCLUDED_AI_BOOST_MAKE_SHARED
-
-
-namespace boost {
-
- template <typename T>
- shared_ptr<T> make_shared() {
- return shared_ptr<T>(new T());
- }
-
- template <typename T, typename T0>
- shared_ptr<T> make_shared(const T0& t0) {
- return shared_ptr<T>(new T(t0));
- }
-
- template <typename T, typename T0,typename T1>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1) {
- return shared_ptr<T>(new T(t0,t1));
- }
-
- template <typename T, typename T0,typename T1,typename T2>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2) {
- return shared_ptr<T>(new T(t0,t1,t2));
- }
-
- template <typename T, typename T0,typename T1,typename T2,typename T3>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) {
- return shared_ptr<T>(new T(t0,t1,t2,t3));
- }
-
- template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
- return shared_ptr<T>(new T(t0,t1,t2,t3,t4));
- }
-
- template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4, typename T5>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) {
- return shared_ptr<T>(new T(t0,t1,t2,t3,t4,t5));
- }
-
- template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4, typename T5, typename T6>
- shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) {
- return shared_ptr<T>(new T(t0,t1,t2,t3,t4,t5,t6));
- }
-}
-
-
-#endif
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp
deleted file mode 100644
index f7615f974..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
-#define BOOST_MATH_COMMON_FACTOR_RT_HPP
-
-
-namespace boost {
-namespace math {
-
-// TODO: use binary GCD for unsigned integers ....
-template < typename IntegerType >
-IntegerType gcd( IntegerType a, IntegerType b )
-{
- const IntegerType zero = (IntegerType)0;
- while ( true )
- {
- if ( a == zero )
- return b;
- b %= a;
-
- if ( b == zero )
- return a;
- a %= b;
- }
-}
-
-template < typename IntegerType >
-IntegerType lcm( IntegerType a, IntegerType b )
-{
- const IntegerType t = gcd (a,b);
- if (!t)return t;
- return a / t * b;
-}
-
-}}
-
-#endif
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/noncopyable.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/noncopyable.hpp
deleted file mode 100644
index 7770bdbd3..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/noncopyable.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Boost noncopyable.hpp header file --------------------------------------//
-
-// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/utility for documentation.
-
-#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
-#define BOOST_NONCOPYABLE_HPP_INCLUDED
-
-namespace boost {
-
-// Private copy constructor and copy assignment ensure classes derived from
-// class noncopyable cannot be copied.
-
-// Contributed by Dave Abrahams
-
-namespace noncopyable_ // protection from unintended ADL
-{
- class noncopyable
- {
- protected:
- noncopyable() {}
- ~noncopyable() {}
- private: // emphasize the following members are private
- noncopyable( const noncopyable& );
- const noncopyable& operator=( const noncopyable& );
- };
-}
-
-typedef noncopyable_::noncopyable noncopyable;
-
-} // namespace boost
-
-#endif // BOOST_NONCOPYABLE_HPP_INCLUDED
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp
deleted file mode 100644
index 6e532ebdd..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2005.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#ifndef BOOST_POINTER_CAST_HPP
-#define BOOST_POINTER_CAST_HPP
-
-namespace boost {
-
-//static_pointer_cast overload for raw pointers
-template<class T, class U>
-inline T* static_pointer_cast(U *ptr)
-{
- return static_cast<T*>(ptr);
-}
-
-//dynamic_pointer_cast overload for raw pointers
-template<class T, class U>
-inline T* dynamic_pointer_cast(U *ptr)
-{
- return dynamic_cast<T*>(ptr);
-}
-
-//const_pointer_cast overload for raw pointers
-template<class T, class U>
-inline T* const_pointer_cast(U *ptr)
-{
- return const_cast<T*>(ptr);
-}
-
-//reinterpret_pointer_cast overload for raw pointers
-template<class T, class U>
-inline T* reinterpret_pointer_cast(U *ptr)
-{
- return reinterpret_cast<T*>(ptr);
-}
-
-} // namespace boost
-
-#endif //BOOST_POINTER_CAST_HPP
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp
deleted file mode 100644
index fb1b11544..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-
-#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED
-#define __AI_BOOST_SCOPED_ARRAY_INCLUDED
-
-#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
-
-namespace boost {
-
-// small replacement for boost::scoped_array
-template <class T>
-class scoped_array
-{
-public:
-
- // provide a default construtctor
- scoped_array()
- : ptr(0)
- {
- }
-
- // construction from an existing heap object of type T
- scoped_array(T* _ptr)
- : ptr(_ptr)
- {
- }
-
- // automatic destruction of the wrapped object at the
- // end of our lifetime
- ~scoped_array()
- {
- delete[] ptr;
- }
-
- inline T* get()
- {
- return ptr;
- }
-
- inline T* operator-> ()
- {
- return ptr;
- }
-
- inline void reset (T* t = 0)
- {
- delete[] ptr;
- ptr = t;
- }
-
- T & operator[](std::ptrdiff_t i) const
- {
- return ptr[i];
- }
-
- void swap(scoped_array & b)
- {
- std::swap(ptr, b.ptr);
- }
-
-private:
-
- // encapsulated object pointer
- T* ptr;
-
-};
-
-template<class T>
-inline void swap(scoped_array<T> & a, scoped_array<T> & b)
-{
- a.swap(b);
-}
-
-} // end of namespace boost
-
-#else
-# error "scoped_array.h was already included"
-#endif
-#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED
-
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp
deleted file mode 100644
index 80c394def..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-
-#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED
-#define __AI_BOOST_SCOPED_PTR_INCLUDED
-
-#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
-
-namespace boost {
-
-// small replacement for boost::scoped_ptr
-template <class T>
-class scoped_ptr
-{
-public:
-
- // provide a default construtctor
- scoped_ptr()
- : ptr(0)
- {
- }
-
- // construction from an existing heap object of type T
- scoped_ptr(T* _ptr)
- : ptr(_ptr)
- {
- }
-
- // automatic destruction of the wrapped object at the
- // end of our lifetime
- ~scoped_ptr()
- {
- delete ptr;
- }
-
- inline T* get() const
- {
- return ptr;
- }
-
- inline operator T*()
- {
- return ptr;
- }
-
- inline T* operator-> ()
- {
- return ptr;
- }
-
- inline void reset (T* t = 0)
- {
- delete ptr;
- ptr = t;
- }
-
- void swap(scoped_ptr & b)
- {
- std::swap(ptr, b.ptr);
- }
-
-private:
-
- // encapsulated object pointer
- T* ptr;
-
-};
-
-template<class T>
-inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b)
-{
- a.swap(b);
-}
-
-} // end of namespace boost
-
-#else
-# error "scoped_ptr.h was already included"
-#endif
-#endif // __AI_BOOST_SCOPED_PTR_INCLUDED
-
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp
deleted file mode 100644
index 9847d9f82..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp
+++ /dev/null
@@ -1,228 +0,0 @@
-
-#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY
-#define INCLUDED_AI_BOOST_SHARED_ARRAY
-
-#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
-
-// ------------------------------
-// Internal stub
-namespace boost {
- namespace array_detail {
- class controller {
- public:
-
- controller()
- : cnt(1)
- {}
-
- public:
-
- template <typename T>
- controller* decref(T* pt) {
- if (--cnt <= 0) {
- delete this;
- delete[] pt;
- }
- return NULL;
- }
-
- controller* incref() {
- ++cnt;
- return this;
- }
-
- long get() const {
- return cnt;
- }
-
- private:
- long cnt;
- };
-
- struct empty {};
-
- template <typename DEST, typename SRC>
- struct is_convertible_stub {
-
- struct yes {char s[1];};
- struct no {char s[2];};
-
- static yes foo(DEST*);
- static no foo(...);
-
- enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)};
- };
-
- template <bool> struct enable_if {};
- template <> struct enable_if<true> {
- typedef empty result;
- };
-
- template <typename DEST, typename SRC>
- struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > {
- };
- }
-
-// ------------------------------
-// Small replacement for boost::shared_array, not threadsafe because no
-// atomic reference counter is in use.
-// ------------------------------
-template <class T>
-class shared_array
-{
- template <typename TT> friend class shared_array;
-
- template<class TT> friend bool operator== (const shared_array<TT>& a, const shared_array<TT>& b);
- template<class TT> friend bool operator!= (const shared_array<TT>& a, const shared_array<TT>& b);
- template<class TT> friend bool operator< (const shared_array<TT>& a, const shared_array<TT>& b);
-
-public:
-
- typedef T element_type;
-
-public:
-
- // provide a default constructor
- shared_array()
- : ptr()
- , ctr(NULL)
- {
- }
-
- // construction from an existing object of type T
- explicit shared_array(T* ptr)
- : ptr(ptr)
- , ctr(ptr ? new array_detail::controller() : NULL)
- {
- }
-
- shared_array(const shared_array& r)
- : ptr(r.ptr)
- , ctr(r.ctr ? r.ctr->incref() : NULL)
- {
- }
-
- template <typename Y>
- shared_array(const shared_array<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty())
- : ptr(r.ptr)
- , ctr(r.ctr ? r.ctr->incref() : NULL)
- {
- }
-
- // automatic destruction of the wrapped object when all
- // references are freed.
- ~shared_array() {
- if (ctr) {
- ctr = ctr->decref(ptr);
- }
- }
-
- shared_array& operator=(const shared_array& r) {
- if (this == &r) {
- return *this;
- }
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = r.ptr;
- ctr = ptr?r.ctr->incref():NULL;
- return *this;
- }
-
- template <typename Y>
- shared_array& operator=(const shared_array<Y>& r) {
- if (this == &r) {
- return *this;
- }
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = r.ptr;
- ctr = ptr?r.ctr->incref():NULL;
- return *this;
- }
-
- // pointer access
- inline operator T*() {
- return ptr;
- }
-
- inline T* operator-> () const {
- return ptr;
- }
-
- // standard semantics
- inline T* get() {
- return ptr;
- }
-
- T& operator[] (std::ptrdiff_t index) const {
- return ptr[index];
- }
-
- inline const T* get() const {
- return ptr;
- }
-
- inline operator bool () const {
- return ptr != NULL;
- }
-
- inline bool unique() const {
- return use_count() == 1;
- }
-
- inline long use_count() const {
- return ctr->get();
- }
-
- inline void reset (T* t = 0) {
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = t;
- ctr = ptr?new array_detail::controller():NULL;
- }
-
- void swap(shared_array & b) {
- std::swap(ptr, b.ptr);
- std::swap(ctr, b.ctr);
- }
-
-
-private:
-
- // encapsulated object pointer
- T* ptr;
-
- // control block
- array_detail::controller* ctr;
-};
-
-template<class T>
-inline void swap(shared_array<T> & a, shared_array<T> & b)
-{
- a.swap(b);
-}
-
-template<class T>
-bool operator== (const shared_array<T>& a, const shared_array<T>& b) {
- return a.ptr == b.ptr;
-}
-template<class T>
-bool operator!= (const shared_array<T>& a, const shared_array<T>& b) {
- return a.ptr != b.ptr;
-}
-
-template<class T>
-bool operator< (const shared_array<T>& a, const shared_array<T>& b) {
- return a.ptr < b.ptr;
-}
-
-
-} // end of namespace boost
-
-#else
-# error "shared_array.h was already included"
-#endif
-#endif // INCLUDED_AI_BOOST_SHARED_ARRAY
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
deleted file mode 100644
index fe9dcd8be..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
+++ /dev/null
@@ -1,257 +0,0 @@
-
-#ifndef INCLUDED_AI_BOOST_SHARED_PTR
-#define INCLUDED_AI_BOOST_SHARED_PTR
-
-#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
-
-// ------------------------------
-// Internal stub
-namespace boost {
- namespace detail {
- class controller {
- public:
-
- controller()
- : cnt(1)
- {}
-
- public:
-
- template <typename T>
- controller* decref(T* pt) {
- if (--cnt <= 0) {
- delete this;
- delete pt;
- }
- return NULL;
- }
-
- controller* incref() {
- ++cnt;
- return this;
- }
-
- long get() const {
- return cnt;
- }
-
- private:
- long cnt;
- };
-
- struct empty {};
-
- template <typename DEST, typename SRC>
- struct is_convertible_stub {
-
- struct yes {char s[1];};
- struct no {char s[2];};
-
- static yes foo(DEST*);
- static no foo(...);
-
- enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)};
- };
-
- template <bool> struct enable_if {};
- template <> struct enable_if<true> {
- typedef empty result;
- };
-
- template <typename DEST, typename SRC>
- struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > {
- };
- }
-
-// ------------------------------
-// Small replacement for boost::shared_ptr, not threadsafe because no
-// atomic reference counter is in use.
-// ------------------------------
-template <class T>
-class shared_ptr
-{
- template <typename TT> friend class shared_ptr;
-
- template<class TT, class U> friend shared_ptr<TT> static_pointer_cast (shared_ptr<U> ptr);
- template<class TT, class U> friend shared_ptr<TT> dynamic_pointer_cast (shared_ptr<U> ptr);
- template<class TT, class U> friend shared_ptr<TT> const_pointer_cast (shared_ptr<U> ptr);
-
- template<class TT> friend bool operator== (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
- template<class TT> friend bool operator!= (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
- template<class TT> friend bool operator< (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
-
-public:
-
- typedef T element_type;
-
-public:
-
- // provide a default constructor
- shared_ptr()
- : ptr()
- , ctr(NULL)
- {
- }
-
- // construction from an existing object of type T
- explicit shared_ptr(T* ptr)
- : ptr(ptr)
- , ctr(ptr ? new detail::controller() : NULL)
- {
- }
-
- shared_ptr(const shared_ptr& r)
- : ptr(r.ptr)
- , ctr(r.ctr ? r.ctr->incref() : NULL)
- {
- }
-
- template <typename Y>
- shared_ptr(const shared_ptr<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty())
- : ptr(r.ptr)
- , ctr(r.ctr ? r.ctr->incref() : NULL)
- {
- }
-
- // automatic destruction of the wrapped object when all
- // references are freed.
- ~shared_ptr() {
- if (ctr) {
- ctr = ctr->decref(ptr);
- }
- }
-
- shared_ptr& operator=(const shared_ptr& r) {
- if (this == &r) {
- return *this;
- }
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = r.ptr;
- ctr = ptr?r.ctr->incref():NULL;
- return *this;
- }
-
- template <typename Y>
- shared_ptr& operator=(const shared_ptr<Y>& r) {
- if (this == &r) {
- return *this;
- }
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = r.ptr;
- ctr = ptr?r.ctr->incref():NULL;
- return *this;
- }
-
- // pointer access
- inline operator T*() const {
- return ptr;
- }
-
- inline T* operator-> () const {
- return ptr;
- }
-
- // standard semantics
- inline T* get() {
- return ptr;
- }
-
- inline const T* get() const {
- return ptr;
- }
-
- inline operator bool () const {
- return ptr != NULL;
- }
-
- inline bool unique() const {
- return use_count() == 1;
- }
-
- inline long use_count() const {
- return ctr->get();
- }
-
- inline void reset (T* t = 0) {
- if (ctr) {
- ctr->decref(ptr);
- }
- ptr = t;
- ctr = ptr?new detail::controller():NULL;
- }
-
- void swap(shared_ptr & b) {
- std::swap(ptr, b.ptr);
- std::swap(ctr, b.ctr);
- }
-
-private:
-
-
- // for use by the various xxx_pointer_cast helper templates
- explicit shared_ptr(T* ptr, detail::controller* ctr)
- : ptr(ptr)
- , ctr(ctr->incref())
- {
- }
-
-private:
-
- // encapsulated object pointer
- T* ptr;
-
- // control block
- detail::controller* ctr;
-};
-
-template<class T>
-inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
-{
- a.swap(b);
-}
-
-template<class T>
-bool operator== (const shared_ptr<T>& a, const shared_ptr<T>& b) {
- return a.ptr == b.ptr;
-}
-template<class T>
-bool operator!= (const shared_ptr<T>& a, const shared_ptr<T>& b) {
- return a.ptr != b.ptr;
-}
-
-template<class T>
-bool operator< (const shared_ptr<T>& a, const shared_ptr<T>& b) {
- return a.ptr < b.ptr;
-}
-
-
-template<class T, class U>
-inline shared_ptr<T> static_pointer_cast( shared_ptr<U> ptr)
-{
- return shared_ptr<T>(static_cast<T*>(ptr.ptr),ptr.ctr);
-}
-
-template<class T, class U>
-inline shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> ptr)
-{
- return shared_ptr<T>(dynamic_cast<T*>(ptr.ptr),ptr.ctr);
-}
-
-template<class T, class U>
-inline shared_ptr<T> const_pointer_cast( shared_ptr<U> ptr)
-{
- return shared_ptr<T>(const_cast<T*>(ptr.ptr),ptr.ctr);
-}
-
-
-
-} // end of namespace boost
-
-#else
-# error "shared_ptr.h was already included"
-#endif
-#endif // INCLUDED_AI_BOOST_SHARED_PTR
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp
deleted file mode 100644
index a533c6fa9..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED
-#define AI_BOOST_STATIC_ASSERT_INCLUDED
-
-#ifndef BOOST_STATIC_ASSERT
-
-namespace boost {
- namespace detail {
-
- template <bool b> class static_assertion_failure;
- template <> class static_assertion_failure<true> {};
- }
-}
-
-
-#define BOOST_STATIC_ASSERT(eval) \
-{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;}
-
-#endif
-#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp
deleted file mode 100644
index 79c73f457..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp
+++ /dev/null
@@ -1,72 +0,0 @@
-// boost timer.hpp header file ---------------------------------------------//
-
-// Copyright Beman Dawes 1994-99. Distributed under the Boost
-// Software License, Version 1.0. (See accompanying file
-// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/timer for documentation.
-
-// Revision History
-// 01 Apr 01 Modified to use new <boost/limits.hpp> header. (JMaddock)
-// 12 Jan 01 Change to inline implementation to allow use without library
-// builds. See docs for more rationale. (Beman Dawes)
-// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock)
-// 16 Jul 99 Second beta
-// 6 Jul 99 Initial boost version
-
-#ifndef BOOST_TIMER_HPP
-#define BOOST_TIMER_HPP
-
-//#include <boost/config.hpp>
-#include <ctime>
-//#include <boost/limits.hpp>
-
-# ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::clock_t; using ::clock; }
-# endif
-
-
-namespace boost {
-
-// timer -------------------------------------------------------------------//
-
-// A timer object measures elapsed time.
-
-// It is recommended that implementations measure wall clock rather than CPU
-// time since the intended use is performance measurement on systems where
-// total elapsed time is more important than just process or CPU time.
-
-// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours
-// due to implementation limitations. The accuracy of timings depends on the
-// accuracy of timing information provided by the underlying platform, and
-// this varies a great deal from platform to platform.
-
-class timer
-{
- public:
- timer() { _start_time = std::clock(); } // postcondition: elapsed()==0
-// timer( const timer& src ); // post: elapsed()==src.elapsed()
-// ~timer(){}
-// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed()
- void restart() { _start_time = std::clock(); } // post: elapsed()==0
- double elapsed() const // return elapsed time in seconds
- { return double(std::clock() - _start_time) / CLOCKS_PER_SEC; }
-
- double elapsed_max() const // return estimated maximum value for elapsed()
- // Portability warning: elapsed_max() may return too high a value on systems
- // where std::clock_t overflows or resets at surprising values.
- {
- return (double((std::numeric_limits<std::clock_t>::max)())
- - double(_start_time)) / double(CLOCKS_PER_SEC);
- }
-
- double elapsed_min() const // return minimum value for elapsed()
- { return double(1)/double(CLOCKS_PER_SEC); }
-
- private:
- std::clock_t _start_time;
-}; // timer
-
-} // namespace boost
-
-#endif // BOOST_TIMER_HPP \ No newline at end of file
diff --git a/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp b/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
deleted file mode 100644
index 3c1dd7b33..000000000
--- a/src/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
+++ /dev/null
@@ -1,283 +0,0 @@
-// A very small replacement for boost::tuple
-// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net]
-
-#ifndef BOOST_TUPLE_INCLUDED
-#define BOOST_TUPLE_INCLUDED
-
-namespace boost {
- namespace detail {
-
- // Represents an empty tuple slot (up to 5 supported)
- struct nulltype {};
-
- // For readable error messages
- struct tuple_component_idx_out_of_bounds;
-
- // To share some code for the const/nonconst versions of the getters
- template <bool b, typename T>
- struct ConstIf {
- typedef T t;
- };
-
- template <typename T>
- struct ConstIf<true,T> {
- typedef const T t;
- };
-
- // Predeclare some stuff
- template <typename, unsigned, typename, bool, unsigned> struct value_getter;
-
- // Helper to obtain the type of a tuple element
- template <typename T, unsigned NIDX, typename TNEXT, unsigned N /*= 0*/>
- struct type_getter {
- typedef type_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,N> next_elem_getter;
- typedef typename next_elem_getter::type type;
- };
-
- template <typename T, unsigned NIDX, typename TNEXT >
- struct type_getter <T,NIDX,TNEXT,NIDX> {
- typedef T type;
- };
-
- // Base class for all explicit specializations of list_elem
- template <typename T, unsigned NIDX, typename TNEXT >
- struct list_elem_base {
-
- // Store template parameters
- typedef TNEXT next_type;
- typedef T type;
-
- static const unsigned nidx = NIDX;
- };
-
- // Represents an element in the tuple component list
- template <typename T, unsigned NIDX, typename TNEXT >
- struct list_elem : list_elem_base<T,NIDX,TNEXT>{
-
- // Real members
- T me;
- TNEXT next;
-
- // Get the value of a specific tuple element
- template <unsigned N>
- typename type_getter<T,NIDX,TNEXT,N>::type& get () {
- value_getter <T,NIDX,TNEXT,false,N> s;
- return s(*this);
- }
-
- // Get the value of a specific tuple element
- template <unsigned N>
- const typename type_getter<T,NIDX,TNEXT,N>::type& get () const {
- value_getter <T,NIDX,TNEXT,true,N> s;
- return s(*this);
- }
-
- // Explicit cast
- template <typename T2, typename TNEXT2 >
- operator list_elem<T2,NIDX,TNEXT2> () const {
- list_elem<T2,NIDX,TNEXT2> ret;
- ret.me = (T2)me;
- ret.next = next;
- return ret;
- }
-
- // Recursively compare two elements (last element returns always true)
- bool operator == (const list_elem& s) const {
- return (me == s.me && next == s.next);
- }
- };
-
- // Represents a non-used tuple element - the very last element processed
- template <typename TNEXT, unsigned NIDX >
- struct list_elem<nulltype,NIDX,TNEXT> : list_elem_base<nulltype,NIDX,TNEXT> {
- template <unsigned N, bool IS_CONST = true> struct value_getter {
- /* just dummy members to produce readable error messages */
- tuple_component_idx_out_of_bounds operator () (typename ConstIf<IS_CONST,list_elem>::t& me);
- };
- template <unsigned N> struct type_getter {
- /* just dummy members to produce readable error messages */
- typedef tuple_component_idx_out_of_bounds type;
- };
-
- // dummy
- list_elem& operator = (const list_elem& other) {
- return *this;
- }
-
- // dummy
- bool operator == (const list_elem& other) {
- return true;
- }
- };
-
- // Represents the absolute end of the list
- typedef list_elem<nulltype,0,int> list_end;
-
- // Helper obtain to query the value of a tuple element
- // NOTE: This can't be a nested class as the compiler won't accept a full or
- // partial specialization of a nested class of a non-specialized template
- template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST, unsigned N>
- struct value_getter {
-
- // calling list_elem
- typedef list_elem<T,NIDX,TNEXT> outer_elem;
-
- // typedef for the getter for next element
- typedef value_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,
- IS_CONST, N> next_value_getter;
-
- typename ConstIf<IS_CONST,typename type_getter<T,NIDX,TNEXT,N>::type>::t&
- operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
-
- next_value_getter s;
- return s(me.next);
- }
- };
-
- template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST>
- struct value_getter <T,NIDX,TNEXT,IS_CONST,NIDX> {
- typedef list_elem<T,NIDX,TNEXT> outer_elem;
-
- typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
- return me.me;
- }
- };
- };
-
- // A very minimal implementation for up to 5 elements
- template <typename T0 = detail::nulltype,
- typename T1 = detail::nulltype,
- typename T2 = detail::nulltype,
- typename T3 = detail::nulltype,
- typename T4 = detail::nulltype>
- class tuple {
-
- template <typename T0b,
- typename T1b,
- typename T2b,
- typename T3b,
- typename T4b >
- friend class tuple;
-
- private:
-
- typedef detail::list_elem<T0,0,
- detail::list_elem<T1,1,
- detail::list_elem<T2,2,
- detail::list_elem<T3,3,
- detail::list_elem<T4,4,
- detail::list_end > > > > > very_long;
-
- very_long m;
-
- public:
-
- // Get a specific tuple element
- template <unsigned N>
- typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () {
- return m.template get<N>();
- }
-
- // ... and the const version
- template <unsigned N>
- const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
- return m.template get<N>();
- }
-
-
- // comparison operators
- bool operator== (const tuple& other) const {
- return m == other.m;
- }
-
- // ... and the other way round
- bool operator!= (const tuple& other) const {
- return !(m == other.m);
- }
-
- // cast to another tuple - all single elements must be convertible
- template <typename T0b, typename T1b,typename T2b,typename T3b, typename T4b>
- operator tuple <T0b,T1b,T2b,T3b,T4b> () const {
- tuple <T0b,T1b,T2b,T3b,T4b> s;
- s.m = (typename tuple <T0b,T1b,T2b,T3b,T4b>::very_long)m;
- return s;
- }
- };
-
- // Another way to access an element ...
- template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
- inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
- tuple<T0,T1,T2,T3,T4>& m) {
- return m.template get<N>();
- }
-
- // ... and the const version
- template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
- inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
- const tuple<T0,T1,T2,T3,T4>& m) {
- return m.template get<N>();
- }
-
- // Constructs a tuple with 5 elements
- template <typename T0,typename T1,typename T2,typename T3,typename T4>
- inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0,
- const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
-
- tuple <T0,T1,T2,T3,T4> t;
- t.template get<0>() = t0;
- t.template get<1>() = t1;
- t.template get<2>() = t2;
- t.template get<3>() = t3;
- t.template get<4>() = t4;
- return t;
- }
-
- // Constructs a tuple with 4 elements
- template <typename T0,typename T1,typename T2,typename T3>
- inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
- const T1& t1,const T2& t2,const T3& t3) {
- tuple <T0,T1,T2,T3> t;
- t.template get<0>() = t0;
- t.template get<1>() = t1;
- t.template get<2>() = t2;
- t.template get<3>() = t3;
- return t;
- }
-
- // Constructs a tuple with 3 elements
- template <typename T0,typename T1,typename T2>
- inline tuple <T0,T1,T2> make_tuple (const T0& t0,
- const T1& t1,const T2& t2) {
- tuple <T0,T1,T2> t;
- t.template get<0>() = t0;
- t.template get<1>() = t1;
- t.template get<2>() = t2;
- return t;
- }
-
- // Constructs a tuple with 2 elements
- template <typename T0,typename T1>
- inline tuple <T0,T1> make_tuple (const T0& t0,
- const T1& t1) {
- tuple <T0,T1> t;
- t.template get<0>() = t0;
- t.template get<1>() = t1;
- return t;
- }
-
- // Constructs a tuple with 1 elements (well ...)
- template <typename T0>
- inline tuple <T0> make_tuple (const T0& t0) {
- tuple <T0> t;
- t.template get<0>() = t0;
- return t;
- }
-
- // Constructs a tuple with 0 elements (well ...)
- inline tuple <> make_tuple () {
- tuple <> t = tuple <> ();
- return t;
- }
-};
-
-#endif // !! BOOST_TUPLE_INCLUDED
diff --git a/src/3rdparty/assimp/code/ByteSwap.h b/src/3rdparty/assimp/code/ByteSwap.h
deleted file mode 100644
index 0d4f52840..000000000
--- a/src/3rdparty/assimp/code/ByteSwap.h
+++ /dev/null
@@ -1,285 +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 Helper class tp perform various byte oder swappings
- (e.g. little to big endian) */
-#ifndef AI_BYTESWAP_H_INC
-#define AI_BYTESWAP_H_INC
-
-#include "../include/assimp/ai_assert.h"
-#include "../include/assimp/types.h"
-
-#if _MSC_VER >= 1400
-#include <stdlib.h>
-#endif
-
-namespace Assimp {
-// --------------------------------------------------------------------------------------
-/** Defines some useful byte order swap routines.
- *
- * This is required to read big-endian model formats on little-endian machines,
- * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
-// --------------------------------------------------------------------------------------
-class ByteSwap
-{
- ByteSwap() {}
-
-public:
-
- // ----------------------------------------------------------------------
- /** Swap two bytes of data
- * @param[inout] _szOut A void* to save the reintcasts for the caller. */
- static inline void Swap2(void* _szOut)
- {
- ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
- uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
- *szOut = _byteswap_ushort(*szOut);
-#else
- uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
- std::swap(szOut[0],szOut[1]);
-#endif
- }
-
- // ----------------------------------------------------------------------
- /** Swap four bytes of data
- * @param[inout] _szOut A void* to save the reintcasts for the caller. */
- static inline void Swap4(void* _szOut)
- {
- ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
- uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
- *szOut = _byteswap_ulong(*szOut);
-#else
- uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
- std::swap(szOut[0],szOut[3]);
- std::swap(szOut[1],szOut[2]);
-#endif
- }
-
- // ----------------------------------------------------------------------
- /** Swap eight bytes of data
- * @param[inout] _szOut A void* to save the reintcasts for the caller. */
- static inline void Swap8(void* _szOut)
- {
- ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
- uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
- *szOut = _byteswap_uint64(*szOut);
-#else
- uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
- std::swap(szOut[0],szOut[7]);
- std::swap(szOut[1],szOut[6]);
- std::swap(szOut[2],szOut[5]);
- std::swap(szOut[3],szOut[4]);
-#endif
- }
-
- // ----------------------------------------------------------------------
- /** ByteSwap a float. Not a joke.
- * @param[inout] fOut ehm. .. */
- static inline void Swap(float* fOut) {
- Swap4(fOut);
- }
-
- // ----------------------------------------------------------------------
- /** ByteSwap a double. Not a joke.
- * @param[inout] fOut ehm. .. */
- static inline void Swap(double* fOut) {
- Swap8(fOut);
- }
-
-
- // ----------------------------------------------------------------------
- /** ByteSwap an int16t. Not a joke.
- * @param[inout] fOut ehm. .. */
- static inline void Swap(int16_t* fOut) {
- Swap2(fOut);
- }
-
- static inline void Swap(uint16_t* fOut) {
- Swap2(fOut);
- }
-
- // ----------------------------------------------------------------------
- /** ByteSwap an int32t. Not a joke.
- * @param[inout] fOut ehm. .. */
- static inline void Swap(int32_t* fOut){
- Swap4(fOut);
- }
-
- static inline void Swap(uint32_t* fOut){
- Swap4(fOut);
- }
-
- // ----------------------------------------------------------------------
- /** ByteSwap an int64t. Not a joke.
- * @param[inout] fOut ehm. .. */
- static inline void Swap(int64_t* fOut) {
- Swap8(fOut);
- }
-
- static inline void Swap(uint64_t* fOut) {
- Swap8(fOut);
- }
-
- // ----------------------------------------------------------------------
- //! Templatized ByteSwap
- //! \returns param tOut as swapped
- template<typename Type>
- static inline Type Swapped(Type tOut)
- {
- return _swapper<Type,sizeof(Type)>()(tOut);
- }
-
-private:
-
- template <typename T, size_t size> struct _swapper;
-};
-
-template <typename T> struct ByteSwap::_swapper<T,2> {
- T operator() (T tOut) {
- Swap2(&tOut);
- return tOut;
- }
-};
-
-template <typename T> struct ByteSwap::_swapper<T,4> {
- T operator() (T tOut) {
- Swap4(&tOut);
- return tOut;
- }
-};
-
-template <typename T> struct ByteSwap::_swapper<T,8> {
- T operator() (T tOut) {
- Swap8(&tOut);
- return tOut;
- }
-};
-
-
-// --------------------------------------------------------------------------------------
-// ByteSwap macros for BigEndian/LittleEndian support
-// --------------------------------------------------------------------------------------
-#if (defined AI_BUILD_BIG_ENDIAN)
-# define AI_LE(t) (t)
-# define AI_BE(t) ByteSwap::Swapped(t)
-# define AI_LSWAP2(p)
-# define AI_LSWAP4(p)
-# define AI_LSWAP8(p)
-# define AI_LSWAP2P(p)
-# define AI_LSWAP4P(p)
-# define AI_LSWAP8P(p)
-# define LE_NCONST const
-# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
-# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
-# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
-# define AI_SWAP2P(p) ByteSwap::Swap2((p))
-# define AI_SWAP4P(p) ByteSwap::Swap4((p))
-# define AI_SWAP8P(p) ByteSwap::Swap8((p))
-# define BE_NCONST
-#else
-# define AI_BE(t) (t)
-# define AI_LE(t) ByteSwap::Swapped(t)
-# define AI_SWAP2(p)
-# define AI_SWAP4(p)
-# define AI_SWAP8(p)
-# define AI_SWAP2P(p)
-# define AI_SWAP4P(p)
-# define AI_SWAP8P(p)
-# define BE_NCONST const
-# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
-# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
-# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
-# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
-# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
-# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
-# define LE_NCONST
-#endif
-
-
-namespace Intern {
-
-// --------------------------------------------------------------------------------------------
-template <typename T, bool doit>
-struct ByteSwapper {
- void operator() (T* inout) {
- ByteSwap::Swap(inout);
- }
-};
-
-template <typename T>
-struct ByteSwapper<T,false> {
- void operator() (T*) {
- }
-};
-
-// --------------------------------------------------------------------------------------------
-template <bool SwapEndianess, typename T, bool RuntimeSwitch>
-struct Getter {
- void operator() (T* inout, bool le) {
-#ifdef AI_BUILD_BIG_ENDIAN
- le = le;
-#else
- le = !le;
-#endif
- if (le) {
- ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
- }
- else ByteSwapper<T,false> () (inout);
- }
-};
-
-template <bool SwapEndianess, typename T>
-struct Getter<SwapEndianess,T,false> {
-
- void operator() (T* inout, bool /*le*/) {
- // static branch
- ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
- }
-};
-} // end Intern
-} // end Assimp
-
-#endif //!! AI_BYTESWAP_H_INC
diff --git a/src/3rdparty/assimp/code/ByteSwapper.h b/src/3rdparty/assimp/code/ByteSwapper.h
new file mode 100644
index 000000000..37538e7cb
--- /dev/null
+++ b/src/3rdparty/assimp/code/ByteSwapper.h
@@ -0,0 +1,286 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file Helper class tp perform various byte oder swappings
+ (e.g. little to big endian) */
+#ifndef AI_BYTESWAPPER_H_INC
+#define AI_BYTESWAPPER_H_INC
+
+#include <assimp/ai_assert.h>
+#include <assimp/types.h>
+#include <stdint.h>
+
+#if _MSC_VER >= 1400
+#include <stdlib.h>
+#endif
+
+namespace Assimp {
+// --------------------------------------------------------------------------------------
+/** Defines some useful byte order swap routines.
+ *
+ * This is required to read big-endian model formats on little-endian machines,
+ * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
+// --------------------------------------------------------------------------------------
+class ByteSwap
+{
+ ByteSwap() {}
+
+public:
+
+ // ----------------------------------------------------------------------
+ /** Swap two bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap2(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
+ *szOut = _byteswap_ushort(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[1]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** Swap four bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap4(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
+ *szOut = _byteswap_ulong(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[3]);
+ std::swap(szOut[1],szOut[2]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** Swap eight bytes of data
+ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
+ static inline void Swap8(void* _szOut)
+ {
+ ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+ uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
+ *szOut = _byteswap_uint64(*szOut);
+#else
+ uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+ std::swap(szOut[0],szOut[7]);
+ std::swap(szOut[1],szOut[6]);
+ std::swap(szOut[2],szOut[5]);
+ std::swap(szOut[3],szOut[4]);
+#endif
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap a float. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(float* fOut) {
+ Swap4(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap a double. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(double* fOut) {
+ Swap8(fOut);
+ }
+
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int16t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int16_t* fOut) {
+ Swap2(fOut);
+ }
+
+ static inline void Swap(uint16_t* fOut) {
+ Swap2(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int32t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int32_t* fOut){
+ Swap4(fOut);
+ }
+
+ static inline void Swap(uint32_t* fOut){
+ Swap4(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ /** ByteSwap an int64t. Not a joke.
+ * @param[inout] fOut ehm. .. */
+ static inline void Swap(int64_t* fOut) {
+ Swap8(fOut);
+ }
+
+ static inline void Swap(uint64_t* fOut) {
+ Swap8(fOut);
+ }
+
+ // ----------------------------------------------------------------------
+ //! Templatized ByteSwap
+ //! \returns param tOut as swapped
+ template<typename Type>
+ static inline Type Swapped(Type tOut)
+ {
+ return _swapper<Type,sizeof(Type)>()(tOut);
+ }
+
+private:
+
+ template <typename T, size_t size> struct _swapper;
+};
+
+template <typename T> struct ByteSwap::_swapper<T,2> {
+ T operator() (T tOut) {
+ Swap2(&tOut);
+ return tOut;
+ }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,4> {
+ T operator() (T tOut) {
+ Swap4(&tOut);
+ return tOut;
+ }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,8> {
+ T operator() (T tOut) {
+ Swap8(&tOut);
+ return tOut;
+ }
+};
+
+
+// --------------------------------------------------------------------------------------
+// ByteSwap macros for BigEndian/LittleEndian support
+// --------------------------------------------------------------------------------------
+#if (defined AI_BUILD_BIG_ENDIAN)
+# define AI_LE(t) (t)
+# define AI_BE(t) ByteSwap::Swapped(t)
+# define AI_LSWAP2(p)
+# define AI_LSWAP4(p)
+# define AI_LSWAP8(p)
+# define AI_LSWAP2P(p)
+# define AI_LSWAP4P(p)
+# define AI_LSWAP8P(p)
+# define LE_NCONST const
+# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
+# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
+# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
+# define AI_SWAP2P(p) ByteSwap::Swap2((p))
+# define AI_SWAP4P(p) ByteSwap::Swap4((p))
+# define AI_SWAP8P(p) ByteSwap::Swap8((p))
+# define BE_NCONST
+#else
+# define AI_BE(t) (t)
+# define AI_LE(t) ByteSwap::Swapped(t)
+# define AI_SWAP2(p)
+# define AI_SWAP4(p)
+# define AI_SWAP8(p)
+# define AI_SWAP2P(p)
+# define AI_SWAP4P(p)
+# define AI_SWAP8P(p)
+# define BE_NCONST const
+# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
+# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
+# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
+# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
+# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
+# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
+# define LE_NCONST
+#endif
+
+
+namespace Intern {
+
+// --------------------------------------------------------------------------------------------
+template <typename T, bool doit>
+struct ByteSwapper {
+ void operator() (T* inout) {
+ ByteSwap::Swap(inout);
+ }
+};
+
+template <typename T>
+struct ByteSwapper<T,false> {
+ void operator() (T*) {
+ }
+};
+
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess, typename T, bool RuntimeSwitch>
+struct Getter {
+ void operator() (T* inout, bool le) {
+#ifdef AI_BUILD_BIG_ENDIAN
+ le = le;
+#else
+ le = !le;
+#endif
+ if (le) {
+ ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
+ }
+ else ByteSwapper<T,false> () (inout);
+ }
+};
+
+template <bool SwapEndianess, typename T>
+struct Getter<SwapEndianess,T,false> {
+
+ void operator() (T* inout, bool /*le*/) {
+ // static branch
+ ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
+ }
+};
+} // end Intern
+} // end Assimp
+
+#endif //!! AI_BYTESWAPPER_H_INC
diff --git a/src/3rdparty/assimp/code/C4DImporter.cpp b/src/3rdparty/assimp/code/C4DImporter.cpp
new file mode 100644
index 000000000..252766ca6
--- /dev/null
+++ b/src/3rdparty/assimp/code/C4DImporter.cpp
@@ -0,0 +1,650 @@
+/*
+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 C4DImporter.cpp
+ * @brief Implementation of the Cinema4D importer class.
+ */
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
+
+// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
+// where it is turned on in the CMake settings.
+
+#ifndef _MSC_VER
+# error C4D support is currently MSVC only
+#endif
+
+#include "C4DImporter.h"
+#include "TinyFormatter.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
+
+#if defined(_M_X64) || defined(__amd64__)
+# define __C4D_64BIT
+#endif
+
+#define __PC
+#include "c4d_file.h"
+#include "default_alien_overloads.h"
+
+using namespace melange;
+
+// overload this function and fill in your own unique data
+void GetWriterInfo(int &id, String &appname)
+{
+ id = 2424226;
+ appname = "Open Asset Import Library";
+}
+
+using namespace Assimp;
+using namespace Assimp::Formatter;
+
+namespace Assimp {
+ template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
+}
+
+static const aiImporterDesc desc = {
+ "Cinema4D Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "c4d"
+};
+
+
+// ------------------------------------------------------------------------------------------------
+C4DImporter::C4DImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+C4DImporter::~C4DImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+ const std::string& extension = GetExtension(pFile);
+ if (extension == "c4d") {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ // TODO
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc* C4DImporter::GetInfo () const
+{
+ return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::SetupProperties(const Importer* /*pImp*/)
+{
+ // nothing to be done for the moment
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void C4DImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
+{
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ if( file.get() == NULL) {
+ ThrowException("failed to open file " + pFile);
+ }
+
+ const size_t file_size = file->FileSize();
+
+ std::vector<uint8_t> mBuffer(file_size);
+ file->Read(&mBuffer[0], 1, file_size);
+
+ Filename f;
+ f.SetMemoryReadMode(&mBuffer[0], file_size);
+
+ // open document first
+ BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
+ if(doc == NULL) {
+ ThrowException("failed to read document " + pFile);
+ }
+
+ pScene->mRootNode = new aiNode("<C4DRoot>");
+
+ // first convert all materials
+ ReadMaterials(doc->GetFirstMaterial());
+
+ // process C4D scenegraph recursively
+ try {
+ RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
+ }
+ catch(...) {
+ for(aiMesh* mesh : meshes) {
+ delete mesh;
+ }
+ BaseDocument::Free(doc);
+ throw;
+ }
+ BaseDocument::Free(doc);
+
+ // copy meshes over
+ pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
+ std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
+
+ // copy materials over, adding a default material if necessary
+ unsigned int mat_count = static_cast<unsigned int>(materials.size());
+ for(aiMesh* mesh : meshes) {
+ ai_assert(mesh->mMaterialIndex <= mat_count);
+ if(mesh->mMaterialIndex >= mat_count) {
+ ++mat_count;
+
+ ScopeGuard<aiMaterial> def_material(new aiMaterial());
+ const aiString name(AI_DEFAULT_MATERIAL_NAME);
+ def_material->AddProperty(&name, AI_MATKEY_NAME);
+
+ materials.push_back(def_material.dismiss());
+ break;
+ }
+ }
+
+ pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
+ std::copy(materials.begin(), materials.end(), pScene->mMaterials);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
+{
+ // based on Melange sample code (C4DImportExport.cpp)
+ while(shader) {
+ if(shader->GetType() == Xlayer) {
+ BaseContainer* container = shader->GetDataInstance();
+ GeData blend = container->GetData(SLA_LAYER_BLEND);
+ iBlendDataType* blend_list = reinterpret_cast<iBlendDataType*>(blend.GetCustomDataType(CUSTOMDATA_BLEND_LIST));
+ if (!blend_list)
+ {
+ LogWarn("ignoring XLayer shader: no blend list given");
+ continue;
+ }
+
+ LayerShaderLayer *lsl = dynamic_cast<LayerShaderLayer*>(blend_list->m_BlendLayers.GetObject(0));
+
+ // Ignore the actual layer blending - models for real-time rendering should not
+ // use them in a non-trivial way. Just try to find textures that we can apply
+ // to the model.
+ while (lsl)
+ {
+ if (lsl->GetType() == TypeFolder)
+ {
+ BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
+ LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
+
+ while (subLsl)
+ {
+ if (subLsl->GetType() == TypeShader) {
+ BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
+ if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
+ return true;
+ }
+ }
+
+ subLsl = subLsl->GetNext();
+ }
+ }
+ else if (lsl->GetType() == TypeShader) {
+ BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
+ if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
+ return true;
+ }
+ }
+
+ lsl = lsl->GetNext();
+ }
+ }
+ else if ( shader->GetType() == Xbitmap )
+ {
+ aiString path;
+ shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
+ path.length = ::strlen(path.data);
+ out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ return true;
+ }
+ else {
+ LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
+ }
+ shader = shader->GetNext();
+ }
+ return false;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
+{
+ // based on Melange sample code
+ while (mat)
+ {
+ const String& name = mat->GetName();
+ if (mat->GetType() == Mmaterial)
+ {
+ aiMaterial* out = new aiMaterial();
+ material_mapping[mat] = static_cast<unsigned int>(materials.size());
+ materials.push_back(out);
+
+ aiString ai_name;
+ name.GetCString(ai_name.data, MAXLEN-1);
+ ai_name.length = ::strlen(ai_name.data);
+ out->AddProperty(&ai_name, AI_MATKEY_NAME);
+
+ Material& m = dynamic_cast<Material&>(*mat);
+
+ if (m.GetChannelState(CHANNEL_COLOR))
+ {
+ GeData data;
+ mat->GetParameter(MATERIAL_COLOR_COLOR, data);
+ Vector color = data.GetVector();
+ mat->GetParameter(MATERIAL_COLOR_BRIGHTNESS, data);
+ const Float brightness = data.GetFloat();
+
+ color *= brightness;
+
+ aiVector3D v;
+ v.x = color.x;
+ v.y = color.y;
+ v.z = color.z;
+ out->AddProperty(&v, 1, AI_MATKEY_COLOR_DIFFUSE);
+ }
+
+ BaseShader* const shader = m.GetShader(MATERIAL_COLOR_SHADER);
+ if(shader) {
+ ReadShader(out, shader);
+ }
+ }
+ else
+ {
+ LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
+ }
+ mat = mat->GetNext();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
+{
+ ai_assert(parent != NULL);
+ std::vector<aiNode*> nodes;
+
+ // based on Melange sample code
+ while (object)
+ {
+ const String& name = object->GetName();
+ const LONG type = object->GetType();
+ const Matrix& ml = object->GetMl();
+
+ aiString string;
+ name.GetCString(string.data, MAXLEN-1);
+ string.length = ::strlen(string.data);
+ aiNode* const nd = new aiNode();
+
+ nd->mParent = parent;
+ nd->mName = string;
+
+ nd->mTransformation.a1 = ml.v1.x;
+ nd->mTransformation.b1 = ml.v1.y;
+ nd->mTransformation.c1 = ml.v1.z;
+
+ nd->mTransformation.a2 = ml.v2.x;
+ nd->mTransformation.b2 = ml.v2.y;
+ nd->mTransformation.c2 = ml.v2.z;
+
+ nd->mTransformation.a3 = ml.v3.x;
+ nd->mTransformation.b3 = ml.v3.y;
+ nd->mTransformation.c3 = ml.v3.z;
+
+ nd->mTransformation.a4 = ml.off.x;
+ nd->mTransformation.b4 = ml.off.y;
+ nd->mTransformation.c4 = ml.off.z;
+
+ nodes.push_back(nd);
+
+ GeData data;
+ if (type == Ocamera)
+ {
+ object->GetParameter(CAMERAOBJECT_FOV, data);
+ // TODO: read camera
+ }
+ else if (type == Olight)
+ {
+ // TODO: read light
+ }
+ else if (type == Opolygon)
+ {
+ aiMesh* const mesh = ReadMesh(object);
+ if(mesh != NULL) {
+ nd->mNumMeshes = 1;
+ nd->mMeshes = new unsigned int[1];
+ nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
+ meshes.push_back(mesh);
+ }
+ }
+ else {
+ LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
+ }
+
+ RecurseHierarchy(object->GetDown(), nd);
+ object = object->GetNext();
+ }
+
+ // copy nodes over to parent
+ parent->mNumChildren = static_cast<unsigned int>(nodes.size());
+ parent->mChildren = new aiNode*[parent->mNumChildren]();
+ std::copy(nodes.begin(), nodes.end(), parent->mChildren);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+aiMesh* C4DImporter::ReadMesh(BaseObject* object)
+{
+ assert(object != NULL && object->GetType() == Opolygon);
+
+ // based on Melange sample code
+ PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
+ ai_assert(polyObject != NULL);
+
+ const LONG pointCount = polyObject->GetPointCount();
+ const LONG polyCount = polyObject->GetPolygonCount();
+ if(!polyObject || !pointCount) {
+ LogWarn("ignoring mesh with zero vertices or faces");
+ return NULL;
+ }
+
+ const Vector* points = polyObject->GetPointR();
+ ai_assert(points != NULL);
+
+ const CPolygon* polys = polyObject->GetPolygonR();
+ ai_assert(polys != NULL);
+
+ ScopeGuard<aiMesh> mesh(new aiMesh());
+ mesh->mNumFaces = static_cast<unsigned int>(polyCount);
+ aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
+
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ mesh->mMaterialIndex = 0;
+
+ unsigned int vcount = 0;
+
+ // first count vertices
+ for (LONG i = 0; i < polyCount; i++)
+ {
+ vcount += 3;
+
+ // TODO: do we also need to handle lines or points with similar checks?
+ if (polys[i].c != polys[i].d)
+ {
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ ++vcount;
+ }
+ }
+
+ ai_assert(vcount > 0);
+
+ mesh->mNumVertices = vcount;
+ aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ aiVector3D* normals, *uvs, *tangents, *bitangents;
+ unsigned int n = 0;
+
+ // check if there are normals, tangents or UVW coordinates
+ BaseTag* tag = object->GetTag(Tnormal);
+ NormalTag* normals_src = NULL;
+ if(tag) {
+ normals_src = dynamic_cast<NormalTag*>(tag);
+ normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
+ }
+
+ tag = object->GetTag(Ttangent);
+ TangentTag* tangents_src = NULL;
+ if(tag) {
+ tangents_src = dynamic_cast<TangentTag*>(tag);
+ tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
+ bitangents = mesh->mBitangents = new aiVector3D[mesh->mNumVertices]();
+ }
+
+ tag = object->GetTag(Tuvw);
+ UVWTag* uvs_src = NULL;
+ if(tag) {
+ uvs_src = dynamic_cast<UVWTag*>(tag);
+ uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
+ }
+
+ // copy vertices and extra channels over and populate faces
+ for (LONG i = 0; i < polyCount; ++i, ++face)
+ {
+ ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
+ const Vector& pointA = points[polys[i].a];
+ verts->x = pointA.x;
+ verts->y = pointA.y;
+ verts->z = pointA.z;
+ ++verts;
+
+ ai_assert(polys[i].b < pointCount && polys[i].b >= 0);
+ const Vector& pointB = points[polys[i].b];
+ verts->x = pointB.x;
+ verts->y = pointB.y;
+ verts->z = pointB.z;
+ ++verts;
+
+ ai_assert(polys[i].c < pointCount && polys[i].c >= 0);
+ const Vector& pointC = points[polys[i].c];
+ verts->x = pointC.x;
+ verts->y = pointC.y;
+ verts->z = pointC.z;
+ ++verts;
+
+ // TODO: do we also need to handle lines or points with similar checks?
+ if (polys[i].c != polys[i].d)
+ {
+ ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
+
+ face->mNumIndices = 4;
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ const Vector& pointD = points[polys[i].d];
+ verts->x = pointD.x;
+ verts->y = pointD.y;
+ verts->z = pointD.z;
+ ++verts;
+ }
+ else {
+ face->mNumIndices = 3;
+ }
+ face->mIndices = new unsigned int[face->mNumIndices];
+ for(unsigned int j = 0; j < face->mNumIndices; ++j) {
+ face->mIndices[j] = n++;
+ }
+
+ // copy normals
+ if (normals_src) {
+ if(i >= normals_src->GetDataCount()) {
+ LogError("unexpected number of normals, ignoring");
+ }
+ else {
+ ConstNormalHandle normal_handle = normals_src->GetDataAddressR();
+ NormalStruct nor;
+ NormalTag::Get(normal_handle, i, nor);
+ normals->x = nor.a.x;
+ normals->y = nor.a.y;
+ normals->z = nor.a.z;
+ ++normals;
+
+ normals->x = nor.b.x;
+ normals->y = nor.b.y;
+ normals->z = nor.b.z;
+ ++normals;
+
+ normals->x = nor.c.x;
+ normals->y = nor.c.y;
+ normals->z = nor.c.z;
+ ++normals;
+
+ if(face->mNumIndices == 4) {
+ normals->x = nor.d.x;
+ normals->y = nor.d.y;
+ normals->z = nor.d.z;
+ ++normals;
+ }
+ }
+ }
+
+ // copy tangents and bitangents
+ if (tangents_src) {
+
+ for(unsigned int k = 0; k < face->mNumIndices; ++k) {
+ LONG l;
+ switch(k) {
+ case 0:
+ l = polys[i].a;
+ break;
+ case 1:
+ l = polys[i].b;
+ break;
+ case 2:
+ l = polys[i].c;
+ break;
+ case 3:
+ l = polys[i].d;
+ break;
+ default:
+ ai_assert(false);
+ }
+ if(l >= tangents_src->GetDataCount()) {
+ LogError("unexpected number of tangents, ignoring");
+ break;
+ }
+
+ Tangent tan = tangents_src->GetDataR()[l];
+ tangents->x = tan.vl.x;
+ tangents->y = tan.vl.y;
+ tangents->z = tan.vl.z;
+ ++tangents;
+
+ bitangents->x = tan.vr.x;
+ bitangents->y = tan.vr.y;
+ bitangents->z = tan.vr.z;
+ ++bitangents;
+ }
+ }
+
+ // copy UVs
+ if (uvs_src) {
+ if(i >= uvs_src->GetDataCount()) {
+ LogError("unexpected number of UV coordinates, ignoring");
+ }
+ else {
+ UVWStruct uvw;
+ uvs_src->Get(uvs_src->GetDataAddressR(),i,uvw);
+
+ uvs->x = uvw.a.x;
+ uvs->y = 1.0f-uvw.a.y;
+ uvs->z = uvw.a.z;
+ ++uvs;
+
+ uvs->x = uvw.b.x;
+ uvs->y = 1.0f-uvw.b.y;
+ uvs->z = uvw.b.z;
+ ++uvs;
+
+ uvs->x = uvw.c.x;
+ uvs->y = 1.0f-uvw.c.y;
+ uvs->z = uvw.c.z;
+ ++uvs;
+
+ if(face->mNumIndices == 4) {
+ uvs->x = uvw.d.x;
+ uvs->y = 1.0f-uvw.d.y;
+ uvs->z = uvw.d.z;
+ ++uvs;
+ }
+ }
+ }
+ }
+
+ mesh->mMaterialIndex = ResolveMaterial(polyObject);
+ return mesh.dismiss();
+}
+
+
+// ------------------------------------------------------------------------------------------------
+unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
+{
+ ai_assert(obj != NULL);
+
+ const unsigned int mat_count = static_cast<unsigned int>(materials.size());
+
+ BaseTag* tag = obj->GetTag(Ttexture);
+ if(tag == NULL) {
+ return mat_count;
+ }
+
+ TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
+
+ BaseMaterial* const mat = ttag.GetMaterial();
+ assert(mat != NULL);
+
+ const MaterialMap::const_iterator it = material_mapping.find(mat);
+ if(it == material_mapping.end()) {
+ return mat_count;
+ }
+
+ ai_assert((*it).second < mat_count);
+ return (*it).second;
+}
+
+#endif // ASSIMP_BUILD_NO_C4D_IMPORTER
+
diff --git a/src/3rdparty/assimp/code/C4DImporter.h b/src/3rdparty/assimp/code/C4DImporter.h
new file mode 100644
index 000000000..3ba2a17c6
--- /dev/null
+++ b/src/3rdparty/assimp/code/C4DImporter.h
@@ -0,0 +1,123 @@
+/*
+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 C4DImporter.h
+ * @brief Declaration of the Cinema4D (*.c4d) importer class.
+ */
+#ifndef INCLUDED_AI_CINEMA_4D_LOADER_H
+#define INCLUDED_AI_CINEMA_4D_LOADER_H
+
+#include "BaseImporter.h"
+#include "LogAux.h"
+
+#include <set>
+struct aiNode;
+struct aiMesh;
+struct aiMaterial;
+
+struct aiImporterDesc;
+
+namespace melange {
+ class BaseObject; // c4d_file.h
+ class PolygonObject;
+ class BaseMaterial;
+ class BaseShader;
+}
+
+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;
+ }
+
+// -------------------------------------------------------------------------------------------
+/** Importer class to load Cinema4D files using the Melange library to be obtained from
+ * www.plugincafe.com
+ *
+ * Note that Melange is not free software. */
+// -------------------------------------------------------------------------------------------
+class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
+{
+public:
+
+ C4DImporter();
+ ~C4DImporter();
+
+
+public:
+
+ // --------------------
+ 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:
+
+ void ReadMaterials(melange::BaseMaterial* mat);
+ void RecurseHierarchy(melange::BaseObject* object, aiNode* parent);
+ aiMesh* ReadMesh(melange::BaseObject* object);
+ unsigned int ResolveMaterial(melange::PolygonObject* obj);
+
+ bool ReadShader(aiMaterial* out, melange::BaseShader* shader);
+
+ std::vector<aiMesh*> meshes;
+ std::vector<aiMaterial*> materials;
+
+ typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap;
+ MaterialMap material_mapping;
+
+}; // !class C4DImporter
+
+} // end of namespace Assimp
+#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
+
diff --git a/src/3rdparty/assimp/code/CInterfaceIOWrapper.h b/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
index d92c5ad72..beffd8678 100644
--- a/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
+++ b/src/3rdparty/assimp/code/CInterfaceIOWrapper.h
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -44,63 +44,65 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_CIOSYSTEM_H_INCLUDED
#define AI_CIOSYSTEM_H_INCLUDED
-#include "../include/assimp/cfileio.h"
+#include <assimp/cfileio.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+
+namespace Assimp {
-namespace Assimp {
-
// ------------------------------------------------------------------------------------------------
// Custom IOStream implementation for the C-API
class CIOStreamWrapper : public IOStream
{
- friend class CIOSystemWrapper;
+ friend class CIOSystemWrapper;
public:
- CIOStreamWrapper(aiFile* pFile)
- : mFile(pFile)
- {}
-
- // ...................................................................
- size_t 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 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 Seek(size_t pOffset,
- aiOrigin pOrigin
- ){
- return mFile->SeekProc(mFile,pOffset,pOrigin);
- }
-
- // ...................................................................
- size_t Tell(void) const {
- return mFile->TellProc(mFile);
- }
-
- // ...................................................................
- size_t FileSize() const {
- return mFile->FileSizeProc(mFile);
- }
-
- // ...................................................................
- void Flush () {
- return mFile->FlushProc(mFile);
- }
+ explicit CIOStreamWrapper(aiFile* pFile)
+ : mFile(pFile)
+ {}
+
+ // ...................................................................
+ size_t 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 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 Seek(size_t pOffset,
+ aiOrigin pOrigin
+ ){
+ return mFile->SeekProc(mFile,pOffset,pOrigin);
+ }
+
+ // ...................................................................
+ size_t Tell(void) const {
+ return mFile->TellProc(mFile);
+ }
+
+ // ...................................................................
+ size_t FileSize() const {
+ return mFile->FileSizeProc(mFile);
+ }
+
+ // ...................................................................
+ void Flush () {
+ return mFile->FlushProc(mFile);
+ }
private:
- aiFile* mFile;
+ aiFile* mFile;
};
// ------------------------------------------------------------------------------------------------
@@ -108,48 +110,48 @@ private:
class CIOSystemWrapper : public IOSystem
{
public:
- CIOSystemWrapper(aiFileIO* pFile)
- : mFileSystem(pFile)
- {}
-
- // ...................................................................
- bool Exists( const char* pFile) const {
- aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
- if (p){
- mFileSystem->CloseProc(mFileSystem,p);
- return true;
- }
- return false;
- }
-
- // ...................................................................
- char getOsSeparator() const {
+ explicit CIOSystemWrapper(aiFileIO* pFile)
+ : mFileSystem(pFile)
+ {}
+
+ // ...................................................................
+ bool Exists( const char* pFile) const {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
+ if (p){
+ mFileSystem->CloseProc(mFileSystem,p);
+ return true;
+ }
+ return false;
+ }
+
+ // ...................................................................
+ char getOsSeparator() const {
#ifndef _WIN32
- return '/';
+ return '/';
#else
- return '\\';
+ return '\\';
#endif
- }
-
- // ...................................................................
- IOStream* Open(const char* pFile,const char* pMode = "rb") {
- aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
- if (!p) {
- return NULL;
- }
- return new CIOStreamWrapper(p);
- }
-
- // ...................................................................
- void Close( IOStream* pFile) {
- if (!pFile) {
- return;
- }
- mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
- delete pFile;
- }
+ }
+
+ // ...................................................................
+ IOStream* Open(const char* pFile,const char* pMode = "rb") {
+ aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
+ if (!p) {
+ return NULL;
+ }
+ return new CIOStreamWrapper(p);
+ }
+
+ // ...................................................................
+ void Close( IOStream* pFile) {
+ if (!pFile) {
+ return;
+ }
+ mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
+ delete pFile;
+ }
private:
- aiFileIO* mFileSystem;
+ aiFileIO* mFileSystem;
};
}
diff --git a/src/3rdparty/assimp/code/CMakeLists.txt b/src/3rdparty/assimp/code/CMakeLists.txt
index 796711316..35ecf5020 100644
--- a/src/3rdparty/assimp/code/CMakeLists.txt
+++ b/src/3rdparty/assimp/code/CMakeLists.txt
@@ -1,3 +1,41 @@
+# 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.
+#
+#----------------------------------------------------------------------
+
# Listing and grouping of all the source files.
# 1) Set the file lists for each component
# 2) Create a Source Group for each component, for IDE project orginization
@@ -8,735 +46,801 @@ cmake_minimum_required( VERSION 2.6 )
SET( HEADER_PATH ../include/assimp )
SET( COMPILER_HEADERS
- ${HEADER_PATH}/Compiler/pushpack1.h
- ${HEADER_PATH}/Compiler/poppack1.h
- ${HEADER_PATH}/Compiler/pstdint.h
+ ${HEADER_PATH}/Compiler/pushpack1.h
+ ${HEADER_PATH}/Compiler/poppack1.h
+ ${HEADER_PATH}/Compiler/pstdint.h
)
SOURCE_GROUP( Compiler FILES ${COMPILER_HEADERS})
SET( PUBLIC_HEADERS
- ${HEADER_PATH}/anim.h
- ${HEADER_PATH}/ai_assert.h
- ${HEADER_PATH}/camera.h
- ${HEADER_PATH}/color4.h
- ${HEADER_PATH}/color4.inl
- ${HEADER_PATH}/config.h
- ${HEADER_PATH}/defs.h
- ${HEADER_PATH}/cfileio.h
- ${HEADER_PATH}/light.h
- ${HEADER_PATH}/material.h
- ${HEADER_PATH}/material.inl
- ${HEADER_PATH}/matrix3x3.h
- ${HEADER_PATH}/matrix3x3.inl
- ${HEADER_PATH}/matrix4x4.h
- ${HEADER_PATH}/matrix4x4.inl
- ${HEADER_PATH}/mesh.h
- ${HEADER_PATH}/postprocess.h
- ${HEADER_PATH}/quaternion.h
- ${HEADER_PATH}/quaternion.inl
- ${HEADER_PATH}/scene.h
- ${HEADER_PATH}/metadata.h
- ${HEADER_PATH}/texture.h
- ${HEADER_PATH}/types.h
- ${HEADER_PATH}/vector2.h
- ${HEADER_PATH}/vector2.inl
- ${HEADER_PATH}/vector3.h
- ${HEADER_PATH}/vector3.inl
- ${HEADER_PATH}/version.h
- ${HEADER_PATH}/cimport.h
- ${HEADER_PATH}/importerdesc.h
- ${HEADER_PATH}/Importer.hpp
- ${HEADER_PATH}/DefaultLogger.hpp
- ${HEADER_PATH}/ProgressHandler.hpp
- ${HEADER_PATH}/IOStream.hpp
- ${HEADER_PATH}/IOSystem.hpp
- ${HEADER_PATH}/Logger.hpp
- ${HEADER_PATH}/LogStream.hpp
- ${HEADER_PATH}/NullLogger.hpp
- ${HEADER_PATH}/cexport.h
- ${HEADER_PATH}/Exporter.hpp
+ ${HEADER_PATH}/anim.h
+ ${HEADER_PATH}/ai_assert.h
+ ${HEADER_PATH}/camera.h
+ ${HEADER_PATH}/color4.h
+ ${HEADER_PATH}/color4.inl
+ ${HEADER_PATH}/config.h
+ ${HEADER_PATH}/defs.h
+ ${HEADER_PATH}/cfileio.h
+ ${HEADER_PATH}/light.h
+ ${HEADER_PATH}/material.h
+ ${HEADER_PATH}/material.inl
+ ${HEADER_PATH}/matrix3x3.h
+ ${HEADER_PATH}/matrix3x3.inl
+ ${HEADER_PATH}/matrix4x4.h
+ ${HEADER_PATH}/matrix4x4.inl
+ ${HEADER_PATH}/mesh.h
+ ${HEADER_PATH}/postprocess.h
+ ${HEADER_PATH}/quaternion.h
+ ${HEADER_PATH}/quaternion.inl
+ ${HEADER_PATH}/scene.h
+ ${HEADER_PATH}/metadata.h
+ ${HEADER_PATH}/texture.h
+ ${HEADER_PATH}/types.h
+ ${HEADER_PATH}/vector2.h
+ ${HEADER_PATH}/vector2.inl
+ ${HEADER_PATH}/vector3.h
+ ${HEADER_PATH}/vector3.inl
+ ${HEADER_PATH}/version.h
+ ${HEADER_PATH}/cimport.h
+ ${HEADER_PATH}/importerdesc.h
+ ${HEADER_PATH}/Importer.hpp
+ ${HEADER_PATH}/DefaultLogger.hpp
+ ${HEADER_PATH}/ProgressHandler.hpp
+ ${HEADER_PATH}/IOStream.hpp
+ ${HEADER_PATH}/IOSystem.hpp
+ ${HEADER_PATH}/Logger.hpp
+ ${HEADER_PATH}/LogStream.hpp
+ ${HEADER_PATH}/NullLogger.hpp
+ ${HEADER_PATH}/cexport.h
+ ${HEADER_PATH}/Exporter.hpp
)
SET( Core_SRCS
- Assimp.cpp
+ Assimp.cpp
)
-SET( Boost_SRCS
- BoostWorkaround/boost/math/common_factor_rt.hpp
- BoostWorkaround/boost/foreach.hpp
- BoostWorkaround/boost/format.hpp
- BoostWorkaround/boost/scoped_array.hpp
- BoostWorkaround/boost/scoped_ptr.hpp
- BoostWorkaround/boost/shared_array.hpp
- BoostWorkaround/boost/shared_ptr.hpp
- BoostWorkaround/boost/make_shared.hpp
- BoostWorkaround/boost/static_assert.hpp
- BoostWorkaround/boost/tuple/tuple.hpp
-)
-SOURCE_GROUP(Boost FILES ${Boost_SRCS})
-
SET( Logging_SRCS
- ${HEADER_PATH}/DefaultLogger.hpp
- ${HEADER_PATH}/LogStream.hpp
- ${HEADER_PATH}/Logger.hpp
- ${HEADER_PATH}/NullLogger.hpp
- Win32DebugLogStream.h
- DefaultLogger.cpp
- FileLogStream.h
- StdOStreamLogStream.h
+ ${HEADER_PATH}/DefaultLogger.hpp
+ ${HEADER_PATH}/LogStream.hpp
+ ${HEADER_PATH}/Logger.hpp
+ ${HEADER_PATH}/NullLogger.hpp
+ Win32DebugLogStream.h
+ DefaultLogger.cpp
+ FileLogStream.h
+ StdOStreamLogStream.h
)
SOURCE_GROUP(Logging FILES ${Logging_SRCS})
SET( Common_SRCS
- fast_atof.h
- qnan.h
- BaseImporter.cpp
- BaseImporter.h
- BaseProcess.cpp
- BaseProcess.h
- Importer.h
- ScenePrivate.h
- PostStepRegistry.cpp
- ImporterRegistry.cpp
- ByteSwap.h
- DefaultProgressHandler.h
- DefaultIOStream.cpp
- DefaultIOStream.h
- DefaultIOSystem.cpp
- DefaultIOSystem.h
- CInterfaceIOWrapper.h
- Hash.h
- Importer.cpp
- IFF.h
- MemoryIOWrapper.h
- ParsingUtils.h
- StreamReader.h
- StringComparison.h
- SGSpatialSort.cpp
- SGSpatialSort.h
- VertexTriangleAdjacency.cpp
- VertexTriangleAdjacency.h
- GenericProperty.h
- SpatialSort.cpp
- SpatialSort.h
- SceneCombiner.cpp
- SceneCombiner.h
- ScenePreprocessor.cpp
- ScenePreprocessor.h
- SkeletonMeshBuilder.cpp
- SkeletonMeshBuilder.h
- SplitByBoneCountProcess.cpp
- SplitByBoneCountProcess.h
- SmoothingGroups.h
- StandardShapes.cpp
- StandardShapes.h
- TargetAnimation.cpp
- TargetAnimation.h
- RemoveComments.cpp
- RemoveComments.h
- Subdivision.cpp
- Subdivision.h
- Vertex.h
- LineSplitter.h
- TinyFormatter.h
- Profiler.h
- LogAux.h
- Bitmap.cpp
- Bitmap.h
+ fast_atof.h
+ qnan.h
+ BaseImporter.cpp
+ BaseImporter.h
+ BaseProcess.cpp
+ BaseProcess.h
+ Importer.h
+ ScenePrivate.h
+ PostStepRegistry.cpp
+ ImporterRegistry.cpp
+ ByteSwapper.h
+ DefaultProgressHandler.h
+ DefaultIOStream.cpp
+ DefaultIOStream.h
+ DefaultIOSystem.cpp
+ DefaultIOSystem.h
+ CInterfaceIOWrapper.h
+ Hash.h
+ Importer.cpp
+ IFF.h
+ MemoryIOWrapper.h
+ ParsingUtils.h
+ StreamReader.h
+ StreamWriter.h
+ StringComparison.h
+ StringUtils.h
+ SGSpatialSort.cpp
+ SGSpatialSort.h
+ VertexTriangleAdjacency.cpp
+ VertexTriangleAdjacency.h
+ GenericProperty.h
+ SpatialSort.cpp
+ SpatialSort.h
+ SceneCombiner.cpp
+ SceneCombiner.h
+ ScenePreprocessor.cpp
+ ScenePreprocessor.h
+ SkeletonMeshBuilder.cpp
+ SkeletonMeshBuilder.h
+ SplitByBoneCountProcess.cpp
+ SplitByBoneCountProcess.h
+ SmoothingGroups.h
+ StandardShapes.cpp
+ StandardShapes.h
+ TargetAnimation.cpp
+ TargetAnimation.h
+ RemoveComments.cpp
+ RemoveComments.h
+ Subdivision.cpp
+ Subdivision.h
+ Vertex.h
+ LineSplitter.h
+ TinyFormatter.h
+ Profiler.h
+ LogAux.h
+ Bitmap.cpp
+ Bitmap.h
+ XMLTools.h
+ Version.cpp
)
SOURCE_GROUP(Common FILES ${Common_SRCS})
-SET( 3DS_SRCS
- 3DSConverter.cpp
- 3DSHelper.h
- 3DSLoader.cpp
- 3DSLoader.h
+IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+ SET( C4D_SRCS
+ C4DImporter.cpp
+ C4DImporter.h
+ )
+ SOURCE_GROUP( C4D FILES ${C4D_SRCS})
+ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+
+# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
+# this way selective loaders can be compiled (reduces filesize + compile time)
+MACRO(ADD_ASSIMP_IMPORTER name)
+ OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" TRUE)
+ IF(ASSIMP_BUILD_${name}_IMPORTER)
+ LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
+ SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
+ SET(${name}_SRCS ${ARGN})
+ SOURCE_GROUP(${name} FILES ${ARGN})
+ ELSE()
+ SET(${name}_SRC "")
+ SET(ASSIMP_IMPORTERS_DISABLED "${ASSIMP_IMPORTERS_DISABLED} ${name}")
+ add_definitions(-DASSIMP_BUILD_NO_${name}_IMPORTER)
+ ENDIF()
+ENDMACRO()
+
+SET(ASSIMP_LOADER_SRCS "")
+SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
+SET(ASSIMP_IMPORTERS_DISABLED "") # disabled list (used to print)
+
+ADD_ASSIMP_IMPORTER( 3DS
+ 3DSConverter.cpp
+ 3DSHelper.h
+ 3DSLoader.cpp
+ 3DSLoader.h
+ 3DSExporter.h
+ 3DSExporter.cpp
)
-SOURCE_GROUP(3DS FILES ${3DS_SRCS})
-SET( AC_SRCS
- ACLoader.cpp
- ACLoader.h
+ADD_ASSIMP_IMPORTER( AC
+ ACLoader.cpp
+ ACLoader.h
)
-SOURCE_GROUP( AC FILES ${AC_SRCS})
-SET( ASE_SRCS
- ASELoader.cpp
- ASELoader.h
- ASEParser.cpp
- ASEParser.h
+ADD_ASSIMP_IMPORTER( ASE
+ ASELoader.cpp
+ ASELoader.h
+ ASEParser.cpp
+ ASEParser.h
)
-SOURCE_GROUP( ASE FILES ${ASE_SRCS})
-SET( B3D_SRCS
- B3DImporter.cpp
- B3DImporter.h
+ADD_ASSIMP_IMPORTER( ASSBIN
+ AssbinExporter.h
+ AssbinExporter.cpp
+ AssbinLoader.h
+ AssbinLoader.cpp
)
-SOURCE_GROUP( B3D FILES ${B3D_SRCS})
-SET( BVH_SRCS
- BVHLoader.cpp
- BVHLoader.h
+ADD_ASSIMP_IMPORTER( ASSXML
+ AssxmlExporter.h
+ AssxmlExporter.cpp
)
-SOURCE_GROUP( BVH FILES ${BVH_SRCS})
-SET( Collada_SRCS
- ColladaHelper.h
- ColladaLoader.cpp
- ColladaLoader.h
- ColladaParser.cpp
- ColladaParser.h
- ColladaExporter.h
- ColladaExporter.cpp
+ADD_ASSIMP_IMPORTER( B3D
+ B3DImporter.cpp
+ B3DImporter.h
)
-SOURCE_GROUP( Collada FILES ${Collada_SRCS})
-SET( DXF_SRCS
- DXFLoader.cpp
- DXFLoader.h
- DXFHelper.h
+ADD_ASSIMP_IMPORTER( BVH
+ BVHLoader.cpp
+ BVHLoader.h
)
-SOURCE_GROUP( DXF FILES ${DXF_SRCS})
-SET( CSM_SRCS
- CSMLoader.cpp
- CSMLoader.h
+ADD_ASSIMP_IMPORTER( COLLADA
+ ColladaHelper.h
+ ColladaLoader.cpp
+ ColladaLoader.h
+ ColladaParser.cpp
+ ColladaParser.h
+ ColladaExporter.h
+ ColladaExporter.cpp
)
-SOURCE_GROUP( CSM FILES ${CSM_SRCS})
-SET( HMP_SRCS
- HMPFileData.h
- HMPLoader.cpp
- HMPLoader.h
- HalfLifeFileData.h
+ADD_ASSIMP_IMPORTER( DXF
+ DXFLoader.cpp
+ DXFLoader.h
+ DXFHelper.h
)
-SOURCE_GROUP( HMP FILES ${HMP_SRCS})
-SET( Irr_SRCS
- IRRLoader.cpp
- IRRLoader.h
- IRRMeshLoader.cpp
- IRRMeshLoader.h
- IRRShared.cpp
- IRRShared.h
+ADD_ASSIMP_IMPORTER( CSM
+ CSMLoader.cpp
+ CSMLoader.h
)
-SOURCE_GROUP( Irr FILES ${Irr_SRCS})
-SET( LWO_SRCS
- LWOAnimation.cpp
- LWOAnimation.h
- LWOBLoader.cpp
- LWOFileData.h
- LWOLoader.cpp
- LWOLoader.h
- LWOMaterial.cpp
+ADD_ASSIMP_IMPORTER( HMP
+ HMPFileData.h
+ HMPLoader.cpp
+ HMPLoader.h
+ HalfLifeFileData.h
)
-SOURCE_GROUP( LWO FILES ${LWO_SRCS})
-SET( LWS_SRCS
- LWSLoader.cpp
- LWSLoader.h
+ADD_ASSIMP_IMPORTER( IRRMESH
+ IRRMeshLoader.cpp
+ IRRMeshLoader.h
+ IRRShared.cpp
+ IRRShared.h
)
-SOURCE_GROUP( LWS FILES ${LWS_SRCS})
+ADD_ASSIMP_IMPORTER( IRR
+ IRRLoader.cpp
+ IRRLoader.h
+ IRRShared.cpp
+ IRRShared.h
+)
+
+ADD_ASSIMP_IMPORTER( LWO
+ LWOAnimation.cpp
+ LWOAnimation.h
+ LWOBLoader.cpp
+ LWOFileData.h
+ LWOLoader.cpp
+ LWOLoader.h
+ LWOMaterial.cpp
+)
+ADD_ASSIMP_IMPORTER( LWS
+ LWSLoader.cpp
+ LWSLoader.h
+)
-SET( MD2_SRCS
- MD2FileData.h
- MD2Loader.cpp
- MD2Loader.h
- MD2NormalTable.h
+ADD_ASSIMP_IMPORTER( MD2
+ MD2FileData.h
+ MD2Loader.cpp
+ MD2Loader.h
+ MD2NormalTable.h
)
-SOURCE_GROUP( MD2 FILES ${MD2_SRCS})
-SET( MD3_SRCS
- MD3FileData.h
- MD3Loader.cpp
- MD3Loader.h
+ADD_ASSIMP_IMPORTER( MD3
+ MD3FileData.h
+ MD3Loader.cpp
+ MD3Loader.h
)
-SOURCE_GROUP( MD3 FILES ${MD3_SRCS})
-SET( MD5_SRCS
- MD5Loader.cpp
- MD5Loader.h
- MD5Parser.cpp
- MD5Parser.h
+ADD_ASSIMP_IMPORTER( MD5
+ MD5Loader.cpp
+ MD5Loader.h
+ MD5Parser.cpp
+ MD5Parser.h
)
-SOURCE_GROUP( MD5 FILES ${MD5_SRCS})
-SET( MDC_SRCS
- MDCFileData.h
- MDCLoader.cpp
- MDCLoader.h
- MDCNormalTable.h
+ADD_ASSIMP_IMPORTER( MDC
+ MDCFileData.h
+ MDCLoader.cpp
+ MDCLoader.h
+ MDCNormalTable.h
)
-SOURCE_GROUP( MDC FILES ${MDC_SRCS})
-SET( MDL_SRCS
- MDLDefaultColorMap.h
- MDLFileData.h
- MDLLoader.cpp
- MDLLoader.h
- MDLMaterialLoader.cpp
+ADD_ASSIMP_IMPORTER( MDL
+ MDLDefaultColorMap.h
+ MDLFileData.h
+ MDLLoader.cpp
+ MDLLoader.h
+ MDLMaterialLoader.cpp
)
-SOURCE_GROUP( MDL FILES ${MDL_SRCS})
SET( MaterialSystem_SRCS
- MaterialSystem.cpp
- MaterialSystem.h
+ MaterialSystem.cpp
+ MaterialSystem.h
)
SOURCE_GROUP( MaterialSystem FILES ${MaterialSystem_SRCS})
-SET( NFF_SRCS
- NFFLoader.cpp
- NFFLoader.h
-)
-SOURCE_GROUP( NFF FILES ${NFF_SRCS})
-
-SET( NDO_SRCS
- NDOLoader.cpp
- NDOLoader.h
-)
-SOURCE_GROUP( NDO FILES ${NDO_SRCS})
-
-SET( OFFFormat_SRCS
- OFFLoader.cpp
- OFFLoader.h
-)
-SOURCE_GROUP( OFFFormat FILES ${OFFFormat_SRCS})
-
-SET( Obj_SRCS
- ObjFileData.h
- ObjFileImporter.cpp
- ObjFileImporter.h
- ObjFileMtlImporter.cpp
- ObjFileMtlImporter.h
- ObjFileParser.cpp
- ObjFileParser.h
- ObjTools.h
-
- ObjExporter.h
- ObjExporter.cpp
-)
-SOURCE_GROUP( Obj FILES ${Obj_SRCS})
-
-SET( Ogre_SRCS
- OgreImporter.h
- OgreStructs.h
- OgreParsingUtils.h
- OgreBinarySerializer.h
- OgreXmlSerializer.h
- OgreImporter.cpp
- OgreStructs.cpp
- OgreBinarySerializer.cpp
- OgreXmlSerializer.cpp
- OgreMaterial.cpp
-)
-SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
-
-SET( Ply_SRCS
- PlyLoader.cpp
- PlyLoader.h
- PlyParser.cpp
- PlyParser.h
- PlyExporter.cpp
- PlyExporter.h
-)
-SOURCE_GROUP( Ply FILES ${Ply_SRCS})
-
-SET(MS3D_SRCS
- MS3DLoader.cpp
- MS3DLoader.h
-)
-SOURCE_GROUP( MS3D FILES ${MS3D_SRCS})
-
-SET(COB_SRCS
- COBLoader.cpp
- COBLoader.h
- COBScene.h
-)
-SOURCE_GROUP( COB FILES ${COB_SRCS})
-
-SET(BLENDER_SRCS
- BlenderLoader.cpp
- BlenderLoader.h
- BlenderDNA.cpp
- BlenderDNA.h
- BlenderDNA.inl
- BlenderScene.cpp
- BlenderScene.h
- BlenderSceneGen.h
- BlenderIntermediate.h
- BlenderModifier.h
- BlenderModifier.cpp
- BlenderBMesh.h
- BlenderBMesh.cpp
- BlenderTessellator.h
- BlenderTessellator.cpp
-)
-SOURCE_GROUP( BLENDER FILES ${BLENDER_SRCS})
-
-SET(IFC_SRCS
- IFCLoader.cpp
- IFCLoader.h
- IFCReaderGen.cpp
- IFCReaderGen.h
- IFCUtil.h
- IFCUtil.cpp
- IFCGeometry.cpp
- IFCMaterial.cpp
- IFCProfile.cpp
- IFCCurve.cpp
- IFCBoolean.cpp
- IFCOpenings.cpp
- STEPFile.h
- STEPFileReader.h
- STEPFileReader.cpp
- STEPFileEncoding.cpp
- STEPFileEncoding.h
-)
-SOURCE_GROUP( IFC FILES ${IFC_SRCS})
-
-SET( XGL_SRCS
- XGLLoader.cpp
- XGLLoader.h
-)
-SOURCE_GROUP( XGL FILES ${XGL_SRCS})
-
-
-SET(FBX_SRCS
- FBXImporter.cpp
- FBXCompileConfig.h
- FBXImporter.h
- FBXParser.cpp
- FBXParser.h
- FBXTokenizer.cpp
- FBXTokenizer.h
- FBXImportSettings.h
- FBXConverter.h
- FBXConverter.cpp
- FBXUtil.h
- FBXUtil.cpp
- FBXDocument.h
- FBXDocument.cpp
- FBXProperties.h
- FBXProperties.cpp
- FBXMeshGeometry.cpp
- FBXMaterial.cpp
- FBXModel.cpp
- FBXAnimation.cpp
- FBXNodeAttribute.cpp
- FBXDeformer.cpp
- FBXBinaryTokenizer.cpp
- FBXDocumentUtil.cpp
-)
-SOURCE_GROUP( FBX FILES ${FBX_SRCS})
-
+ADD_ASSIMP_IMPORTER( NFF
+ NFFLoader.cpp
+ NFFLoader.h
+)
+
+ADD_ASSIMP_IMPORTER( NDO
+ NDOLoader.cpp
+ NDOLoader.h
+)
+
+ADD_ASSIMP_IMPORTER( OFF
+ OFFLoader.cpp
+ OFFLoader.h
+)
+
+ADD_ASSIMP_IMPORTER( OBJ
+ ObjFileData.h
+ ObjFileImporter.cpp
+ ObjFileImporter.h
+ ObjFileMtlImporter.cpp
+ ObjFileMtlImporter.h
+ ObjFileParser.cpp
+ ObjFileParser.h
+ ObjTools.h
+ ObjExporter.h
+ ObjExporter.cpp
+)
+
+ADD_ASSIMP_IMPORTER( OGRE
+ OgreImporter.h
+ OgreStructs.h
+ OgreParsingUtils.h
+ OgreBinarySerializer.h
+ OgreXmlSerializer.h
+ OgreImporter.cpp
+ OgreStructs.cpp
+ OgreBinarySerializer.cpp
+ OgreXmlSerializer.cpp
+ OgreMaterial.cpp
+)
+
+ADD_ASSIMP_IMPORTER( OPENGEX
+ OpenGEXExporter.cpp
+ OpenGEXExporter.h
+ OpenGEXImporter.cpp
+ OpenGEXImporter.h
+ OpenGEXStructs.h
+)
+
+ADD_ASSIMP_IMPORTER( PLY
+ PlyLoader.cpp
+ PlyLoader.h
+ PlyParser.cpp
+ PlyParser.h
+ PlyExporter.cpp
+ PlyExporter.h
+)
+
+ADD_ASSIMP_IMPORTER( MS3D
+ MS3DLoader.cpp
+ MS3DLoader.h
+)
+
+ADD_ASSIMP_IMPORTER( COB
+ COBLoader.cpp
+ COBLoader.h
+ COBScene.h
+)
+
+ADD_ASSIMP_IMPORTER( BLEND
+ BlenderLoader.cpp
+ BlenderLoader.h
+ BlenderDNA.cpp
+ BlenderDNA.h
+ BlenderDNA.inl
+ BlenderScene.cpp
+ BlenderScene.h
+ BlenderSceneGen.h
+ BlenderIntermediate.h
+ BlenderModifier.h
+ BlenderModifier.cpp
+ BlenderBMesh.h
+ BlenderBMesh.cpp
+ BlenderTessellator.h
+ BlenderTessellator.cpp
+)
+
+ADD_ASSIMP_IMPORTER( IFC
+ IFCLoader.cpp
+ IFCLoader.h
+ IFCReaderGen.cpp
+ IFCReaderGen.h
+ IFCUtil.h
+ IFCUtil.cpp
+ IFCGeometry.cpp
+ IFCMaterial.cpp
+ IFCProfile.cpp
+ IFCCurve.cpp
+ IFCBoolean.cpp
+ IFCOpenings.cpp
+ STEPFile.h
+ STEPFileReader.h
+ STEPFileReader.cpp
+ STEPFileEncoding.cpp
+ STEPFileEncoding.h
+)
+if (MSVC AND ASSIMP_BUILD_IFC_IMPORTER)
+ set_source_files_properties(IFCReaderGen.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
+endif (MSVC AND ASSIMP_BUILD_IFC_IMPORTER)
+
+ADD_ASSIMP_IMPORTER( XGL
+ XGLLoader.cpp
+ XGLLoader.h
+)
+
+
+ADD_ASSIMP_IMPORTER( FBX
+ FBXImporter.cpp
+ FBXCompileConfig.h
+ FBXImporter.h
+ FBXParser.cpp
+ FBXParser.h
+ FBXTokenizer.cpp
+ FBXTokenizer.h
+ FBXImportSettings.h
+ FBXConverter.h
+ FBXConverter.cpp
+ FBXUtil.h
+ FBXUtil.cpp
+ FBXDocument.h
+ FBXDocument.cpp
+ FBXProperties.h
+ FBXProperties.cpp
+ FBXMeshGeometry.h
+ FBXMeshGeometry.cpp
+ FBXMaterial.cpp
+ FBXModel.cpp
+ FBXAnimation.cpp
+ FBXNodeAttribute.cpp
+ FBXDeformer.cpp
+ FBXBinaryTokenizer.cpp
+ FBXDocumentUtil.cpp
+)
SET( PostProcessing_SRCS
- CalcTangentsProcess.cpp
- CalcTangentsProcess.h
- ComputeUVMappingProcess.cpp
- ComputeUVMappingProcess.h
- ConvertToLHProcess.cpp
- ConvertToLHProcess.h
- FindDegenerates.cpp
- FindDegenerates.h
- FindInstancesProcess.cpp
- FindInstancesProcess.h
- FindInvalidDataProcess.cpp
- FindInvalidDataProcess.h
- FixNormalsStep.cpp
- FixNormalsStep.h
- GenFaceNormalsProcess.cpp
- GenFaceNormalsProcess.h
- GenVertexNormalsProcess.cpp
- GenVertexNormalsProcess.h
- PretransformVertices.cpp
- PretransformVertices.h
- ImproveCacheLocality.cpp
- ImproveCacheLocality.h
- JoinVerticesProcess.cpp
- JoinVerticesProcess.h
- LimitBoneWeightsProcess.cpp
- LimitBoneWeightsProcess.h
- RemoveRedundantMaterials.cpp
- RemoveRedundantMaterials.h
- RemoveVCProcess.cpp
- RemoveVCProcess.h
- SortByPTypeProcess.cpp
- SortByPTypeProcess.h
- SplitLargeMeshes.cpp
- SplitLargeMeshes.h
- TextureTransform.cpp
- TextureTransform.h
- TriangulateProcess.cpp
- TriangulateProcess.h
- ValidateDataStructure.cpp
- ValidateDataStructure.h
- OptimizeGraph.cpp
- OptimizeGraph.h
- OptimizeMeshes.cpp
- OptimizeMeshes.h
- DeboneProcess.cpp
- DeboneProcess.h
- ProcessHelper.h
- ProcessHelper.cpp
- PolyTools.h
- MakeVerboseFormat.cpp
- MakeVerboseFormat.h
+ CalcTangentsProcess.cpp
+ CalcTangentsProcess.h
+ ComputeUVMappingProcess.cpp
+ ComputeUVMappingProcess.h
+ ConvertToLHProcess.cpp
+ ConvertToLHProcess.h
+ FindDegenerates.cpp
+ FindDegenerates.h
+ FindInstancesProcess.cpp
+ FindInstancesProcess.h
+ FindInvalidDataProcess.cpp
+ FindInvalidDataProcess.h
+ FixNormalsStep.cpp
+ FixNormalsStep.h
+ GenFaceNormalsProcess.cpp
+ GenFaceNormalsProcess.h
+ GenVertexNormalsProcess.cpp
+ GenVertexNormalsProcess.h
+ PretransformVertices.cpp
+ PretransformVertices.h
+ ImproveCacheLocality.cpp
+ ImproveCacheLocality.h
+ JoinVerticesProcess.cpp
+ JoinVerticesProcess.h
+ LimitBoneWeightsProcess.cpp
+ LimitBoneWeightsProcess.h
+ RemoveRedundantMaterials.cpp
+ RemoveRedundantMaterials.h
+ RemoveVCProcess.cpp
+ RemoveVCProcess.h
+ SortByPTypeProcess.cpp
+ SortByPTypeProcess.h
+ SplitLargeMeshes.cpp
+ SplitLargeMeshes.h
+ TextureTransform.cpp
+ TextureTransform.h
+ TriangulateProcess.cpp
+ TriangulateProcess.h
+ ValidateDataStructure.cpp
+ ValidateDataStructure.h
+ OptimizeGraph.cpp
+ OptimizeGraph.h
+ OptimizeMeshes.cpp
+ OptimizeMeshes.h
+ DeboneProcess.cpp
+ DeboneProcess.h
+ ProcessHelper.h
+ ProcessHelper.cpp
+ PolyTools.h
+ MakeVerboseFormat.cpp
+ MakeVerboseFormat.h
)
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
-SET( Q3D_SRCS
- Q3DLoader.cpp
- Q3DLoader.h
+ADD_ASSIMP_IMPORTER( Q3D
+ Q3DLoader.cpp
+ Q3DLoader.h
+)
+
+ADD_ASSIMP_IMPORTER( Q3BSP
+ Q3BSPFileData.h
+ Q3BSPFileParser.h
+ Q3BSPFileParser.cpp
+ Q3BSPFileImporter.h
+ Q3BSPFileImporter.cpp
+ Q3BSPZipArchive.h
+ Q3BSPZipArchive.cpp
)
-SOURCE_GROUP( Q3D FILES ${Q3D_SRCS})
-SET( Q3BSP_SRCS
- Q3BSPFileData.h
- Q3BSPFileParser.h
- Q3BSPFileParser.cpp
- Q3BSPFileImporter.h
- Q3BSPFileImporter.cpp
- Q3BSPZipArchive.h
- Q3BSPZipArchive.cpp
+ADD_ASSIMP_IMPORTER( RAW
+ RawLoader.cpp
+ RawLoader.h
)
-SOURCE_GROUP( Q3BSP FILES ${Q3BSP_SRCS})
-SET( Raw_SRCS
- RawLoader.cpp
- RawLoader.h
+ADD_ASSIMP_IMPORTER( SIB
+ SIBImporter.cpp
+ SIBImporter.h
)
-SOURCE_GROUP( Raw FILES ${Raw_SRCS})
-SET( SMD_SRCS
- SMDLoader.cpp
- SMDLoader.h
+ADD_ASSIMP_IMPORTER( SMD
+ SMDLoader.cpp
+ SMDLoader.h
)
-SOURCE_GROUP( SMD FILES ${SMD_SRCS})
-SET( STL_SRCS
- STLLoader.cpp
- STLLoader.h
- STLExporter.h
- STLExporter.cpp
+ADD_ASSIMP_IMPORTER( STL
+ STLLoader.cpp
+ STLLoader.h
+ STLExporter.h
+ STLExporter.cpp
)
-SOURCE_GROUP( STL FILES ${STL_SRCS})
-SET( Terragen_SRCS
- TerragenLoader.cpp
- TerragenLoader.h
+ADD_ASSIMP_IMPORTER( TERRAGEN
+ TerragenLoader.cpp
+ TerragenLoader.h
)
-SOURCE_GROUP( Terragen FILES ${Terragen_SRCS})
-SET( Unreal_SRCS
- UnrealLoader.cpp
- UnrealLoader.h
+ADD_ASSIMP_IMPORTER( 3D
+ UnrealLoader.cpp
+ UnrealLoader.h
)
-SOURCE_GROUP( Unreal FILES ${Unreal_SRCS})
-SET( XFile_SRCS
- XFileHelper.h
- XFileImporter.cpp
- XFileImporter.h
- XFileParser.cpp
- XFileParser.h
+ADD_ASSIMP_IMPORTER( X
+ XFileHelper.h
+ XFileImporter.cpp
+ XFileImporter.h
+ XFileParser.cpp
+ XFileParser.h
+ XFileExporter.h
+ XFileExporter.cpp
)
-SOURCE_GROUP( XFile FILES ${XFile_SRCS})
+
+ADD_ASSIMP_IMPORTER( GLTF
+ glTFAsset.h
+ glTFAsset.inl
+ glTFAssetWriter.h
+ glTFAssetWriter.inl
+ glTFImporter.cpp
+ glTFImporter.h
+ glTFExporter.h
+ glTFExporter.cpp
+)
+
+
+ADD_ASSIMP_IMPORTER( 3MF
+ D3MFImporter.h
+ D3MFImporter.cpp
+ D3MFOpcPackage.h
+ D3MFOpcPackage.cpp
+)
+
+
+SET( Step_SRCS
+ StepExporter.h
+ StepExporter.cpp
+)
+SOURCE_GROUP( Step FILES ${Step_SRCS})
SET( Exporter_SRCS
- Exporter.cpp
- AssimpCExport.cpp
- BlobIOSystem.h
+ Exporter.cpp
+ AssimpCExport.cpp
+ BlobIOSystem.h
)
SOURCE_GROUP( Exporter FILES ${Exporter_SRCS})
SET( Extra_SRCS
- MD4FileData.h
+ MD4FileData.h
)
SOURCE_GROUP( Extra FILES ${Extra_SRCS})
SET( IrrXML_SRCS
- irrXMLWrapper.h
- ../contrib/irrXML/CXMLReaderImpl.h
- ../contrib/irrXML/heapsort.h
- ../contrib/irrXML/irrArray.h
- ../contrib/irrXML/irrString.h
- ../contrib/irrXML/irrTypes.h
- ../contrib/irrXML/irrXML.cpp
- ../contrib/irrXML/irrXML.h
+ irrXMLWrapper.h
+ ../contrib/irrXML/CXMLReaderImpl.h
+ ../contrib/irrXML/heapsort.h
+ ../contrib/irrXML/irrArray.h
+ ../contrib/irrXML/irrString.h
+ ../contrib/irrXML/irrTypes.h
+ ../contrib/irrXML/irrXML.cpp
+ ../contrib/irrXML/irrXML.h
)
SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
SET( ConvertUTF_SRCS
- ../contrib/ConvertUTF/ConvertUTF.h
- ../contrib/ConvertUTF/ConvertUTF.c
+ ../contrib/ConvertUTF/ConvertUTF.h
+ ../contrib/ConvertUTF/ConvertUTF.c
)
SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS})
-SET( Clipper_SRCS
- ../contrib/clipper/clipper.hpp
- ../contrib/clipper/clipper.cpp
+SET( Clipper_SRCS
+ ../contrib/clipper/clipper.hpp
+ ../contrib/clipper/clipper.cpp
)
SOURCE_GROUP( Clipper FILES ${Clipper_SRCS})
-SET( Poly2Tri_SRCS
- ../contrib/poly2tri/poly2tri/common/shapes.cc
- ../contrib/poly2tri/poly2tri/common/shapes.h
- ../contrib/poly2tri/poly2tri/common/utils.h
- ../contrib/poly2tri/poly2tri/sweep/advancing_front.h
- ../contrib/poly2tri/poly2tri/sweep/advancing_front.cc
- ../contrib/poly2tri/poly2tri/sweep/cdt.cc
- ../contrib/poly2tri/poly2tri/sweep/cdt.h
- ../contrib/poly2tri/poly2tri/sweep/sweep.cc
- ../contrib/poly2tri/poly2tri/sweep/sweep.h
- ../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
- ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
+SET( Poly2Tri_SRCS
+ ../contrib/poly2tri/poly2tri/common/shapes.cc
+ ../contrib/poly2tri/poly2tri/common/shapes.h
+ ../contrib/poly2tri/poly2tri/common/utils.h
+ ../contrib/poly2tri/poly2tri/sweep/advancing_front.h
+ ../contrib/poly2tri/poly2tri/sweep/advancing_front.cc
+ ../contrib/poly2tri/poly2tri/sweep/cdt.cc
+ ../contrib/poly2tri/poly2tri/sweep/cdt.h
+ ../contrib/poly2tri/poly2tri/sweep/sweep.cc
+ ../contrib/poly2tri/poly2tri/sweep/sweep.h
+ ../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
+ ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
)
SOURCE_GROUP( Poly2Tri FILES ${Poly2Tri_SRCS})
SET( unzip_SRCS
- ../contrib/unzip/crypt.h
- ../contrib/unzip/ioapi.c
- ../contrib/unzip/ioapi.h
- ../contrib/unzip/unzip.c
- ../contrib/unzip/unzip.h
+ ../contrib/unzip/crypt.h
+ ../contrib/unzip/ioapi.c
+ ../contrib/unzip/ioapi.h
+ ../contrib/unzip/unzip.c
+ ../contrib/unzip/unzip.h
)
SOURCE_GROUP( unzip FILES ${unzip_SRCS})
+SET ( openddl_parser_SRCS
+ ../contrib/openddlparser/code/OpenDDLParser.cpp
+ ../contrib/openddlparser/code/DDLNode.cpp
+ ../contrib/openddlparser/code/OpenDDLCommon.cpp
+ ../contrib/openddlparser/code/OpenDDLExport.cpp
+ ../contrib/openddlparser/code/Value.cpp
+ ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
+ ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
+ ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
+ ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
+ ../contrib/openddlparser/include/openddlparser/DDLNode.h
+ ../contrib/openddlparser/include/openddlparser/Value.h
+)
+SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
+
+INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" )
# VC2010 fixes
if(MSVC10)
- OPTION( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
- if( VC10_STDINT_FIX )
- ADD_DEFINITIONS( -D_STDINT )
- endif( VC10_STDINT_FIX )
+ option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
+ if( VC10_STDINT_FIX )
+ ADD_DEFINITIONS( -D_STDINT )
+ endif( VC10_STDINT_FIX )
endif(MSVC10)
ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT )
if ( MSVC )
- ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
- ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+ ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+ ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ( MSVC )
if (UNZIP_FOUND)
- SET (unzip_compile_SRCS "")
+ SET (unzip_compile_SRCS "")
else (UNZIP_FOUND)
- SET (unzip_compile_SRCS ${unzip_SRCS})
+ SET (unzip_compile_SRCS ${unzip_SRCS})
endif (UNZIP_FOUND)
+MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")
+MESSAGE(STATUS "Disabled formats:${ASSIMP_IMPORTERS_DISABLED}")
+
SET( assimp_src
- # Assimp Files
- ${Core_SRCS}
- ${Common_SRCS}
- ${Logging_SRCS}
- ${Exporter_SRCS}
- ${PostProcessing_SRCS}
-
- # Model Support
- ${3DS_SRCS}
- ${AC_SRCS}
- ${ASE_SRCS}
- ${B3D_SRCS}
- ${BVH_SRCS}
- ${Collada_SRCS}
- ${DXF_SRCS}
- ${CSM_SRCS}
- ${HMP_SRCS}
- ${Irr_SRCS}
- ${LWO_SRCS}
- ${LWS_SRCS}
- ${MD2_SRCS}
- ${MD3_SRCS}
- ${MD5_SRCS}
- ${MDC_SRCS}
- ${MDL_SRCS}
- ${MaterialSystem_SRCS}
- ${NFF_SRCS}
- ${OFFFormat_SRCS}
- ${Obj_SRCS}
- ${Ogre_SRCS}
- ${Ply_SRCS}
- ${Q3D_SRCS}
- ${Q3BSP_SRCS}
- ${Raw_SRCS}
- ${SMD_SRCS}
- ${STL_SRCS}
- ${Terragen_SRCS}
- ${Unreal_SRCS}
- ${XFile_SRCS}
- ${Extra_SRCS}
- ${MS3D_SRCS}
- ${COB_SRCS}
- ${BLENDER_SRCS}
- ${NDO_SRCS}
- ${IFC_SRCS}
- ${XGL_SRCS}
- ${FBX_SRCS}
-
- # Third-party libraries
- ${IrrXML_SRCS}
- ${ConvertUTF_SRCS}
- ${unzip_compile_SRCS}
- ${Poly2Tri_SRCS}
- ${Clipper_SRCS}
- # Necessary to show the headers in the project when using the VC++ generator:
- ${Boost_SRCS}
-
- ${PUBLIC_HEADERS}
- ${COMPILER_HEADERS}
-
- # Old precompiled header
- # (removed because the precompiled header is not updated when visual studio switch configuration which leads to failed compilation.
- # Moreover it's a drag to recompile assimp entirely each time a modification is made to one of the included header, which is definitely counter-productive.)
- AssimpPCH.cpp
-)
-
-#ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src)
+ # Assimp Files
+ ${Core_SRCS}
+ ${Common_SRCS}
+ ${Logging_SRCS}
+ ${Exporter_SRCS}
+ ${PostProcessing_SRCS}
+ ${MaterialSystem_SRCS}
+ ${Step_SRCS}
+
+ # Model Support
+ ${ASSIMP_LOADER_SRCS}
+
+ # Third-party libraries
+ ${IrrXML_SRCS}
+ ${ConvertUTF_SRCS}
+ ${unzip_compile_SRCS}
+ ${Poly2Tri_SRCS}
+ ${Clipper_SRCS}
+ ${openddl_parser_SRCS}
+ # Necessary to show the headers in the project when using the VC++ generator:
+
+ ${PUBLIC_HEADERS}
+ ${COMPILER_HEADERS}
+
+)
+ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
+
+INCLUDE_DIRECTORIES(
+ ../contrib/openddlparser/include
+)
+
+IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+ SET( assimp_src ${assimp_src} ${C4D_SRCS})
+ INCLUDE_DIRECTORIES(${C4D_INCLUDES})
+ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_LIBRARY( assimp ${assimp_src} )
-SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
+
+if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
+ set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
+ add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
+ target_link_libraries(assimp android_jniiosystem)
+endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
+
+IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+ TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARIES})
+ TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARIES})
+ TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES})
+ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+
+if( MSVC )
+ # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
+ if( MSVC70 OR MSVC71 )
+ set(MSVC_PREFIX "vc70")
+ elseif( MSVC80 )
+ set(MSVC_PREFIX "vc80")
+ elseif( MSVC90 )
+ set(MSVC_PREFIX "vc90")
+ elseif( MSVC10 )
+ set(MSVC_PREFIX "vc100")
+ elseif( MSVC11 )
+ set(MSVC_PREFIX "vc110")
+ elseif( MSVC12 )
+ set(MSVC_PREFIX "vc120")
+ elseif( MSVC14 )
+ set(MSVC_PREFIX "vc140")
+ else()
+ set(MSVC_PREFIX "vc150")
+ endif()
+ set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
+endif()
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
SET_TARGET_PROPERTIES( assimp PROPERTIES
- VERSION ${ASSIMP_VERSION}
- SOVERSION ${ASSIMP_SOVERSION} # use full version
- OUTPUT_NAME assimp${ASSIMP_LIBRARY_SUFFIX}
+ VERSION ${ASSIMP_VERSION}
+ SOVERSION ${ASSIMP_SOVERSION} # use full version
+ OUTPUT_NAME assimp${LIBRARY_SUFFIX}
)
if (APPLE)
- SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}")
+ SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}")
endif()
# Build against external unzip, or add ../contrib/unzip so
# assimp can #include "unzip.h"
if (UNZIP_FOUND)
- INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
- TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
+ INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
+ TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
else (UNZIP_FOUND)
- INCLUDE_DIRECTORIES("../contrib/unzip")
+ INCLUDE_DIRECTORIES("../")
endif (UNZIP_FOUND)
INSTALL( TARGETS assimp
- LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
- ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
- RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
- COMPONENT ${LIBASSIMP_COMPONENT})
+ LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
+ COMPONENT ${LIBASSIMP_COMPONENT})
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
+if (ASSIMP_ANDROID_JNIIOSYSTEM)
+ INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
+ DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
+ COMPONENT assimp-dev)
+endif(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB)
- install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb
- DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
- CONFIGURATIONS Debug
- )
- install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp.pdb
- DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
- CONFIGURATIONS RelWithDebInfo
- )
+ install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
+ DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ CONFIGURATIONS Debug
+ )
+ install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp.pdb
+ DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+ CONFIGURATIONS RelWithDebInfo
+ )
endif ()
diff --git a/src/3rdparty/assimp/code/COBLoader.cpp b/src/3rdparty/assimp/code/COBLoader.cpp
index 49a45be7a..4f0ad3980 100644
--- a/src/3rdparty/assimp/code/COBLoader.cpp
+++ b/src/3rdparty/assimp/code/COBLoader.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file COBLoader.cpp
* @brief Implementation of the TrueSpace COB/SCN importer class.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "COBLoader.h"
@@ -53,36 +53,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LineSplitter.h"
#include "TinyFormatter.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
using namespace Assimp;
using namespace Assimp::COB;
using namespace Assimp::Formatter;
-#define for_each BOOST_FOREACH
-
static const float units[] = {
- 1000.f,
- 100.f,
- 1.f,
- 0.001f,
- 1.f/0.0254f,
- 1.f/0.3048f,
- 1.f/0.9144f,
- 1.f/1609.344f
-};
+ 1000.f,
+ 100.f,
+ 1.f,
+ 0.001f,
+ 1.f/0.0254f,
+ 1.f/0.3048f,
+ 1.f/0.9144f,
+ 1.f/1609.344f
+};
static const aiImporterDesc desc = {
- "TrueSpace Object Importer",
- "",
- "",
- "little-endian files only",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "cob scn"
+ "TrueSpace Object Importer",
+ "",
+ "",
+ "little-endian files only",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "cob scn"
};
@@ -92,843 +95,847 @@ COBImporter::COBImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
COBImporter::~COBImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string& extension = GetExtension(pFile);
- if (extension == "cob" || extension == "scn") {
- return true;
- }
-
- else if ((!extension.length() || checkSig) && pIOHandler) {
- const char* tokens[] = {"Caligary"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string& extension = GetExtension(pFile);
+ if (extension == "cob" || extension == "scn") {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ const char* tokens[] = {"Caligary"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Loader meta information
const aiImporterDesc* COBImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void COBImporter::SetupProperties(const Importer* /*pImp*/)
{
- // nothing to be done for the moment
+ // nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------
-/*static*/ void COBImporter::ThrowException(const std::string& msg)
+/*static*/ AI_WONT_RETURN void COBImporter::ThrowException(const std::string& msg)
{
- throw DeadlyImportError("COB: "+msg);
+ throw DeadlyImportError("COB: "+msg);
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void COBImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void COBImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- COB::Scene scene;
- boost::scoped_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) );
-
- // check header
- char head[32];
- stream->CopyAndAdvance(head,32);
- if (strncmp(head,"Caligari ",9)) {
- ThrowException("Could not found magic id: `Caligari`");
- }
-
- DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
- void (COBImporter::* load)(Scene&,StreamReaderLE*)= head[15]=='A'?&COBImporter::ReadAsciiFile:&COBImporter::ReadBinaryFile;
- if (head[16]!='L') {
- ThrowException("File is big-endian, which is not supported");
- }
-
- // load data into intermediate structures
- (this->*load)(scene,stream.get());
- if(scene.nodes.empty()) {
- ThrowException("No nodes loaded");
- }
-
- // sort faces by material indices
- for_each(boost::shared_ptr< Node >& n,scene.nodes) {
- if (n->type == Node::TYPE_MESH) {
- Mesh& mesh = (Mesh&)(*n.get());
- for_each(Face& f,mesh.faces) {
- mesh.temp_map[f.material].push_back(&f);
- }
- }
- }
-
- // count meshes
- for_each(boost::shared_ptr< Node >& n,scene.nodes) {
- if (n->type == Node::TYPE_MESH) {
- Mesh& mesh = (Mesh&)(*n.get());
- if (mesh.vertex_positions.size() && mesh.texture_coords.size()) {
- pScene->mNumMeshes += mesh.temp_map.size();
- }
- }
- }
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]();
- pScene->mNumMeshes = 0;
-
- // count lights and cameras
- for_each(boost::shared_ptr< Node >& n,scene.nodes) {
- if (n->type == Node::TYPE_LIGHT) {
- ++pScene->mNumLights;
- }
- else if (n->type == Node::TYPE_CAMERA) {
- ++pScene->mNumCameras;
- }
- }
-
- if (pScene->mNumLights) {
- pScene->mLights = new aiLight*[pScene->mNumLights]();
- }
- if (pScene->mNumCameras) {
- pScene->mCameras = new aiCamera*[pScene->mNumCameras]();
- }
- pScene->mNumLights = pScene->mNumCameras = 0;
-
- // resolve parents by their IDs and build the output graph
- boost::scoped_ptr<Node> root(new Group());
- for(size_t n = 0; n < scene.nodes.size(); ++n) {
- const Node& nn = *scene.nodes[n].get();
- if(nn.parent_id==0) {
- root->temp_children.push_back(&nn);
- }
-
- for(size_t m = n; m < scene.nodes.size(); ++m) {
- const Node& mm = *scene.nodes[m].get();
- if (mm.parent_id == nn.id) {
- nn.temp_children.push_back(&mm);
- }
- }
- }
-
- pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
+ COB::Scene scene;
+ std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) );
+
+ // check header
+ char head[32];
+ stream->CopyAndAdvance(head,32);
+ if (strncmp(head,"Caligari ",9)) {
+ ThrowException("Could not found magic id: `Caligari`");
+ }
+
+ DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
+ if (head[16]!='L') {
+ ThrowException("File is big-endian, which is not supported");
+ }
+
+ // load data into intermediate structures
+ if (head[15]=='A') {
+ ReadAsciiFile(scene, stream.get());
+ }
+ else {
+ ReadBinaryFile(scene, stream.get());
+ }
+ if(scene.nodes.empty()) {
+ ThrowException("No nodes loaded");
+ }
+
+ // sort faces by material indices
+ for(std::shared_ptr< Node >& n : scene.nodes) {
+ if (n->type == Node::TYPE_MESH) {
+ Mesh& mesh = (Mesh&)(*n.get());
+ for(Face& f : mesh.faces) {
+ mesh.temp_map[f.material].push_back(&f);
+ }
+ }
+ }
+
+ // count meshes
+ for(std::shared_ptr< Node >& n : scene.nodes) {
+ if (n->type == Node::TYPE_MESH) {
+ Mesh& mesh = (Mesh&)(*n.get());
+ if (mesh.vertex_positions.size() && mesh.texture_coords.size()) {
+ pScene->mNumMeshes += mesh.temp_map.size();
+ }
+ }
+ }
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]();
+ pScene->mNumMeshes = 0;
+
+ // count lights and cameras
+ for(std::shared_ptr< Node >& n : scene.nodes) {
+ if (n->type == Node::TYPE_LIGHT) {
+ ++pScene->mNumLights;
+ }
+ else if (n->type == Node::TYPE_CAMERA) {
+ ++pScene->mNumCameras;
+ }
+ }
+
+ if (pScene->mNumLights) {
+ pScene->mLights = new aiLight*[pScene->mNumLights]();
+ }
+ if (pScene->mNumCameras) {
+ pScene->mCameras = new aiCamera*[pScene->mNumCameras]();
+ }
+ pScene->mNumLights = pScene->mNumCameras = 0;
+
+ // resolve parents by their IDs and build the output graph
+ std::unique_ptr<Node> root(new Group());
+ for(size_t n = 0; n < scene.nodes.size(); ++n) {
+ const Node& nn = *scene.nodes[n].get();
+ if(nn.parent_id==0) {
+ root->temp_children.push_back(&nn);
+ }
+
+ for(size_t m = n; m < scene.nodes.size(); ++m) {
+ const Node& mm = *scene.nodes[m].get();
+ if (mm.parent_id == nn.id) {
+ nn.temp_children.push_back(&mm);
+ }
+ }
+ }
+
+ pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
}
// ------------------------------------------------------------------------------------------------
-void ConvertTexture(boost::shared_ptr< Texture > tex, aiMaterial* out, aiTextureType type)
+void ConvertTexture(std::shared_ptr< Texture > tex, aiMaterial* out, aiTextureType type)
{
- const aiString path( tex->path );
- out->AddProperty(&path,AI_MATKEY_TEXTURE(type,0));
- out->AddProperty(&tex->transform,1,AI_MATKEY_UVTRANSFORM(type,0));
+ const aiString path( tex->path );
+ out->AddProperty(&path,AI_MATKEY_TEXTURE(type,0));
+ out->AddProperty(&tex->transform,1,AI_MATKEY_UVTRANSFORM(type,0));
}
// ------------------------------------------------------------------------------------------------
aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill)
{
- aiNode* nd = new aiNode();
- nd->mName.Set(root.name);
- nd->mTransformation = root.transform;
-
- // Note to everybody believing Voodoo is appropriate here:
- // I know polymorphism, run as fast as you can ;-)
- if (Node::TYPE_MESH == root.type) {
- const Mesh& ndmesh = (const Mesh&)(root);
- if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) {
-
- typedef std::pair<unsigned int,Mesh::FaceRefList> Entry;
- for_each(const Entry& reflist,ndmesh.temp_map) {
- { // create mesh
- size_t n = 0;
- for_each(Face* f, reflist.second) {
- n += f->indices.size();
- }
- if (!n) {
- continue;
- }
- aiMesh* outmesh = fill->mMeshes[fill->mNumMeshes++] = new aiMesh();
- ++nd->mNumMeshes;
-
- outmesh->mVertices = new aiVector3D[n];
- outmesh->mTextureCoords[0] = new aiVector3D[n];
-
- outmesh->mFaces = new aiFace[reflist.second.size()]();
- for_each(Face* f, reflist.second) {
- if (f->indices.empty()) {
- continue;
- }
-
- aiFace& fout = outmesh->mFaces[outmesh->mNumFaces++];
- fout.mIndices = new unsigned int[f->indices.size()];
-
- for_each(VertexIndex& v, f->indices) {
- if (v.pos_idx >= ndmesh.vertex_positions.size()) {
- ThrowException("Position index out of range");
- }
- if (v.uv_idx >= ndmesh.texture_coords.size()) {
- ThrowException("UV index out of range");
- }
- outmesh->mVertices[outmesh->mNumVertices] = ndmesh.vertex_positions[ v.pos_idx ];
- outmesh->mTextureCoords[0][outmesh->mNumVertices] = aiVector3D(
- ndmesh.texture_coords[ v.uv_idx ].x,
- ndmesh.texture_coords[ v.uv_idx ].y,
- 0.f
- );
-
- fout.mIndices[fout.mNumIndices++] = outmesh->mNumVertices++;
- }
- }
- outmesh->mMaterialIndex = fill->mNumMaterials;
- }{ // create material
- const Material* min = NULL;
- for_each(const Material& m, scin.materials) {
- if (m.parent_id == ndmesh.id && m.matnum == reflist.first) {
- min = &m;
- break;
- }
- }
- boost::scoped_ptr<const Material> defmat;
- if(!min) {
- DefaultLogger::get()->debug(format()<<"Could not resolve material index "
- <<reflist.first<<" - creating default material for this slot");
-
- defmat.reset(min=new Material());
- }
-
- aiMaterial* mat = new aiMaterial();
- fill->mMaterials[fill->mNumMaterials++] = mat;
-
- const aiString s(format("#mat_")<<fill->mNumMeshes<<"_"<<min->matnum);
- mat->AddProperty(&s,AI_MATKEY_NAME);
-
- if(int tmp = ndmesh.draw_flags & Mesh::WIRED ? 1 : 0) {
- mat->AddProperty(&tmp,1,AI_MATKEY_ENABLE_WIREFRAME);
- }
-
- { int shader;
- switch(min->shader)
- {
- case Material::FLAT:
- shader = aiShadingMode_Gouraud;
- break;
-
- case Material::PHONG:
- shader = aiShadingMode_Phong;
- break;
-
- case Material::METAL:
- shader = aiShadingMode_CookTorrance;
- break;
-
- default:
- ai_assert(false); // shouldn't be here
- }
- mat->AddProperty(&shader,1,AI_MATKEY_SHADING_MODEL);
- if(shader != aiShadingMode_Gouraud) {
- mat->AddProperty(&min->exp,1,AI_MATKEY_SHININESS);
- }
- }
-
- mat->AddProperty(&min->ior,1,AI_MATKEY_REFRACTI);
- mat->AddProperty(&min->rgb,1,AI_MATKEY_COLOR_DIFFUSE);
-
- aiColor3D c = aiColor3D(min->rgb)*min->ks;
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
-
- c = aiColor3D(min->rgb)*min->ka;
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
-
- // convert textures if some exist.
- if(min->tex_color) {
- ConvertTexture(min->tex_color,mat,aiTextureType_DIFFUSE);
- }
- if(min->tex_env) {
- ConvertTexture(min->tex_env ,mat,aiTextureType_UNKNOWN);
- }
- if(min->tex_bump) {
- ConvertTexture(min->tex_bump ,mat,aiTextureType_HEIGHT);
- }
- }
- }
- }
- }
- else if (Node::TYPE_LIGHT == root.type) {
- const Light& ndlight = (const Light&)(root);
- aiLight* outlight = fill->mLights[fill->mNumLights++] = new aiLight();
-
- outlight->mName.Set(ndlight.name);
- outlight->mColorDiffuse = outlight->mColorAmbient = outlight->mColorSpecular = ndlight.color;
-
- outlight->mAngleOuterCone = AI_DEG_TO_RAD(ndlight.angle);
- outlight->mAngleInnerCone = AI_DEG_TO_RAD(ndlight.inner_angle);
-
- // XXX
- outlight->mType = ndlight.ltype==Light::SPOT ? aiLightSource_SPOT : aiLightSource_DIRECTIONAL;
- }
- else if (Node::TYPE_CAMERA == root.type) {
- const Camera& ndcam = (const Camera&)(root);
- aiCamera* outcam = fill->mCameras[fill->mNumCameras++] = new aiCamera();
-
- outcam->mName.Set(ndcam.name);
- }
-
- // add meshes
- if (nd->mNumMeshes) { // mMeshes must be NULL if count is 0
- nd->mMeshes = new unsigned int[nd->mNumMeshes];
- for(unsigned int i = 0; i < nd->mNumMeshes;++i) {
- nd->mMeshes[i] = fill->mNumMeshes-i-1;
- }
- }
-
- // add children recursively
- nd->mChildren = new aiNode*[root.temp_children.size()]();
- for_each(const Node* n, root.temp_children) {
- (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n,scin,fill))->mParent = nd;
- }
-
- return nd;
+ aiNode* nd = new aiNode();
+ nd->mName.Set(root.name);
+ nd->mTransformation = root.transform;
+
+ // Note to everybody believing Voodoo is appropriate here:
+ // I know polymorphism, run as fast as you can ;-)
+ if (Node::TYPE_MESH == root.type) {
+ const Mesh& ndmesh = (const Mesh&)(root);
+ if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) {
+
+ typedef std::pair<unsigned int,Mesh::FaceRefList> Entry;
+ for(const Entry& reflist : ndmesh.temp_map) {
+ { // create mesh
+ size_t n = 0;
+ for(Face* f : reflist.second) {
+ n += f->indices.size();
+ }
+ if (!n) {
+ continue;
+ }
+ aiMesh* outmesh = fill->mMeshes[fill->mNumMeshes++] = new aiMesh();
+ ++nd->mNumMeshes;
+
+ outmesh->mVertices = new aiVector3D[n];
+ outmesh->mTextureCoords[0] = new aiVector3D[n];
+
+ outmesh->mFaces = new aiFace[reflist.second.size()]();
+ for(Face* f : reflist.second) {
+ if (f->indices.empty()) {
+ continue;
+ }
+
+ aiFace& fout = outmesh->mFaces[outmesh->mNumFaces++];
+ fout.mIndices = new unsigned int[f->indices.size()];
+
+ for(VertexIndex& v : f->indices) {
+ if (v.pos_idx >= ndmesh.vertex_positions.size()) {
+ ThrowException("Position index out of range");
+ }
+ if (v.uv_idx >= ndmesh.texture_coords.size()) {
+ ThrowException("UV index out of range");
+ }
+ outmesh->mVertices[outmesh->mNumVertices] = ndmesh.vertex_positions[ v.pos_idx ];
+ outmesh->mTextureCoords[0][outmesh->mNumVertices] = aiVector3D(
+ ndmesh.texture_coords[ v.uv_idx ].x,
+ ndmesh.texture_coords[ v.uv_idx ].y,
+ 0.f
+ );
+
+ fout.mIndices[fout.mNumIndices++] = outmesh->mNumVertices++;
+ }
+ }
+ outmesh->mMaterialIndex = fill->mNumMaterials;
+ }{ // create material
+ const Material* min = NULL;
+ for(const Material& m : scin.materials) {
+ if (m.parent_id == ndmesh.id && m.matnum == reflist.first) {
+ min = &m;
+ break;
+ }
+ }
+ std::unique_ptr<const Material> defmat;
+ if(!min) {
+ DefaultLogger::get()->debug(format()<<"Could not resolve material index "
+ <<reflist.first<<" - creating default material for this slot");
+
+ defmat.reset(min=new Material());
+ }
+
+ aiMaterial* mat = new aiMaterial();
+ fill->mMaterials[fill->mNumMaterials++] = mat;
+
+ const aiString s(format("#mat_")<<fill->mNumMeshes<<"_"<<min->matnum);
+ mat->AddProperty(&s,AI_MATKEY_NAME);
+
+ if(int tmp = ndmesh.draw_flags & Mesh::WIRED ? 1 : 0) {
+ mat->AddProperty(&tmp,1,AI_MATKEY_ENABLE_WIREFRAME);
+ }
+
+ { int shader;
+ switch(min->shader)
+ {
+ case Material::FLAT:
+ shader = aiShadingMode_Gouraud;
+ break;
+
+ case Material::PHONG:
+ shader = aiShadingMode_Phong;
+ break;
+
+ case Material::METAL:
+ shader = aiShadingMode_CookTorrance;
+ break;
+
+ default:
+ ai_assert(false); // shouldn't be here
+ }
+ mat->AddProperty(&shader,1,AI_MATKEY_SHADING_MODEL);
+ if(shader != aiShadingMode_Gouraud) {
+ mat->AddProperty(&min->exp,1,AI_MATKEY_SHININESS);
+ }
+ }
+
+ mat->AddProperty(&min->ior,1,AI_MATKEY_REFRACTI);
+ mat->AddProperty(&min->rgb,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ aiColor3D c = aiColor3D(min->rgb)*min->ks;
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
+
+ c = aiColor3D(min->rgb)*min->ka;
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
+
+ // convert textures if some exist.
+ if(min->tex_color) {
+ ConvertTexture(min->tex_color,mat,aiTextureType_DIFFUSE);
+ }
+ if(min->tex_env) {
+ ConvertTexture(min->tex_env ,mat,aiTextureType_UNKNOWN);
+ }
+ if(min->tex_bump) {
+ ConvertTexture(min->tex_bump ,mat,aiTextureType_HEIGHT);
+ }
+ }
+ }
+ }
+ }
+ else if (Node::TYPE_LIGHT == root.type) {
+ const Light& ndlight = (const Light&)(root);
+ aiLight* outlight = fill->mLights[fill->mNumLights++] = new aiLight();
+
+ outlight->mName.Set(ndlight.name);
+ outlight->mColorDiffuse = outlight->mColorAmbient = outlight->mColorSpecular = ndlight.color;
+
+ outlight->mAngleOuterCone = AI_DEG_TO_RAD(ndlight.angle);
+ outlight->mAngleInnerCone = AI_DEG_TO_RAD(ndlight.inner_angle);
+
+ // XXX
+ outlight->mType = ndlight.ltype==Light::SPOT ? aiLightSource_SPOT : aiLightSource_DIRECTIONAL;
+ }
+ else if (Node::TYPE_CAMERA == root.type) {
+ const Camera& ndcam = (const Camera&)(root);
+ aiCamera* outcam = fill->mCameras[fill->mNumCameras++] = new aiCamera();
+
+ outcam->mName.Set(ndcam.name);
+ }
+
+ // add meshes
+ if (nd->mNumMeshes) { // mMeshes must be NULL if count is 0
+ nd->mMeshes = new unsigned int[nd->mNumMeshes];
+ for(unsigned int i = 0; i < nd->mNumMeshes;++i) {
+ nd->mMeshes[i] = fill->mNumMeshes-i-1;
+ }
+ }
+
+ // add children recursively
+ nd->mChildren = new aiNode*[root.temp_children.size()]();
+ for(const Node* n : root.temp_children) {
+ (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n,scin,fill))->mParent = nd;
+ }
+
+ return nd;
}
// ------------------------------------------------------------------------------------------------
// Read an ASCII file into the given scene data structure
void COBImporter::ReadAsciiFile(Scene& out, StreamReaderLE* stream)
{
- ChunkInfo ci;
- for(LineSplitter splitter(*stream);splitter;++splitter) {
-
- // add all chunks to be recognized here. /else ../ omitted intentionally.
- if (splitter.match_start("PolH ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadPolH_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("BitM ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadBitM_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Mat1 ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadMat1_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Grou ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadGrou_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Lght ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadLght_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Came ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadCame_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Bone ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadBone_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Chan ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadChan_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("Unit ")) {
- ReadChunkInfo_Ascii(ci,splitter);
- ReadUnit_Ascii(out,splitter,ci);
- }
- if (splitter.match_start("END ")) {
- // we don't need this, but I guess there is a reason this
- // chunk has been implemented into COB for.
- return;
- }
- }
+ ChunkInfo ci;
+ for(LineSplitter splitter(*stream);splitter;++splitter) {
+
+ // add all chunks to be recognized here. /else ../ omitted intentionally.
+ if (splitter.match_start("PolH ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadPolH_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("BitM ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadBitM_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Mat1 ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadMat1_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Grou ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadGrou_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Lght ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadLght_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Came ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadCame_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Bone ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadBone_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Chan ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadChan_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("Unit ")) {
+ ReadChunkInfo_Ascii(ci,splitter);
+ ReadUnit_Ascii(out,splitter,ci);
+ }
+ if (splitter.match_start("END ")) {
+ // we don't need this, but I guess there is a reason this
+ // chunk has been implemented into COB for.
+ return;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadChunkInfo_Ascii(ChunkInfo& out, const LineSplitter& splitter)
{
- const char* all_tokens[8];
- splitter.get_tokens(all_tokens);
+ const char* all_tokens[8];
+ splitter.get_tokens(all_tokens);
- out.version = (all_tokens[1][1]-'0')*100+(all_tokens[1][3]-'0')*10+(all_tokens[1][4]-'0');
- out.id = strtoul10(all_tokens[3]);
- out.parent_id = strtoul10(all_tokens[5]);
- out.size = strtol10(all_tokens[7]);
+ out.version = (all_tokens[1][1]-'0')*100+(all_tokens[1][3]-'0')*10+(all_tokens[1][4]-'0');
+ out.id = strtoul10(all_tokens[3]);
+ out.parent_id = strtoul10(all_tokens[5]);
+ out.size = strtol10(all_tokens[7]);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo& nfo, const char* name)
{
- const std::string error = format("Encountered unsupported chunk: ") << name <<
- " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
-
- // we can recover if the chunk size was specified.
- if(nfo.size != static_cast<unsigned int>(-1)) {
- DefaultLogger::get()->error(error);
-
- // (HACK) - our current position in the stream is the beginning of the
- // head line of the next chunk. That's fine, but the caller is going
- // to call ++ on `splitter`, which we need to swallow to avoid
- // missing the next line.
- splitter.get_stream().IncPtr(nfo.size);
- splitter.swallow_next_increment();
- }
- else ThrowException(error);
+ const std::string error = format("Encountered unsupported chunk: ") << name <<
+ " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
+
+ // we can recover if the chunk size was specified.
+ if(nfo.size != static_cast<unsigned int>(-1)) {
+ DefaultLogger::get()->error(error);
+
+ // (HACK) - our current position in the stream is the beginning of the
+ // head line of the next chunk. That's fine, but the caller is going
+ // to call ++ on `splitter`, which we need to swallow to avoid
+ // missing the next line.
+ splitter.get_stream().IncPtr(nfo.size);
+ splitter.swallow_next_increment();
+ }
+ else ThrowException(error);
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) {
- LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
+void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) {
+ LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) {
- LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
+void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) {
+ LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) {
- LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
+void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) {
+ LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) {
- LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
+void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) {
+ LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const Formatter::format& message) {
- DefaultLogger::get()->warn(std::string("COB: ")+=message);
+void COBImporter::LogWarn_Ascii(const Formatter::format& message) {
+ DefaultLogger::get()->warn(std::string("COB: ")+=message);
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const Formatter::format& message) {
- DefaultLogger::get()->error(std::string("COB: ")+=message);
+void COBImporter::LogError_Ascii(const Formatter::format& message) {
+ DefaultLogger::get()->error(std::string("COB: ")+=message);
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const Formatter::format& message) {
- DefaultLogger::get()->info(std::string("COB: ")+=message);
+void COBImporter::LogInfo_Ascii(const Formatter::format& message) {
+ DefaultLogger::get()->info(std::string("COB: ")+=message);
}
// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const Formatter::format& message) {
- DefaultLogger::get()->debug(std::string("COB: ")+=message);
+void COBImporter::LogDebug_Ascii(const Formatter::format& message) {
+ DefaultLogger::get()->debug(std::string("COB: ")+=message);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
{
- for(;splitter;++splitter) {
- if (splitter.match_start("Name")) {
- msh.name = std::string(splitter[1]);
-
- // make nice names by merging the dupe count
- std::replace(msh.name.begin(),msh.name.end(),
- ',','_');
- }
- else if (splitter.match_start("Transform")) {
- for(unsigned int y = 0; y < 4 && ++splitter; ++y) {
- const char* s = splitter->c_str();
- for(unsigned int x = 0; x < 4; ++x) {
- SkipSpaces(&s);
- msh.transform[y][x] = fast_atof(&s);
- }
- }
- // we need the transform chunk, so we won't return until we have it.
- return;
- }
- }
+ for(;splitter;++splitter) {
+ if (splitter.match_start("Name")) {
+ msh.name = std::string(splitter[1]);
+
+ // make nice names by merging the dupe count
+ std::replace(msh.name.begin(),msh.name.end(),
+ ',','_');
+ }
+ else if (splitter.match_start("Transform")) {
+ for(unsigned int y = 0; y < 4 && ++splitter; ++y) {
+ const char* s = splitter->c_str();
+ for(unsigned int x = 0; x < 4; ++x) {
+ SkipSpaces(&s);
+ msh.transform[y][x] = fast_atof(&s);
+ }
+ }
+ // we need the transform chunk, so we won't return until we have it.
+ return;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
template <typename T>
-void COBImporter::ReadFloat3Tuple_Ascii(T& fill, const char** in)
+void COBImporter::ReadFloat3Tuple_Ascii(T& fill, const char** in)
{
- const char* rgb = *in;
- for(unsigned int i = 0; i < 3; ++i) {
- SkipSpaces(&rgb);
- if (*rgb == ',')++rgb;
- SkipSpaces(&rgb);
-
- fill[i] = fast_atof(&rgb);
- }
- *in = rgb;
+ const char* rgb = *in;
+ for(unsigned int i = 0; i < 3; ++i) {
+ SkipSpaces(&rgb);
+ if (*rgb == ',')++rgb;
+ SkipSpaces(&rgb);
+
+ fill[i] = fast_atof(&rgb);
+ }
+ *in = rgb;
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Mat1");
- }
-
- ++splitter;
- if (!splitter.match_start("mat# ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
- return;
- }
-
- out.materials.push_back(Material());
- Material& mat = out.materials.back();
- mat = nfo;
-
- mat.matnum = strtoul10(splitter[1]);
- ++splitter;
-
- if (!splitter.match_start("shader: ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
- return;
- }
- std::string shader = std::string(splitter[1]);
- shader = shader.substr(0,shader.find_first_of(" \t"));
-
- if (shader == "metal") {
- mat.shader = Material::METAL;
- }
- else if (shader == "phong") {
- mat.shader = Material::PHONG;
- }
- else if (shader != "flat") {
- LogWarn_Ascii(splitter,format()<<
- "Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
- }
-
- ++splitter;
- if (!splitter.match_start("rgb ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `rgb` line in `Mat1` chunk "<<nfo.id);
- }
-
- const char* rgb = splitter[1];
- ReadFloat3Tuple_Ascii(mat.rgb,&rgb);
-
- ++splitter;
- if (!splitter.match_start("alpha ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `alpha` line in `Mat1` chunk "<<nfo.id);
- }
-
- const char* tokens[10];
- splitter.get_tokens(tokens);
-
- mat.alpha = fast_atof( tokens[1] );
- mat.ka = fast_atof( tokens[3] );
- mat.ks = fast_atof( tokens[5] );
- mat.exp = fast_atof( tokens[7] );
- mat.ior = fast_atof( tokens[9] );
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Mat1");
+ }
+
+ ++splitter;
+ if (!splitter.match_start("mat# ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+ return;
+ }
+
+ out.materials.push_back(Material());
+ Material& mat = out.materials.back();
+ mat = nfo;
+
+ mat.matnum = strtoul10(splitter[1]);
+ ++splitter;
+
+ if (!splitter.match_start("shader: ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+ return;
+ }
+ std::string shader = std::string(splitter[1]);
+ shader = shader.substr(0,shader.find_first_of(" \t"));
+
+ if (shader == "metal") {
+ mat.shader = Material::METAL;
+ }
+ else if (shader == "phong") {
+ mat.shader = Material::PHONG;
+ }
+ else if (shader != "flat") {
+ LogWarn_Ascii(splitter,format()<<
+ "Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
+ }
+
+ ++splitter;
+ if (!splitter.match_start("rgb ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `rgb` line in `Mat1` chunk "<<nfo.id);
+ }
+
+ const char* rgb = splitter[1];
+ ReadFloat3Tuple_Ascii(mat.rgb,&rgb);
+
+ ++splitter;
+ if (!splitter.match_start("alpha ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `alpha` line in `Mat1` chunk "<<nfo.id);
+ }
+
+ const char* tokens[10];
+ splitter.get_tokens(tokens);
+
+ mat.alpha = fast_atof( tokens[1] );
+ mat.ka = fast_atof( tokens[3] );
+ mat.ks = fast_atof( tokens[5] );
+ mat.exp = fast_atof( tokens[7] );
+ mat.ior = fast_atof( tokens[9] );
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 1) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Unit");
- }
- ++splitter;
- if (!splitter.match_start("Units ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `Units` line in `Unit` chunk "<<nfo.id);
- return;
- }
-
- // parent chunks preceede their childs, so we should have the
- // corresponding chunk already.
- for_each(boost::shared_ptr< Node >& nd, out.nodes) {
- if (nd->id == nfo.parent_id) {
- const unsigned int t=strtoul10(splitter[1]);
-
- nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
- LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
- ,1.f):units[t];
- return;
- }
- }
- LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
- <<nfo.parent_id<<" which does not exist");
+ if(nfo.version > 1) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Unit");
+ }
+ ++splitter;
+ if (!splitter.match_start("Units ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `Units` line in `Unit` chunk "<<nfo.id);
+ return;
+ }
+
+ // parent chunks preceede their childs, so we should have the
+ // corresponding chunk already.
+ for(std::shared_ptr< Node >& nd : out.nodes) {
+ if (nd->id == nfo.parent_id) {
+ const unsigned int t=strtoul10(splitter[1]);
+
+ nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
+ LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+ ,1.f):units[t];
+ return;
+ }
+ }
+ LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
+ <<nfo.parent_id<<" which does not exist");
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadChan_Ascii(Scene& /*out*/, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Chan");
- }
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Chan");
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Lght");
- }
-
- out.nodes.push_back(boost::shared_ptr<Light>(new Light()));
- Light& msh = (Light&)(*out.nodes.back().get());
- msh = nfo;
-
- ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
-
- if (splitter.match_start("Infinite ")) {
- msh.ltype = Light::INFINITE;
- }
- else if (splitter.match_start("Local ")) {
- msh.ltype = Light::LOCAL;
- }
- else if (splitter.match_start("Spot ")) {
- msh.ltype = Light::SPOT;
- }
- else {
- LogWarn_Ascii(splitter,format()<<
- "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
- msh.ltype = Light::SPOT;
- }
-
- ++splitter;
- if (!splitter.match_start("color ")) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `color` line in `Lght` chunk "<<nfo.id);
- }
-
- const char* rgb = splitter[1];
- ReadFloat3Tuple_Ascii(msh.color ,&rgb);
-
- SkipSpaces(&rgb);
- if (strncmp(rgb,"cone angle",10)) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
- }
- SkipSpaces(rgb+10,&rgb);
- msh.angle = fast_atof(&rgb);
-
- SkipSpaces(&rgb);
- if (strncmp(rgb,"inner angle",11)) {
- LogWarn_Ascii(splitter,format()<<
- "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
- }
- SkipSpaces(rgb+11,&rgb);
- msh.inner_angle = fast_atof(&rgb);
-
- // skip the rest for we can't handle this kind of physically-based lighting information.
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Lght");
+ }
+
+ out.nodes.push_back(std::shared_ptr<Light>(new Light()));
+ Light& msh = (Light&)(*out.nodes.back().get());
+ msh = nfo;
+
+ ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
+
+ if (splitter.match_start("Infinite ")) {
+ msh.ltype = Light::INFINITE;
+ }
+ else if (splitter.match_start("Local ")) {
+ msh.ltype = Light::LOCAL;
+ }
+ else if (splitter.match_start("Spot ")) {
+ msh.ltype = Light::SPOT;
+ }
+ else {
+ LogWarn_Ascii(splitter,format()<<
+ "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
+ msh.ltype = Light::SPOT;
+ }
+
+ ++splitter;
+ if (!splitter.match_start("color ")) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `color` line in `Lght` chunk "<<nfo.id);
+ }
+
+ const char* rgb = splitter[1];
+ ReadFloat3Tuple_Ascii(msh.color ,&rgb);
+
+ SkipSpaces(&rgb);
+ if (strncmp(rgb,"cone angle",10)) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+ }
+ SkipSpaces(rgb+10,&rgb);
+ msh.angle = fast_atof(&rgb);
+
+ SkipSpaces(&rgb);
+ if (strncmp(rgb,"inner angle",11)) {
+ LogWarn_Ascii(splitter,format()<<
+ "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+ }
+ SkipSpaces(rgb+11,&rgb);
+ msh.inner_angle = fast_atof(&rgb);
+
+ // skip the rest for we can't handle this kind of physically-based lighting information.
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadCame_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 2) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Came");
- }
+ if(nfo.version > 2) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Came");
+ }
- out.nodes.push_back(boost::shared_ptr<Camera>(new Camera()));
- Camera& msh = (Camera&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Camera>(new Camera()));
+ Camera& msh = (Camera&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
+ ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
- // skip the next line, we don't know this differenciation between a
- // standard camera and a panoramic camera.
- ++splitter;
+ // skip the next line, we don't know this differenciation between a
+ // standard camera and a panoramic camera.
+ ++splitter;
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBone_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 5) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Bone");
- }
+ if(nfo.version > 5) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Bone");
+ }
- out.nodes.push_back(boost::shared_ptr<Bone>(new Bone()));
- Bone& msh = (Bone&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Bone>(new Bone()));
+ Bone& msh = (Bone&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
+ ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
- // TODO
+ // TODO
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadGrou_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 1) {
- return UnsupportedChunk_Ascii(splitter,nfo,"Grou");
- }
+ if(nfo.version > 1) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"Grou");
+ }
- out.nodes.push_back(boost::shared_ptr<Group>(new Group()));
- Group& msh = (Group&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Group>(new Group()));
+ Group& msh = (Group&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
+ ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Ascii(splitter,nfo,"PolH");
- }
-
- out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh()));
- Mesh& msh = (Mesh&)(*out.nodes.back().get());
- msh = nfo;
-
- ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
-
- // the chunk has a fixed order of components, but some are not interesting of us so
- // we're just looking for keywords in arbitrary order. The end of the chunk is
- // either the last `Face` or the `DrawFlags` attribute, depending on the format ver.
- for(;splitter;++splitter) {
- if (splitter.match_start("World Vertices")) {
- const unsigned int cnt = strtoul10(splitter[2]);
- msh.vertex_positions.resize(cnt);
-
- for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
- const char* s = splitter->c_str();
-
- aiVector3D& v = msh.vertex_positions[cur];
-
- SkipSpaces(&s);
- v.x = fast_atof(&s);
- SkipSpaces(&s);
- v.y = fast_atof(&s);
- SkipSpaces(&s);
- v.z = fast_atof(&s);
- }
- }
- else if (splitter.match_start("Texture Vertices")) {
- const unsigned int cnt = strtoul10(splitter[2]);
- msh.texture_coords.resize(cnt);
-
- for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
- const char* s = splitter->c_str();
-
- aiVector2D& v = msh.texture_coords[cur];
-
- SkipSpaces(&s);
- v.x = fast_atof(&s);
- SkipSpaces(&s);
- v.y = fast_atof(&s);
- }
- }
- else if (splitter.match_start("Faces")) {
- const unsigned int cnt = strtoul10(splitter[1]);
- msh.faces.reserve(cnt);
-
- for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
- if (splitter.match_start("Hole")) {
- LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
- continue;
- }
-
- if (!splitter.match_start("Face")) {
- ThrowException("Expected Face line");
- }
-
- msh.faces.push_back(Face());
- Face& face = msh.faces.back();
-
- face.indices.resize(strtoul10(splitter[2]));
- face.flags = strtoul10(splitter[4]);
- face.material = strtoul10(splitter[6]);
-
- const char* s = (++splitter)->c_str();
- for(size_t i = 0; i < face.indices.size(); ++i) {
- if(!SkipSpaces(&s)) {
- ThrowException("Expected EOL token in Face entry");
- }
- if ('<' != *s++) {
- ThrowException("Expected < token in Face entry");
- }
- face.indices[i].pos_idx = strtoul10(s,&s);
- if (',' != *s++) {
- ThrowException("Expected , token in Face entry");
- }
- face.indices[i].uv_idx = strtoul10(s,&s);
- if ('>' != *s++) {
- ThrowException("Expected < token in Face entry");
- }
- }
- }
- if (nfo.version <= 4) {
- break;
- }
- }
- else if (splitter.match_start("DrawFlags")) {
- msh.draw_flags = strtoul10(splitter[1]);
- break;
- }
- }
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"PolH");
+ }
+
+ out.nodes.push_back(std::shared_ptr<Mesh>(new Mesh()));
+ Mesh& msh = (Mesh&)(*out.nodes.back().get());
+ msh = nfo;
+
+ ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
+
+ // the chunk has a fixed order of components, but some are not interesting of us so
+ // we're just looking for keywords in arbitrary order. The end of the chunk is
+ // either the last `Face` or the `DrawFlags` attribute, depending on the format ver.
+ for(;splitter;++splitter) {
+ if (splitter.match_start("World Vertices")) {
+ const unsigned int cnt = strtoul10(splitter[2]);
+ msh.vertex_positions.resize(cnt);
+
+ for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
+ const char* s = splitter->c_str();
+
+ aiVector3D& v = msh.vertex_positions[cur];
+
+ SkipSpaces(&s);
+ v.x = fast_atof(&s);
+ SkipSpaces(&s);
+ v.y = fast_atof(&s);
+ SkipSpaces(&s);
+ v.z = fast_atof(&s);
+ }
+ }
+ else if (splitter.match_start("Texture Vertices")) {
+ const unsigned int cnt = strtoul10(splitter[2]);
+ msh.texture_coords.resize(cnt);
+
+ for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
+ const char* s = splitter->c_str();
+
+ aiVector2D& v = msh.texture_coords[cur];
+
+ SkipSpaces(&s);
+ v.x = fast_atof(&s);
+ SkipSpaces(&s);
+ v.y = fast_atof(&s);
+ }
+ }
+ else if (splitter.match_start("Faces")) {
+ const unsigned int cnt = strtoul10(splitter[1]);
+ msh.faces.reserve(cnt);
+
+ for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
+ if (splitter.match_start("Hole")) {
+ LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
+ continue;
+ }
+
+ if (!splitter.match_start("Face")) {
+ ThrowException("Expected Face line");
+ }
+
+ msh.faces.push_back(Face());
+ Face& face = msh.faces.back();
+
+ face.indices.resize(strtoul10(splitter[2]));
+ face.flags = strtoul10(splitter[4]);
+ face.material = strtoul10(splitter[6]);
+
+ const char* s = (++splitter)->c_str();
+ for(size_t i = 0; i < face.indices.size(); ++i) {
+ if(!SkipSpaces(&s)) {
+ ThrowException("Expected EOL token in Face entry");
+ }
+ if ('<' != *s++) {
+ ThrowException("Expected < token in Face entry");
+ }
+ face.indices[i].pos_idx = strtoul10(s,&s);
+ if (',' != *s++) {
+ ThrowException("Expected , token in Face entry");
+ }
+ face.indices[i].uv_idx = strtoul10(s,&s);
+ if ('>' != *s++) {
+ ThrowException("Expected < token in Face entry");
+ }
+ }
+ }
+ if (nfo.version <= 4) {
+ break;
+ }
+ }
+ else if (splitter.match_start("DrawFlags")) {
+ msh.draw_flags = strtoul10(splitter[1]);
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const ChunkInfo& nfo)
{
- if(nfo.version > 1) {
- return UnsupportedChunk_Ascii(splitter,nfo,"BitM");
- }
+ if(nfo.version > 1) {
+ return UnsupportedChunk_Ascii(splitter,nfo,"BitM");
+ }
/*
- "\nThumbNailHdrSize %ld"
- "\nThumbHeader: %02hx 02hx %02hx "
- "\nColorBufSize %ld"
- "\nColorBufZipSize %ld"
- "\nZippedThumbnail: %02hx 02hx %02hx "
+ "\nThumbNailHdrSize %ld"
+ "\nThumbHeader: %02hx 02hx %02hx "
+ "\nColorBufSize %ld"
+ "\nColorBufZipSize %ld"
+ "\nZippedThumbnail: %02hx 02hx %02hx "
*/
- const unsigned int head = strtoul10((++splitter)[1]);
- if (head != sizeof(Bitmap::BitmapHeader)) {
- LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
- return;
- }
-
- /*union {
- Bitmap::BitmapHeader data;
- char opaq[sizeof Bitmap::BitmapHeader()];
- };*/
-// ReadHexOctets(opaq,head,(++splitter)[1]);
+ const unsigned int head = strtoul10((++splitter)[1]);
+ if (head != sizeof(Bitmap::BitmapHeader)) {
+ LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
+ return;
+ }
+
+ /*union {
+ Bitmap::BitmapHeader data;
+ char opaq[sizeof Bitmap::BitmapHeader()];
+ };*/
+// ReadHexOctets(opaq,head,(++splitter)[1]);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadString_Binary(std::string& out, StreamReaderLE& reader)
{
- out.resize( reader.GetI2());
- for_each(char& c,out) {
- c = reader.GetI1();
- }
+ out.resize( reader.GetI2());
+ for(char& c : out) {
+ c = reader.GetI1();
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBasicNodeInfo_Binary(Node& msh, StreamReaderLE& reader, const ChunkInfo& /*nfo*/)
{
- const unsigned int dupes = reader.GetI2();
- ReadString_Binary(msh.name,reader);
+ const unsigned int dupes = reader.GetI2();
+ ReadString_Binary(msh.name,reader);
- msh.name = format(msh.name)<<'_'<<dupes;
+ msh.name = format(msh.name)<<'_'<<dupes;
- // skip local axes for the moment
- reader.IncPtr(48);
+ // skip local axes for the moment
+ reader.IncPtr(48);
- msh.transform = aiMatrix4x4();
- for(unsigned int y = 0; y < 3; ++y) {
- for(unsigned int x =0; x < 4; ++x) {
- msh.transform[y][x] = reader.GetF4();
- }
- }
+ msh.transform = aiMatrix4x4();
+ for(unsigned int y = 0; y < 3; ++y) {
+ for(unsigned int x =0; x < 4; ++x) {
+ msh.transform[y][x] = reader.GetF4();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkInfo& nfo, const char* name)
{
- const std::string error = format("Encountered unsupported chunk: ") << name <<
- " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
-
- // we can recover if the chunk size was specified.
- if(nfo.size != static_cast<unsigned int>(-1)) {
- DefaultLogger::get()->error(error);
- reader.IncPtr(nfo.size);
- }
- else ThrowException(error);
+ const std::string error = format("Encountered unsupported chunk: ") << name <<
+ " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
+
+ // we can recover if the chunk size was specified.
+ if(nfo.size != static_cast<unsigned int>(-1)) {
+ DefaultLogger::get()->error(error);
+ reader.IncPtr(nfo.size);
+ }
+ else ThrowException(error);
}
// ------------------------------------------------------------------------------------------------
@@ -937,354 +944,354 @@ class chunk_guard {
public:
- chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader)
- : nfo(nfo)
- , reader(reader)
- , cur(reader.GetCurrentPos())
- {
- }
+ chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader)
+ : nfo(nfo)
+ , reader(reader)
+ , cur(reader.GetCurrentPos())
+ {
+ }
- ~chunk_guard() {
- // don't do anything if the size is not given
- if(nfo.size != static_cast<unsigned int>(-1)) {
- reader.IncPtr(static_cast<int>(nfo.size)-reader.GetCurrentPos()+cur);
- }
- }
+ ~chunk_guard() {
+ // don't do anything if the size is not given
+ if(nfo.size != static_cast<unsigned int>(-1)) {
+ reader.IncPtr(static_cast<int>(nfo.size)-reader.GetCurrentPos()+cur);
+ }
+ }
private:
- const COB::ChunkInfo& nfo;
- StreamReaderLE& reader;
- long cur;
+ const COB::ChunkInfo& nfo;
+ StreamReaderLE& reader;
+ long cur;
};
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader)
{
- while(1) {
- std::string type;
- type += reader -> GetI1()
- ,type += reader -> GetI1()
- ,type += reader -> GetI1()
- ,type += reader -> GetI1()
- ;
-
- ChunkInfo nfo;
- nfo.version = reader -> GetI2()*10;
- nfo.version += reader -> GetI2();
-
- nfo.id = reader->GetI4();
- nfo.parent_id = reader->GetI4();
- nfo.size = reader->GetI4();
-
- if (type == "PolH") {
- ReadPolH_Binary(out,*reader,nfo);
- }
- else if (type == "BitM") {
- ReadBitM_Binary(out,*reader,nfo);
- }
- else if (type == "Grou") {
- ReadGrou_Binary(out,*reader,nfo);
- }
- else if (type == "Lght") {
- ReadLght_Binary(out,*reader,nfo);
- }
- else if (type == "Came") {
- ReadCame_Binary(out,*reader,nfo);
- }
- else if (type == "Mat1") {
- ReadMat1_Binary(out,*reader,nfo);
- }
- /* else if (type == "Bone") {
- ReadBone_Binary(out,*reader,nfo);
- }
- else if (type == "Chan") {
- ReadChan_Binary(out,*reader,nfo);
- }*/
- else if (type == "Unit") {
- ReadUnit_Binary(out,*reader,nfo);
- }
- else if (type == "OLay") {
- // ignore layer index silently.
- if(nfo.size != static_cast<unsigned int>(-1) ) {
- reader->IncPtr(nfo.size);
- }
- else return UnsupportedChunk_Binary(*reader,nfo,type.c_str());
- }
- else if (type == "END ") {
- return;
- }
- else UnsupportedChunk_Binary(*reader,nfo,type.c_str());
- }
+ while(1) {
+ std::string type;
+ type += reader -> GetI1()
+ ,type += reader -> GetI1()
+ ,type += reader -> GetI1()
+ ,type += reader -> GetI1()
+ ;
+
+ ChunkInfo nfo;
+ nfo.version = reader -> GetI2()*10;
+ nfo.version += reader -> GetI2();
+
+ nfo.id = reader->GetI4();
+ nfo.parent_id = reader->GetI4();
+ nfo.size = reader->GetI4();
+
+ if (type == "PolH") {
+ ReadPolH_Binary(out,*reader,nfo);
+ }
+ else if (type == "BitM") {
+ ReadBitM_Binary(out,*reader,nfo);
+ }
+ else if (type == "Grou") {
+ ReadGrou_Binary(out,*reader,nfo);
+ }
+ else if (type == "Lght") {
+ ReadLght_Binary(out,*reader,nfo);
+ }
+ else if (type == "Came") {
+ ReadCame_Binary(out,*reader,nfo);
+ }
+ else if (type == "Mat1") {
+ ReadMat1_Binary(out,*reader,nfo);
+ }
+ /* else if (type == "Bone") {
+ ReadBone_Binary(out,*reader,nfo);
+ }
+ else if (type == "Chan") {
+ ReadChan_Binary(out,*reader,nfo);
+ }*/
+ else if (type == "Unit") {
+ ReadUnit_Binary(out,*reader,nfo);
+ }
+ else if (type == "OLay") {
+ // ignore layer index silently.
+ if(nfo.size != static_cast<unsigned int>(-1) ) {
+ reader->IncPtr(nfo.size);
+ }
+ else return UnsupportedChunk_Binary(*reader,nfo,type.c_str());
+ }
+ else if (type == "END ") {
+ return;
+ }
+ else UnsupportedChunk_Binary(*reader,nfo,type.c_str());
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Binary(reader,nfo,"PolH");
- }
- const chunk_guard cn(nfo,reader);
-
- out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh()));
- Mesh& msh = (Mesh&)(*out.nodes.back().get());
- msh = nfo;
-
- ReadBasicNodeInfo_Binary(msh,reader,nfo);
-
- msh.vertex_positions.resize(reader.GetI4());
- for_each(aiVector3D& v,msh.vertex_positions) {
- v.x = reader.GetF4();
- v.y = reader.GetF4();
- v.z = reader.GetF4();
- }
-
- msh.texture_coords.resize(reader.GetI4());
- for_each(aiVector2D& v,msh.texture_coords) {
- v.x = reader.GetF4();
- v.y = reader.GetF4();
- }
-
- const size_t numf = reader.GetI4();
- msh.faces.reserve(numf);
- for(size_t i = 0; i < numf; ++i) {
- // XXX backface culling flag is 0x10 in flags
-
- // hole?
- bool hole;
- if ((hole = (reader.GetI1() & 0x08) != 0)) {
- // XXX Basically this should just work fine - then triangulator
- // should output properly triangulated data even for polygons
- // with holes. Test data specific to COB is needed to confirm it.
- if (msh.faces.empty()) {
- ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
- }
- }
- else msh.faces.push_back(Face());
- Face& f = msh.faces.back();
-
- const size_t num = reader.GetI2();
- f.indices.reserve(f.indices.size() + num);
-
- if(!hole) {
- f.material = reader.GetI2();
- f.flags = 0;
- }
-
- for(size_t x = 0; x < num; ++x) {
- f.indices.push_back(VertexIndex());
-
- VertexIndex& v = f.indices.back();
- v.pos_idx = reader.GetI4();
- v.uv_idx = reader.GetI4();
- }
-
- if(hole) {
- std::reverse(f.indices.rbegin(),f.indices.rbegin()+num);
- }
- }
- if (nfo.version>4) {
- msh.draw_flags = reader.GetI4();
- }
- nfo.version>5 && nfo.version<8 ? reader.GetI4() : 0;
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Binary(reader,nfo,"PolH");
+ }
+ const chunk_guard cn(nfo,reader);
+
+ out.nodes.push_back(std::shared_ptr<Mesh>(new Mesh()));
+ Mesh& msh = (Mesh&)(*out.nodes.back().get());
+ msh = nfo;
+
+ ReadBasicNodeInfo_Binary(msh,reader,nfo);
+
+ msh.vertex_positions.resize(reader.GetI4());
+ for(aiVector3D& v : msh.vertex_positions) {
+ v.x = reader.GetF4();
+ v.y = reader.GetF4();
+ v.z = reader.GetF4();
+ }
+
+ msh.texture_coords.resize(reader.GetI4());
+ for(aiVector2D& v : msh.texture_coords) {
+ v.x = reader.GetF4();
+ v.y = reader.GetF4();
+ }
+
+ const size_t numf = reader.GetI4();
+ msh.faces.reserve(numf);
+ for(size_t i = 0; i < numf; ++i) {
+ // XXX backface culling flag is 0x10 in flags
+
+ // hole?
+ bool hole;
+ if ((hole = (reader.GetI1() & 0x08) != 0)) {
+ // XXX Basically this should just work fine - then triangulator
+ // should output properly triangulated data even for polygons
+ // with holes. Test data specific to COB is needed to confirm it.
+ if (msh.faces.empty()) {
+ ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
+ }
+ }
+ else msh.faces.push_back(Face());
+ Face& f = msh.faces.back();
+
+ const size_t num = reader.GetI2();
+ f.indices.reserve(f.indices.size() + num);
+
+ if(!hole) {
+ f.material = reader.GetI2();
+ f.flags = 0;
+ }
+
+ for(size_t x = 0; x < num; ++x) {
+ f.indices.push_back(VertexIndex());
+
+ VertexIndex& v = f.indices.back();
+ v.pos_idx = reader.GetI4();
+ v.uv_idx = reader.GetI4();
+ }
+
+ if(hole) {
+ std::reverse(f.indices.rbegin(),f.indices.rbegin()+num);
+ }
+ }
+ if (nfo.version>4) {
+ msh.draw_flags = reader.GetI4();
+ }
+ nfo.version>5 && nfo.version<8 ? reader.GetI4() : 0;
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadBitM_Binary(COB::Scene& /*out*/, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 1) {
- return UnsupportedChunk_Binary(reader,nfo,"BitM");
- }
+ if(nfo.version > 1) {
+ return UnsupportedChunk_Binary(reader,nfo,"BitM");
+ }
- const chunk_guard cn(nfo,reader);
+ const chunk_guard cn(nfo,reader);
- const uint32_t len = reader.GetI4();
- reader.IncPtr(len);
+ const uint32_t len = reader.GetI4();
+ reader.IncPtr(len);
- reader.GetI4();
- reader.IncPtr(reader.GetI4());
+ reader.GetI4();
+ reader.IncPtr(reader.GetI4());
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 8) {
- return UnsupportedChunk_Binary(reader,nfo,"Mat1");
- }
-
- const chunk_guard cn(nfo,reader);
-
- out.materials.push_back(Material());
- Material& mat = out.materials.back();
- mat = nfo;
-
- mat.matnum = reader.GetI2();
- switch(reader.GetI1()) {
- case 'f':
- mat.type = Material::FLAT;
- break;
- case 'p':
- mat.type = Material::PHONG;
- break;
- case 'm':
- mat.type = Material::METAL;
- break;
- default:
- LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
- mat.type = Material::FLAT;
- }
-
- switch(reader.GetI1()) {
- case 'f':
- mat.autofacet = Material::FACETED;
- break;
- case 'a':
- mat.autofacet = Material::AUTOFACETED;
- break;
- case 's':
- mat.autofacet = Material::SMOOTH;
- break;
- default:
- LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
- mat.autofacet = Material::FACETED;
- }
- mat.autofacet_angle = static_cast<float>(reader.GetI1());
-
- mat.rgb.r = reader.GetF4();
- mat.rgb.g = reader.GetF4();
- mat.rgb.b = reader.GetF4();
-
- mat.alpha = reader.GetF4();
- mat.ka = reader.GetF4();
- mat.ks = reader.GetF4();
- mat.exp = reader.GetF4();
- mat.ior = reader.GetF4();
-
- char id[2];
- id[0] = reader.GetI1(),id[1] = reader.GetI1();
-
- if (id[0] == 'e' && id[1] == ':') {
- mat.tex_env.reset(new Texture());
-
- reader.GetI1();
- ReadString_Binary(mat.tex_env->path,reader);
-
- // advance to next texture-id
- id[0] = reader.GetI1(),id[1] = reader.GetI1();
- }
-
- if (id[0] == 't' && id[1] == ':') {
- mat.tex_color.reset(new Texture());
-
- reader.GetI1();
- ReadString_Binary(mat.tex_color->path,reader);
-
- mat.tex_color->transform.mTranslation.x = reader.GetF4();
- mat.tex_color->transform.mTranslation.y = reader.GetF4();
-
- mat.tex_color->transform.mScaling.x = reader.GetF4();
- mat.tex_color->transform.mScaling.y = reader.GetF4();
-
- // advance to next texture-id
- id[0] = reader.GetI1(),id[1] = reader.GetI1();
- }
-
- if (id[0] == 'b' && id[1] == ':') {
- mat.tex_bump.reset(new Texture());
-
- reader.GetI1();
- ReadString_Binary(mat.tex_bump->path,reader);
-
- mat.tex_bump->transform.mTranslation.x = reader.GetF4();
- mat.tex_bump->transform.mTranslation.y = reader.GetF4();
-
- mat.tex_bump->transform.mScaling.x = reader.GetF4();
- mat.tex_bump->transform.mScaling.y = reader.GetF4();
-
- // skip amplitude for I don't know its purpose.
- reader.GetF4();
- }
- reader.IncPtr(-2);
+ if(nfo.version > 8) {
+ return UnsupportedChunk_Binary(reader,nfo,"Mat1");
+ }
+
+ const chunk_guard cn(nfo,reader);
+
+ out.materials.push_back(Material());
+ Material& mat = out.materials.back();
+ mat = nfo;
+
+ mat.matnum = reader.GetI2();
+ switch(reader.GetI1()) {
+ case 'f':
+ mat.type = Material::FLAT;
+ break;
+ case 'p':
+ mat.type = Material::PHONG;
+ break;
+ case 'm':
+ mat.type = Material::METAL;
+ break;
+ default:
+ LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
+ mat.type = Material::FLAT;
+ }
+
+ switch(reader.GetI1()) {
+ case 'f':
+ mat.autofacet = Material::FACETED;
+ break;
+ case 'a':
+ mat.autofacet = Material::AUTOFACETED;
+ break;
+ case 's':
+ mat.autofacet = Material::SMOOTH;
+ break;
+ default:
+ LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
+ mat.autofacet = Material::FACETED;
+ }
+ mat.autofacet_angle = static_cast<float>(reader.GetI1());
+
+ mat.rgb.r = reader.GetF4();
+ mat.rgb.g = reader.GetF4();
+ mat.rgb.b = reader.GetF4();
+
+ mat.alpha = reader.GetF4();
+ mat.ka = reader.GetF4();
+ mat.ks = reader.GetF4();
+ mat.exp = reader.GetF4();
+ mat.ior = reader.GetF4();
+
+ char id[2];
+ id[0] = reader.GetI1(),id[1] = reader.GetI1();
+
+ if (id[0] == 'e' && id[1] == ':') {
+ mat.tex_env.reset(new Texture());
+
+ reader.GetI1();
+ ReadString_Binary(mat.tex_env->path,reader);
+
+ // advance to next texture-id
+ id[0] = reader.GetI1(),id[1] = reader.GetI1();
+ }
+
+ if (id[0] == 't' && id[1] == ':') {
+ mat.tex_color.reset(new Texture());
+
+ reader.GetI1();
+ ReadString_Binary(mat.tex_color->path,reader);
+
+ mat.tex_color->transform.mTranslation.x = reader.GetF4();
+ mat.tex_color->transform.mTranslation.y = reader.GetF4();
+
+ mat.tex_color->transform.mScaling.x = reader.GetF4();
+ mat.tex_color->transform.mScaling.y = reader.GetF4();
+
+ // advance to next texture-id
+ id[0] = reader.GetI1(),id[1] = reader.GetI1();
+ }
+
+ if (id[0] == 'b' && id[1] == ':') {
+ mat.tex_bump.reset(new Texture());
+
+ reader.GetI1();
+ ReadString_Binary(mat.tex_bump->path,reader);
+
+ mat.tex_bump->transform.mTranslation.x = reader.GetF4();
+ mat.tex_bump->transform.mTranslation.y = reader.GetF4();
+
+ mat.tex_bump->transform.mScaling.x = reader.GetF4();
+ mat.tex_bump->transform.mScaling.y = reader.GetF4();
+
+ // skip amplitude for I don't know its purpose.
+ reader.GetF4();
+ }
+ reader.IncPtr(-2);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 2) {
- return UnsupportedChunk_Binary(reader,nfo,"Came");
- }
+ if(nfo.version > 2) {
+ return UnsupportedChunk_Binary(reader,nfo,"Came");
+ }
- const chunk_guard cn(nfo,reader);
+ const chunk_guard cn(nfo,reader);
- out.nodes.push_back(boost::shared_ptr<Camera>(new Camera()));
- Camera& msh = (Camera&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Camera>(new Camera()));
+ Camera& msh = (Camera&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Binary(msh,reader,nfo);
+ ReadBasicNodeInfo_Binary(msh,reader,nfo);
- // the rest is not interesting for us, so we skip over it.
- if(nfo.version > 1) {
- if (reader.GetI2()==512) {
- reader.IncPtr(42);
- }
- }
+ // the rest is not interesting for us, so we skip over it.
+ if(nfo.version > 1) {
+ if (reader.GetI2()==512) {
+ reader.IncPtr(42);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 2) {
- return UnsupportedChunk_Binary(reader,nfo,"Lght");
- }
+ if(nfo.version > 2) {
+ return UnsupportedChunk_Binary(reader,nfo,"Lght");
+ }
- const chunk_guard cn(nfo,reader);
+ const chunk_guard cn(nfo,reader);
- out.nodes.push_back(boost::shared_ptr<Light>(new Light()));
- Light& msh = (Light&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Light>(new Light()));
+ Light& msh = (Light&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Binary(msh,reader,nfo);
+ ReadBasicNodeInfo_Binary(msh,reader,nfo);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 2) {
- return UnsupportedChunk_Binary(reader,nfo,"Grou");
- }
+ if(nfo.version > 2) {
+ return UnsupportedChunk_Binary(reader,nfo,"Grou");
+ }
- const chunk_guard cn(nfo,reader);
+ const chunk_guard cn(nfo,reader);
- out.nodes.push_back(boost::shared_ptr<Group>(new Group()));
- Group& msh = (Group&)(*out.nodes.back().get());
- msh = nfo;
+ out.nodes.push_back(std::shared_ptr<Group>(new Group()));
+ Group& msh = (Group&)(*out.nodes.back().get());
+ msh = nfo;
- ReadBasicNodeInfo_Binary(msh,reader,nfo);
+ ReadBasicNodeInfo_Binary(msh,reader,nfo);
}
// ------------------------------------------------------------------------------------------------
void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
{
- if(nfo.version > 1) {
- return UnsupportedChunk_Binary(reader,nfo,"Unit");
- }
-
- const chunk_guard cn(nfo,reader);
-
- // parent chunks preceede their childs, so we should have the
- // corresponding chunk already.
- for_each(boost::shared_ptr< Node >& nd, out.nodes) {
- if (nd->id == nfo.parent_id) {
- const unsigned int t=reader.GetI2();
- nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
- LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
- ,1.f):units[t];
-
- return;
- }
- }
- LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
- <<nfo.parent_id<<" which does not exist");
+ if(nfo.version > 1) {
+ return UnsupportedChunk_Binary(reader,nfo,"Unit");
+ }
+
+ const chunk_guard cn(nfo,reader);
+
+ // parent chunks preceede their childs, so we should have the
+ // corresponding chunk already.
+ for(std::shared_ptr< Node >& nd : out.nodes) {
+ if (nd->id == nfo.parent_id) {
+ const unsigned int t=reader.GetI2();
+ nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
+ LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+ ,1.f):units[t];
+
+ return;
+ }
+ }
+ LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
+ <<nfo.parent_id<<" which does not exist");
}
diff --git a/src/3rdparty/assimp/code/COBLoader.h b/src/3rdparty/assimp/code/COBLoader.h
index 6ce3898bf..efccc448d 100644
--- a/src/3rdparty/assimp/code/COBLoader.h
+++ b/src/3rdparty/assimp/code/COBLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,123 +45,127 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_COB_LOADER_H
#include "BaseImporter.h"
-namespace Assimp {
- class LineSplitter;
-
- // 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;
- }
-
- // COBScene.h
- namespace COB {
- struct ChunkInfo;
- struct Node;
- struct Scene;
- }
+#include "StreamReader.h"
+
+struct aiNode;
+
+namespace Assimp {
+ class LineSplitter;
+
+ // 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;
+ }
+
+ // COBScene.h
+ namespace COB {
+ struct ChunkInfo;
+ struct Node;
+ struct Scene;
+ }
// -------------------------------------------------------------------------------------------
-/** Importer class to load TrueSpace files (cob,scn) up to v6.
+/** Importer class to load TrueSpace files (cob,scn) up to v6.
*
* Currently relatively limited, loads only ASCII files and needs more test coverage. */
// -------------------------------------------------------------------------------------------
class COBImporter : public BaseImporter
{
public:
- COBImporter();
- ~COBImporter();
+ COBImporter();
+ ~COBImporter();
public:
- // --------------------
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // --------------------
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // --------------------
- const aiImporterDesc* GetInfo () const;
+ // --------------------
+ const aiImporterDesc* GetInfo () const;
- // --------------------
- void SetupProperties(const Importer* pImp);
+ // --------------------
+ void SetupProperties(const Importer* pImp);
- // --------------------
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // --------------------
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- // -------------------------------------------------------------------
- /** Prepend 'COB: ' and throw msg.*/
- static void ThrowException(const std::string& msg);
+ // -------------------------------------------------------------------
+ /** Prepend 'COB: ' and throw msg.*/
+ AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
- // -------------------------------------------------------------------
- /** @brief Read from an ascii scene/object file
- * @param out Receives output data.
- * @param stream Stream to read from. */
- void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
+ // -------------------------------------------------------------------
+ /** @brief Read from an ascii scene/object file
+ * @param out Receives output data.
+ * @param stream Stream to read from. */
+ void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
- // -------------------------------------------------------------------
- /** @brief Read from a binary scene/object file
- * @param out Receives output data.
- * @param stream Stream to read from. */
- void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
+ // -------------------------------------------------------------------
+ /** @brief Read from a binary scene/object file
+ * @param out Receives output data.
+ * @param stream Stream to read from. */
+ void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
private:
- // Conversion to Assimp output format
+ // Conversion to Assimp output format
- aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
+ aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
private:
- // ASCII file support
+ // ASCII file support
- void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
- void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
- void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
+ void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
+ void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
+ void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
- void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+ void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
- // ASCII file logging stuff to add proper line numbers to messages
+ // ASCII file logging stuff to add proper line numbers to messages
- static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
- static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
- static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
- static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
+ static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
+ static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
+ static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
+ static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
- static void LogWarn_Ascii (const Formatter::format& message);
- static void LogError_Ascii (const Formatter::format& message);
- static void LogInfo_Ascii (const Formatter::format& message);
- static void LogDebug_Ascii (const Formatter::format& message);
+ static void LogWarn_Ascii (const Formatter::format& message);
+ static void LogError_Ascii (const Formatter::format& message);
+ static void LogInfo_Ascii (const Formatter::format& message);
+ static void LogDebug_Ascii (const Formatter::format& message);
- // Binary file support
+ // Binary file support
- void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
- void ReadString_Binary(std::string& out, StreamReaderLE& reader);
- void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
+ void ReadString_Binary(std::string& out, StreamReaderLE& reader);
+ void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
- void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+ void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
}; // !class COBImporter
diff --git a/src/3rdparty/assimp/code/COBScene.h b/src/3rdparty/assimp/code/COBScene.h
index 4cf295551..0e27d1461 100644
--- a/src/3rdparty/assimp/code/COBScene.h
+++ b/src/3rdparty/assimp/code/COBScene.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,228 +44,231 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_COB_SCENE_H
#define INCLUDED_AI_COB_SCENE_H
-#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <deque>
+
#include "BaseImporter.h"
+#include "./../include/assimp/material.h"
-namespace Assimp {
- namespace COB {
+namespace Assimp {
+ namespace COB {
// ------------------
/** Represents a single vertex index in a face */
struct VertexIndex
{
- // intentionally uninitialized
- unsigned int pos_idx,uv_idx;
+ // intentionally uninitialized
+ unsigned int pos_idx,uv_idx;
};
// ------------------
/** COB Face data structure */
struct Face
{
- // intentionally uninitialized
- unsigned int material, flags;
- std::vector<VertexIndex> indices;
+ // intentionally uninitialized
+ unsigned int material, flags;
+ std::vector<VertexIndex> indices;
};
// ------------------
/** COB chunk header information */
struct ChunkInfo
{
- enum {NO_SIZE=UINT_MAX};
+ enum {NO_SIZE=UINT_MAX};
- ChunkInfo ()
- : id (0)
- , parent_id (0)
- , version (0)
- , size (NO_SIZE)
- {}
+ ChunkInfo ()
+ : id (0)
+ , parent_id (0)
+ , version (0)
+ , size (NO_SIZE)
+ {}
- // Id of this chunk, unique within file
- unsigned int id;
+ // Id of this chunk, unique within file
+ unsigned int id;
- // and the corresponding parent
- unsigned int parent_id;
+ // and the corresponding parent
+ unsigned int parent_id;
- // version. v1.23 becomes 123
- unsigned int version;
+ // version. v1.23 becomes 123
+ unsigned int version;
- // chunk size in bytes, only relevant for binary files
- // NO_SIZE is also valid.
- unsigned int size;
+ // chunk size in bytes, only relevant for binary files
+ // NO_SIZE is also valid.
+ unsigned int size;
};
// ------------------
/** A node in the scenegraph */
struct Node : public ChunkInfo
{
- enum Type {
- TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
- };
+ enum Type {
+ TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
+ };
- virtual ~Node() {}
- Node(Type type) : type(type), unit_scale(1.f){}
+ virtual ~Node() {}
+ Node(Type type) : type(type), unit_scale(1.f){}
- Type type;
+ Type type;
- // used during resolving
- typedef std::deque<const Node*> ChildList;
- mutable ChildList temp_children;
+ // used during resolving
+ typedef std::deque<const Node*> ChildList;
+ mutable ChildList temp_children;
- // unique name
- std::string name;
+ // unique name
+ std::string name;
- // local mesh transformation
- aiMatrix4x4 transform;
+ // local mesh transformation
+ aiMatrix4x4 transform;
- // scaling for this node to get to the metric system
- float unit_scale;
+ // scaling for this node to get to the metric system
+ float unit_scale;
};
// ------------------
/** COB Mesh data structure */
struct Mesh : public Node
{
- using ChunkInfo::operator=;
- enum DrawFlags {
- SOLID = 0x1,
- TRANS = 0x2,
- WIRED = 0x4,
- BBOX = 0x8,
- HIDE = 0x10
- };
-
- Mesh()
- : Node(TYPE_MESH)
- , draw_flags(SOLID)
- {}
-
- // vertex elements
- std::vector<aiVector2D> texture_coords;
- std::vector<aiVector3D> vertex_positions;
-
- // face data
- std::vector<Face> faces;
-
- // misc. drawing flags
- unsigned int draw_flags;
-
- // used during resolving
- typedef std::deque<Face*> FaceRefList;
- typedef std::map< unsigned int,FaceRefList > TempMap;
- TempMap temp_map;
+ using ChunkInfo::operator=;
+ enum DrawFlags {
+ SOLID = 0x1,
+ TRANS = 0x2,
+ WIRED = 0x4,
+ BBOX = 0x8,
+ HIDE = 0x10
+ };
+
+ Mesh()
+ : Node(TYPE_MESH)
+ , draw_flags(SOLID)
+ {}
+
+ // vertex elements
+ std::vector<aiVector2D> texture_coords;
+ std::vector<aiVector3D> vertex_positions;
+
+ // face data
+ std::vector<Face> faces;
+
+ // misc. drawing flags
+ unsigned int draw_flags;
+
+ // used during resolving
+ typedef std::deque<Face*> FaceRefList;
+ typedef std::map< unsigned int,FaceRefList > TempMap;
+ TempMap temp_map;
};
// ------------------
/** COB Group data structure */
struct Group : public Node
{
- using ChunkInfo::operator=;
- Group() : Node(TYPE_GROUP) {}
+ using ChunkInfo::operator=;
+ Group() : Node(TYPE_GROUP) {}
};
// ------------------
/** COB Bone data structure */
struct Bone : public Node
{
- using ChunkInfo::operator=;
- Bone() : Node(TYPE_BONE) {}
+ using ChunkInfo::operator=;
+ Bone() : Node(TYPE_BONE) {}
};
// ------------------
/** COB Light data structure */
struct Light : public Node
{
- enum LightType {
- SPOT,LOCAL,INFINITE
- };
+ enum LightType {
+ SPOT,LOCAL,INFINITE
+ };
- using ChunkInfo::operator=;
- Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
+ using ChunkInfo::operator=;
+ Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
- aiColor3D color;
- float angle,inner_angle;
+ aiColor3D color;
+ float angle,inner_angle;
- LightType ltype;
+ LightType ltype;
};
// ------------------
/** COB Camera data structure */
struct Camera : public Node
{
- using ChunkInfo::operator=;
- Camera() : Node(TYPE_CAMERA) {}
+ using ChunkInfo::operator=;
+ Camera() : Node(TYPE_CAMERA) {}
};
// ------------------
/** COB Texture data structure */
struct Texture
{
- std::string path;
- aiUVTransform transform;
+ std::string path;
+ aiUVTransform transform;
};
// ------------------
/** COB Material data structure */
struct Material : ChunkInfo
{
- using ChunkInfo::operator=;
- enum Shader {
- FLAT,PHONG,METAL
- };
+ using ChunkInfo::operator=;
+ enum Shader {
+ FLAT,PHONG,METAL
+ };
- enum AutoFacet {
- FACETED,AUTOFACETED,SMOOTH
- };
+ enum AutoFacet {
+ FACETED,AUTOFACETED,SMOOTH
+ };
- Material() : alpha(),exp(),ior(),ka(),ks(1.f),
- matnum(UINT_MAX),
- shader(FLAT),autofacet(FACETED),
- autofacet_angle()
- {}
+ Material() : alpha(),exp(),ior(),ka(),ks(1.f),
+ matnum(UINT_MAX),
+ shader(FLAT),autofacet(FACETED),
+ autofacet_angle()
+ {}
- std::string type;
+ std::string type;
- aiColor3D rgb;
- float alpha, exp, ior,ka,ks;
+ aiColor3D rgb;
+ float alpha, exp, ior,ka,ks;
- unsigned int matnum;
- Shader shader;
+ unsigned int matnum;
+ Shader shader;
- AutoFacet autofacet;
- float autofacet_angle;
+ AutoFacet autofacet;
+ float autofacet_angle;
- boost::shared_ptr<Texture> tex_env,tex_bump,tex_color;
+ std::shared_ptr<Texture> tex_env,tex_bump,tex_color;
};
// ------------------
/** Embedded bitmap, for instance for the thumbnail image */
struct Bitmap : ChunkInfo
{
- Bitmap() : orig_size() {}
- struct BitmapHeader
- {
- };
-
- BitmapHeader head;
- size_t orig_size;
- std::vector<char> buff_zipped;
+ Bitmap() : orig_size() {}
+ struct BitmapHeader
+ {
+ };
+
+ BitmapHeader head;
+ size_t orig_size;
+ std::vector<char> buff_zipped;
};
-typedef std::deque< boost::shared_ptr<Node> > NodeList;
+typedef std::deque< std::shared_ptr<Node> > NodeList;
typedef std::vector< Material > MaterialList;
// ------------------
/** Represents a master COB scene, even if we loaded just a single COB file */
struct Scene
{
- NodeList nodes;
- MaterialList materials;
+ NodeList nodes;
+ MaterialList materials;
- // becomes *0 later
- Bitmap thumbnail;
+ // becomes *0 later
+ Bitmap thumbnail;
};
- } // end COB
+ } // end COB
} // end Assimp
#endif
diff --git a/src/3rdparty/assimp/code/CSMLoader.cpp b/src/3rdparty/assimp/code/CSMLoader.cpp
index c92a3ac79..925abf4bd 100644
--- a/src/3rdparty/assimp/code/CSMLoader.cpp
+++ b/src/3rdparty/assimp/code/CSMLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implementation of the CSM importer class.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
@@ -51,20 +51,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SkeletonMeshBuilder.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <assimp/Importer.hpp>
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/anim.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "CharacterStudio Motion Importer (MoCap)",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "csm"
+ "CharacterStudio Motion Importer (MoCap)",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "csm"
};
@@ -75,225 +82,225 @@ CSMImporter::CSMImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
CSMImporter::~CSMImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- // check file extension
- const std::string extension = GetExtension(pFile);
-
- if( extension == "csm")
- return true;
-
- if ((checkSig || !extension.length()) && pIOHandler) {
- const char* tokens[] = {"$Filename"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "csm")
+ return true;
+
+ if ((checkSig || !extension.length()) && pIOHandler) {
+ const char* tokens[] = {"$Filename"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported
const aiImporterDesc* CSMImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void CSMImporter::SetupProperties(const Importer* pImp)
{
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void CSMImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void CSMImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
- }
-
- // allocate storage and copy the contents of the file to a memory buffer
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
- const char* buffer = &mBuffer2[0];
-
- aiAnimation* anim = new aiAnimation();
- int first = 0, last = 0x00ffffff;
-
- // now process the file and look out for '$' sections
- while (1) {
- SkipSpaces(&buffer);
- if ('\0' == *buffer)
- break;
-
- if ('$' == *buffer) {
- ++buffer;
- if (TokenMatchI(buffer,"firstframe",10)) {
- SkipSpaces(&buffer);
- first = strtol10(buffer,&buffer);
- }
- else if (TokenMatchI(buffer,"lastframe",9)) {
- SkipSpaces(&buffer);
- last = strtol10(buffer,&buffer);
- }
- else if (TokenMatchI(buffer,"rate",4)) {
- SkipSpaces(&buffer);
- float d;
- buffer = fast_atoreal_move<float>(buffer,d);
- anim->mTicksPerSecond = d;
- }
- else if (TokenMatchI(buffer,"order",5)) {
- std::vector< aiNodeAnim* > anims_temp;
- anims_temp.reserve(30);
- while (1) {
- SkipSpaces(&buffer);
- if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
- break; // next section
-
- // Construct a new node animation channel and setup its name
- anims_temp.push_back(new aiNodeAnim());
- aiNodeAnim* nda = anims_temp.back();
-
- char* ot = nda->mNodeName.data;
- while (!IsSpaceOrNewLine(*buffer))
- *ot++ = *buffer++;
-
- *ot = '\0';
- nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
- }
-
- anim->mNumChannels = anims_temp.size();
- if (!anim->mNumChannels)
- throw DeadlyImportError("CSM: Empty $order section");
-
- // copy over to the output animation
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
- ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
- }
- else if (TokenMatchI(buffer,"points",6)) {
- if (!anim->mNumChannels)
- throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
-
- // If we know how many frames we'll read, we can preallocate some storage
- unsigned int alloc = 100;
- if (last != 0x00ffffff)
- {
- alloc = last-first;
- alloc += alloc>>2u; // + 25%
- for (unsigned int i = 0; i < anim->mNumChannels;++i)
- anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
- }
-
- unsigned int filled = 0;
-
- // Now read all point data.
- while (1) {
- SkipSpaces(&buffer);
- if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) {
- break; // next section
- }
-
- // read frame
- const int frame = ::strtoul10(buffer,&buffer);
- last = std::max(frame,last);
- first = std::min(frame,last);
- for (unsigned int i = 0; i < anim->mNumChannels;++i) {
-
- aiNodeAnim* s = anim->mChannels[i];
- if (s->mNumPositionKeys == alloc) { /* need to reallocate? */
-
- aiVectorKey* old = s->mPositionKeys;
- s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
- ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
- delete[] old;
- }
-
- // read x,y,z
- if(!SkipSpacesAndLineEnd(&buffer))
- throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord");
-
- if (TokenMatchI(buffer, "DROPOUT", 7)) {
- // seems this is invalid marker data; at least the doc says it's possible
- DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
- }
- else {
- aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
- sub->mTime = (double)frame;
- buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
-
- if(!SkipSpacesAndLineEnd(&buffer))
- throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord");
- buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
-
- if(!SkipSpacesAndLineEnd(&buffer))
- throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord");
- buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
-
- ++s->mNumPositionKeys;
- }
- }
-
- // update allocation granularity
- if (filled == alloc)
- alloc *= 2;
-
- ++filled;
- }
- // all channels must be complete in order to continue safely.
- for (unsigned int i = 0; i < anim->mNumChannels;++i) {
-
- if (!anim->mChannels[i]->mNumPositionKeys)
- throw DeadlyImportError("CSM: Invalid marker track");
- }
- }
- }
- else {
- // advance to the next line
- SkipLine(&buffer);
- }
- }
-
- // Setup a proper animation duration
- anim->mDuration = last - std::min( first, 0 );
-
- // build a dummy root node with the tiny markers as children
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("$CSM_DummyRoot");
-
- pScene->mRootNode->mNumChildren = anim->mNumChannels;
- pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
-
- for (unsigned int i = 0; i < anim->mNumChannels;++i) {
- aiNodeAnim* na = anim->mChannels[i];
-
- aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
- nd->mName = anim->mChannels[i]->mNodeName;
- nd->mParent = pScene->mRootNode;
-
- aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
- }
-
- // Store the one and only animation in the scene
- pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1];
- pScene->mAnimations[0] = anim;
- anim->mName.Set("$CSM_MasterAnim");
-
- // mark the scene as incomplete and run SkeletonMeshBuilder on it
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-
- if (!noSkeletonMesh) {
- SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
+ }
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ aiAnimation* anim = new aiAnimation();
+ int first = 0, last = 0x00ffffff;
+
+ // now process the file and look out for '$' sections
+ while (1) {
+ SkipSpaces(&buffer);
+ if ('\0' == *buffer)
+ break;
+
+ if ('$' == *buffer) {
+ ++buffer;
+ if (TokenMatchI(buffer,"firstframe",10)) {
+ SkipSpaces(&buffer);
+ first = strtol10(buffer,&buffer);
+ }
+ else if (TokenMatchI(buffer,"lastframe",9)) {
+ SkipSpaces(&buffer);
+ last = strtol10(buffer,&buffer);
+ }
+ else if (TokenMatchI(buffer,"rate",4)) {
+ SkipSpaces(&buffer);
+ float d;
+ buffer = fast_atoreal_move<float>(buffer,d);
+ anim->mTicksPerSecond = d;
+ }
+ else if (TokenMatchI(buffer,"order",5)) {
+ std::vector< aiNodeAnim* > anims_temp;
+ anims_temp.reserve(30);
+ while (1) {
+ SkipSpaces(&buffer);
+ if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
+ break; // next section
+
+ // Construct a new node animation channel and setup its name
+ anims_temp.push_back(new aiNodeAnim());
+ aiNodeAnim* nda = anims_temp.back();
+
+ char* ot = nda->mNodeName.data;
+ while (!IsSpaceOrNewLine(*buffer))
+ *ot++ = *buffer++;
+
+ *ot = '\0';
+ nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
+ }
+
+ anim->mNumChannels = anims_temp.size();
+ if (!anim->mNumChannels)
+ throw DeadlyImportError("CSM: Empty $order section");
+
+ // copy over to the output animation
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+ ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
+ }
+ else if (TokenMatchI(buffer,"points",6)) {
+ if (!anim->mNumChannels)
+ throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
+
+ // If we know how many frames we'll read, we can preallocate some storage
+ unsigned int alloc = 100;
+ if (last != 0x00ffffff)
+ {
+ alloc = last-first;
+ alloc += alloc>>2u; // + 25%
+ for (unsigned int i = 0; i < anim->mNumChannels;++i)
+ anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
+ }
+
+ unsigned int filled = 0;
+
+ // Now read all point data.
+ while (1) {
+ SkipSpaces(&buffer);
+ if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) {
+ break; // next section
+ }
+
+ // read frame
+ const int frame = ::strtoul10(buffer,&buffer);
+ last = std::max(frame,last);
+ first = std::min(frame,last);
+ for (unsigned int i = 0; i < anim->mNumChannels;++i) {
+
+ aiNodeAnim* s = anim->mChannels[i];
+ if (s->mNumPositionKeys == alloc) { /* need to reallocate? */
+
+ aiVectorKey* old = s->mPositionKeys;
+ s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
+ ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
+ delete[] old;
+ }
+
+ // read x,y,z
+ if(!SkipSpacesAndLineEnd(&buffer))
+ throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample x coord");
+
+ if (TokenMatchI(buffer, "DROPOUT", 7)) {
+ // seems this is invalid marker data; at least the doc says it's possible
+ DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
+ }
+ else {
+ aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
+ sub->mTime = (double)frame;
+ buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
+
+ if(!SkipSpacesAndLineEnd(&buffer))
+ throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
+ buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
+
+ if(!SkipSpacesAndLineEnd(&buffer))
+ throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
+ buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
+
+ ++s->mNumPositionKeys;
+ }
+ }
+
+ // update allocation granularity
+ if (filled == alloc)
+ alloc *= 2;
+
+ ++filled;
+ }
+ // all channels must be complete in order to continue safely.
+ for (unsigned int i = 0; i < anim->mNumChannels;++i) {
+
+ if (!anim->mChannels[i]->mNumPositionKeys)
+ throw DeadlyImportError("CSM: Invalid marker track");
+ }
+ }
+ }
+ else {
+ // advance to the next line
+ SkipLine(&buffer);
+ }
+ }
+
+ // Setup a proper animation duration
+ anim->mDuration = last - std::min( first, 0 );
+
+ // build a dummy root node with the tiny markers as children
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("$CSM_DummyRoot");
+
+ pScene->mRootNode->mNumChildren = anim->mNumChannels;
+ pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
+
+ for (unsigned int i = 0; i < anim->mNumChannels;++i) {
+ aiNodeAnim* na = anim->mChannels[i];
+
+ aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
+ nd->mName = anim->mChannels[i]->mNodeName;
+ nd->mParent = pScene->mRootNode;
+
+ aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
+ }
+
+ // Store the one and only animation in the scene
+ pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1];
+ pScene->mAnimations[0] = anim;
+ anim->mName.Set("$CSM_MasterAnim");
+
+ // mark the scene as incomplete and run SkeletonMeshBuilder on it
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+
+ if (!noSkeletonMesh) {
+ SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
+ }
}
#endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER
diff --git a/src/3rdparty/assimp/code/CSMLoader.h b/src/3rdparty/assimp/code/CSMLoader.h
index 624782f47..71abb7e91 100644
--- a/src/3rdparty/assimp/code/CSMLoader.h
+++ b/src/3rdparty/assimp/code/CSMLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,7 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDED_AI_CSM_LOADER_H
#define INCLUDED_AI_CSM_LOADER_H
-namespace Assimp {
+
+#include "BaseImporter.h"
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class to load MOCAPs in CharacterStudio Motion format.
@@ -57,30 +60,30 @@ namespace Assimp {
class CSMImporter : public BaseImporter
{
public:
- CSMImporter();
- ~CSMImporter();
+ CSMImporter();
+ ~CSMImporter();
public:
- // -------------------------------------------------------------------
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
- // -------------------------------------------------------------------
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- bool noSkeletonMesh;
+ bool noSkeletonMesh;
}; // end of class CSMImporter
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
index 1d5e1bdec..dbba1bed3 100644
--- a/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
+++ b/src/3rdparty/assimp/code/CalcTangentsProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,30 +25,29 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file Implementation of the post processing step to calculate
+/** @file Implementation of the post processing step to calculate
* tangents and bitangents for all imported meshes
*/
-#include "AssimpPCH.h"
-
// internal headers
#include "CalcTangentsProcess.h"
#include "ProcessHelper.h"
#include "TinyFormatter.h"
+#include "qnan.h"
using namespace Assimp;
@@ -57,21 +56,21 @@ using namespace Assimp;
CalcTangentsProcess::CalcTangentsProcess()
: configMaxAngle( AI_DEG_TO_RAD(45.f) )
, configSourceUV( 0 ) {
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
CalcTangentsProcess::~CalcTangentsProcess()
{
- // nothing to do here
+ // 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;
+ return (pFlags & aiProcess_CalcTangentSpace) != 0;
}
// ------------------------------------------------------------------------------------------------
@@ -80,12 +79,12 @@ 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);
+ // 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);
+ configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
}
// ------------------------------------------------------------------------------------------------
@@ -96,12 +95,12 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
DefaultLogger::get()->debug("CalcTangentsProcess begin");
- bool bHas = false;
- for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
- if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
+ bool bHas = false;
+ for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
+ if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
}
- if ( bHas ) {
+ if ( bHas ) {
DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
} else {
DefaultLogger::get()->debug("CalcTangentsProcess finished");
@@ -109,109 +108,109 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
}
// ------------------------------------------------------------------------------------------------
-// Calculates tangents and bitangents for the given mesh
+// 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) // thisimplies 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)))
- {
- DefaultLogger::get()->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)
- {
- DefaultLogger::get()->error("Failed to compute tangents; need normals");
- return false;
- }
- if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
- {
- DefaultLogger::get()->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;
+ // 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)))
+ {
+ DefaultLogger::get()->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)
+ {
+ DefaultLogger::get()->error("Failed to compute tangents; need normals");
+ return false;
+ }
+ if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
+ {
+ DefaultLogger::get()->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;
+ 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 ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
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 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];
+ // 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.Normalize(); localBitangent.Normalize();
+ // 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.Normalize(); localBitangent.Normalize();
// 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);
@@ -221,98 +220,98 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
localTangent = meshNorm[p] ^ localBitangent;
localTangent.Normalize();
} else {
- localBitangent = localTangent ^ meshNorm[p];
+ localBitangent = localTangent ^ meshNorm[p];
localBitangent.Normalize();
}
}
// and write it into the mesh.
- meshTang[ p ] = localTangent;
- meshBitang[ p ] = localBitangent;
- }
+ 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 = cosf(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.clear();
-
- // 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;
+ // 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 = cosf(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;
}
diff --git a/src/3rdparty/assimp/code/CalcTangentsProcess.h b/src/3rdparty/assimp/code/CalcTangentsProcess.h
index 4ebc47fa4..4a6122668 100644
--- a/src/3rdparty/assimp/code/CalcTangentsProcess.h
+++ b/src/3rdparty/assimp/code/CalcTangentsProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,23 +23,23 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to calculate tangents and
+/** @file Defines a post processing step to calculate tangents and
bitangents on all imported meshes.*/
#ifndef AI_CALCTANGENTSPROCESS_H_INC
#define AI_CALCTANGENTSPROCESS_H_INC
@@ -54,60 +54,60 @@ 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
+ * because the joining of vertices also considers tangents and bitangents for
* uniqueness.
*/
class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess
{
public:
- CalcTangentsProcess();
- ~CalcTangentsProcess();
+ 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;
- }
+ // -------------------------------------------------------------------
+ /** 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);
+ // -------------------------------------------------------------------
+ /** 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);
+ // -------------------------------------------------------------------
+ /** 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;
+ /** Configuration option: maximum smoothing angle, in radians*/
+ float configMaxAngle;
+ unsigned int configSourceUV;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ColladaExporter.cpp b/src/3rdparty/assimp/code/ColladaExporter.cpp
index 2bf7deb72..14534ad72 100644
--- a/src/3rdparty/assimp/code/ColladaExporter.cpp
+++ b/src/3rdparty/assimp/code/ColladaExporter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,22 +23,22 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
@@ -46,8 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Bitmap.h"
#include "fast_atof.h"
-#include "SceneCombiner.h"
+#include "SceneCombiner.h"
+#include "DefaultIOSystem.h"
+#include "XMLTools.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/scene.h>
+
+#include "Exceptional.h"
+#include <memory>
#include <ctime>
#include <set>
@@ -58,222 +66,421 @@ namespace Assimp
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneCollada(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
- std::string path = "";
- std::string file = pFile;
-
- // We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable.
- // Moreover, the path given by some applications is not even consistent with the OS specific type of separator.
- const char* end_path = std::max(strrchr(pFile, '\\'), strrchr(pFile, '/'));
-
- if(end_path != NULL) {
- path = std::string(pFile, end_path + 1 - pFile);
- file = file.substr(end_path + 1 - pFile, file.npos);
-
- std::size_t pos = file.find_last_of('.');
- if(pos != file.npos) {
- file = file.substr(0, pos);
- }
- }
-
- // invoke the exporter
- ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);
-
- // we're still here - export successfully completed. Write result to the given IOSYstem
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
- }
-
- // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
- outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
+ std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+ std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
+
+ // invoke the exporter
+ ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);
+
+ // we're still here - export successfully completed. Write result to the given IOSYstem
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
+ }
+
+ // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
+ outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
}
} // end of namespace Assimp
+
// ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
{
- // make sure that all formatting happens using the standard, C locale and not the user's current locale
- mOutput.imbue( std::locale("C") );
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ mOutput.imbue( std::locale("C") );
+ mOutput.precision(16);
- mScene = pScene;
- mSceneOwned = false;
+ mScene = pScene;
+ mSceneOwned = false;
- // set up strings
- endstr = "\n";
+ // set up strings
+ endstr = "\n";
- // start writing
- WriteFile();
+ // start writing
+ WriteFile();
}
// ------------------------------------------------------------------------------------------------
// Destructor
ColladaExporter::~ColladaExporter()
{
- if(mSceneOwned) {
- delete mScene;
- }
+ if(mSceneOwned) {
+ delete mScene;
+ }
}
// ------------------------------------------------------------------------------------------------
// Starts writing the contents
void ColladaExporter::WriteFile()
{
- // write the DTD
- mOutput << "<?xml version=\"1.0\"?>" << endstr;
- // COLLADA element start
- mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr;
- PushTag();
-
- WriteTextures();
- WriteHeader();
-
- WriteMaterials();
- WriteGeometryLibrary();
-
- WriteSceneLibrary();
-
- // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
- mOutput << startstr << "<scene>" << endstr;
- PushTag();
- mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
- PopTag();
- mOutput << startstr << "</scene>" << endstr;
- PopTag();
- mOutput << "</COLLADA>" << endstr;
+ // write the DTD
+ mOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" << endstr;
+ // COLLADA element start
+ mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr;
+ PushTag();
+
+ WriteTextures();
+ WriteHeader();
+
+ WriteCamerasLibrary();
+ WriteLightsLibrary();
+ WriteMaterials();
+ WriteGeometryLibrary();
+
+ WriteSceneLibrary();
+
+ // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
+ mOutput << startstr << "<scene>" << endstr;
+ PushTag();
+ mOutput << startstr << "<instance_visual_scene url=\"#" + XMLEscape(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
+ PopTag();
+ mOutput << startstr << "</scene>" << endstr;
+ PopTag();
+ mOutput << "</COLLADA>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes the asset header
void ColladaExporter::WriteHeader()
{
- static const float epsilon = 0.000001f;
- static const aiQuaternion x_rot(aiMatrix3x3(
- 0, -1, 0,
- 1, 0, 0,
- 0, 0, 1));
- static const aiQuaternion y_rot(aiMatrix3x3(
- 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1));
- static const aiQuaternion z_rot(aiMatrix3x3(
- 1, 0, 0,
- 0, 0, 1,
- 0, -1, 0));
-
- static const unsigned int date_nb_chars = 20;
- char date_str[date_nb_chars];
- std::time_t date = std::time(NULL);
- std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
-
- std::string scene_name = mScene->mRootNode->mName.C_Str();
-
- aiVector3D scaling;
- aiQuaternion rotation;
- aiVector3D position;
- mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
-
- bool add_root_node = false;
-
- float scale = 1.0;
- if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
- scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
- } else {
- add_root_node = true;
- }
-
- std::string up_axis = "Y_UP";
- if(rotation.Equal(x_rot, epsilon)) {
- up_axis = "X_UP";
- } else if(rotation.Equal(y_rot, epsilon)) {
- up_axis = "Y_UP";
- } else if(rotation.Equal(z_rot, epsilon)) {
- up_axis = "Z_UP";
- } else {
- add_root_node = true;
- }
-
- if(! position.Equal(aiVector3D(0, 0, 0))) {
- add_root_node = true;
- }
-
- if(mScene->mRootNode->mNumChildren == 0) {
- add_root_node = true;
- }
-
- if(add_root_node) {
- aiScene* scene;
- SceneCombiner::CopyScene(&scene, mScene);
-
- aiNode* root = new aiNode("Scene");
-
- root->mNumChildren = 1;
- root->mChildren = new aiNode*[root->mNumChildren];
-
- root->mChildren[0] = scene->mRootNode;
- scene->mRootNode->mParent = root;
- scene->mRootNode = root;
-
- mScene = scene;
- mSceneOwned = true;
-
- up_axis = "Y_UP";
- scale = 1.0;
- }
-
- mOutput << startstr << "<asset>" << endstr;
- PushTag();
- mOutput << startstr << "<contributor>" << endstr;
- PushTag();
- mOutput << startstr << "<author>Assimp</author>" << endstr;
- mOutput << startstr << "<authoring_tool>Assimp Collada Exporter</authoring_tool>" << endstr;
- PopTag();
- mOutput << startstr << "</contributor>" << endstr;
- mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
- mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
- mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
- mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
- PopTag();
- mOutput << startstr << "</asset>" << endstr;
+ static const float epsilon = 0.00001f;
+ static const aiQuaternion x_rot(aiMatrix3x3(
+ 0, -1, 0,
+ 1, 0, 0,
+ 0, 0, 1));
+ static const aiQuaternion y_rot(aiMatrix3x3(
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1));
+ static const aiQuaternion z_rot(aiMatrix3x3(
+ 1, 0, 0,
+ 0, 0, 1,
+ 0, -1, 0));
+
+ static const unsigned int date_nb_chars = 20;
+ char date_str[date_nb_chars];
+ std::time_t date = std::time(NULL);
+ std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
+
+ aiVector3D scaling;
+ aiQuaternion rotation;
+ aiVector3D position;
+ mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
+ rotation.Normalize();
+
+ bool add_root_node = false;
+
+ float scale = 1.0;
+ if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
+ scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
+ } else {
+ add_root_node = true;
+ }
+
+ std::string up_axis = "Y_UP";
+ if(rotation.Equal(x_rot, epsilon)) {
+ up_axis = "X_UP";
+ } else if(rotation.Equal(y_rot, epsilon)) {
+ up_axis = "Y_UP";
+ } else if(rotation.Equal(z_rot, epsilon)) {
+ up_axis = "Z_UP";
+ } else {
+ add_root_node = true;
+ }
+
+ if(! position.Equal(aiVector3D(0, 0, 0))) {
+ add_root_node = true;
+ }
+
+ if(mScene->mRootNode->mNumChildren == 0) {
+ add_root_node = true;
+ }
+
+ if(add_root_node) {
+ aiScene* scene;
+ SceneCombiner::CopyScene(&scene, mScene);
+
+ aiNode* root = new aiNode("Scene");
+
+ root->mNumChildren = 1;
+ root->mChildren = new aiNode*[root->mNumChildren];
+
+ root->mChildren[0] = scene->mRootNode;
+ scene->mRootNode->mParent = root;
+ scene->mRootNode = root;
+
+ mScene = scene;
+ mSceneOwned = true;
+
+ up_axis = "Y_UP";
+ scale = 1.0;
+ }
+
+ mOutput << startstr << "<asset>" << endstr;
+ PushTag();
+ mOutput << startstr << "<contributor>" << endstr;
+ PushTag();
+
+ aiMetadata* meta = mScene->mRootNode->mMetaData;
+ aiString value;
+ if (!meta || !meta->Get("Author", value))
+ mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
+ else
+ mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
+
+ if (!meta || !meta->Get("AuthoringTool", value))
+ mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
+ else
+ mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
+
+ //mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
+ //mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</contributor>" << endstr;
+ mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
+ mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
+ mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
+ mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
+ PopTag();
+ mOutput << startstr << "</asset>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Write the embedded textures
void ColladaExporter::WriteTextures() {
- static const unsigned int buffer_size = 1024;
- char str[buffer_size];
+ static const unsigned int buffer_size = 1024;
+ char str[buffer_size];
+
+ if(mScene->HasTextures()) {
+ for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
+ // It would be great to be able to create a directory in portable standard C++, but it's not the case,
+ // so we just write the textures in the current directory.
- if(mScene->HasTextures()) {
- for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
- // It would be great to be able to create a directory in portable standard C++, but it's not the case,
- // so we just write the textures in the current directory.
+ aiTexture* texture = mScene->mTextures[i];
- aiTexture* texture = mScene->mTextures[i];
+ ASSIMP_itoa10(str, buffer_size, i + 1);
- ASSIMP_itoa10(str, buffer_size, i + 1);
+ std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
- std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
+ std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output texture file: " + mPath + name);
+ }
- boost::scoped_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output texture file: " + mPath + name);
- }
+ if(texture->mHeight == 0) {
+ outfile->Write((void*) texture->pcData, texture->mWidth, 1);
+ } else {
+ Bitmap::Save(texture, outfile.get());
+ }
+
+ outfile->Flush();
+
+ textures.insert(std::make_pair(i, name));
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Write the embedded textures
+void ColladaExporter::WriteCamerasLibrary() {
+ if(mScene->HasCameras()) {
+
+ mOutput << startstr << "<library_cameras>" << endstr;
+ PushTag();
+
+ for( size_t a = 0; a < mScene->mNumCameras; ++a)
+ WriteCamera( a);
+
+ PopTag();
+ mOutput << startstr << "</library_cameras>" << endstr;
+
+ }
+}
+
+void ColladaExporter::WriteCamera(size_t pIndex){
+
+ const aiCamera *cam = mScene->mCameras[pIndex];
+ const std::string idstrEscaped = XMLEscape(cam->mName.C_Str());
+
+ mOutput << startstr << "<camera id=\"" << idstrEscaped << "-camera\" name=\"" << idstrEscaped << "_name\" >" << endstr;
+ PushTag();
+ mOutput << startstr << "<optics>" << endstr;
+ PushTag();
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+ //assimp doesn't support the import of orthographic cameras! se we write
+ //always perspective
+ mOutput << startstr << "<perspective>" << endstr;
+ PushTag();
+ mOutput << startstr << "<xfov sid=\"xfov\">"<<
+ AI_RAD_TO_DEG(cam->mHorizontalFOV)
+ <<"</xfov>" << endstr;
+ mOutput << startstr << "<aspect_ratio>"
+ << cam->mAspect
+ << "</aspect_ratio>" << endstr;
+ mOutput << startstr << "<znear sid=\"znear\">"
+ << cam->mClipPlaneNear
+ << "</znear>" << endstr;
+ mOutput << startstr << "<zfar sid=\"zfar\">"
+ << cam->mClipPlaneFar
+ << "</zfar>" << endstr;
+ PopTag();
+ mOutput << startstr << "</perspective>" << endstr;
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+ PopTag();
+ mOutput << startstr << "</optics>" << endstr;
+ PopTag();
+ mOutput << startstr << "</camera>" << endstr;
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Write the embedded textures
+void ColladaExporter::WriteLightsLibrary() {
+ if(mScene->HasLights()) {
+
+ mOutput << startstr << "<library_lights>" << endstr;
+ PushTag();
+
+ for( size_t a = 0; a < mScene->mNumLights; ++a)
+ WriteLight( a);
+
+ PopTag();
+ mOutput << startstr << "</library_lights>" << endstr;
+
+ }
+}
+
+void ColladaExporter::WriteLight(size_t pIndex){
+
+ const aiLight *light = mScene->mLights[pIndex];
+ const std::string idstrEscaped = XMLEscape(light->mName.C_Str());
+
+ mOutput << startstr << "<light id=\"" << idstrEscaped << "-light\" name=\""
+ << idstrEscaped << "_name\" >" << endstr;
+ PushTag();
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+ switch(light->mType){
+ case aiLightSource_AMBIENT:
+ WriteAmbienttLight(light);
+ break;
+ case aiLightSource_DIRECTIONAL:
+ WriteDirectionalLight(light);
+ break;
+ case aiLightSource_POINT:
+ WritePointLight(light);
+ break;
+ case aiLightSource_SPOT:
+ WriteSpotLight(light);
+ break;
+ case aiLightSource_AREA:
+ case aiLightSource_UNDEFINED:
+ case _aiLightSource_Force32Bit:
+ break;
+ }
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</light>" << endstr;
+
+}
+
+void ColladaExporter::WritePointLight(const aiLight *const light){
+ const aiColor3D &color= light->mColorDiffuse;
+ mOutput << startstr << "<point>" << endstr;
+ PushTag();
+ mOutput << startstr << "<color sid=\"color\">"
+ << color.r<<" "<<color.g<<" "<<color.b
+ <<"</color>" << endstr;
+ mOutput << startstr << "<constant_attenuation>"
+ << light->mAttenuationConstant
+ <<"</constant_attenuation>" << endstr;
+ mOutput << startstr << "<linear_attenuation>"
+ << light->mAttenuationLinear
+ <<"</linear_attenuation>" << endstr;
+ mOutput << startstr << "<quadratic_attenuation>"
+ << light->mAttenuationQuadratic
+ <<"</quadratic_attenuation>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</point>" << endstr;
+
+}
+void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
+ const aiColor3D &color= light->mColorDiffuse;
+ mOutput << startstr << "<directional>" << endstr;
+ PushTag();
+ mOutput << startstr << "<color sid=\"color\">"
+ << color.r<<" "<<color.g<<" "<<color.b
+ <<"</color>" << endstr;
+
+ PopTag();
+ mOutput << startstr << "</directional>" << endstr;
+
+}
+void ColladaExporter::WriteSpotLight(const aiLight *const light){
+
+ const aiColor3D &color= light->mColorDiffuse;
+ mOutput << startstr << "<spot>" << endstr;
+ PushTag();
+ mOutput << startstr << "<color sid=\"color\">"
+ << color.r<<" "<<color.g<<" "<<color.b
+ <<"</color>" << endstr;
+ mOutput << startstr << "<constant_attenuation>"
+ << light->mAttenuationConstant
+ <<"</constant_attenuation>" << endstr;
+ mOutput << startstr << "<linear_attenuation>"
+ << light->mAttenuationLinear
+ <<"</linear_attenuation>" << endstr;
+ mOutput << startstr << "<quadratic_attenuation>"
+ << light->mAttenuationQuadratic
+ <<"</quadratic_attenuation>" << endstr;
+ /*
+ out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
+ srcLight->mFalloffAngle);
+ */
+
+ const float fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone);
+ mOutput << startstr <<"<falloff_angle sid=\"fall_off_angle\">"
+ << fallOffAngle
+ <<"</falloff_angle>" << endstr;
+ double temp = light->mAngleOuterCone-light->mAngleInnerCone;
+
+ temp = std::cos(temp);
+ temp = std::log(temp)/std::log(0.1);
+ temp = 1/temp;
+ mOutput << startstr << "<falloff_exponent sid=\"fall_off_exponent\">"
+ << temp
+ <<"</falloff_exponent>" << endstr;
+
+
+ PopTag();
+ mOutput << startstr << "</spot>" << endstr;
+
+}
- if(texture->mHeight == 0) {
- outfile->Write((void*) texture->pcData, texture->mWidth, 1);
- } else {
- Bitmap::Save(texture, outfile.get());
- }
+void ColladaExporter::WriteAmbienttLight(const aiLight *const light){
- outfile->Flush();
+ const aiColor3D &color= light->mColorAmbient;
+ mOutput << startstr << "<ambient>" << endstr;
+ PushTag();
+ mOutput << startstr << "<color sid=\"color\">"
+ << color.r<<" "<<color.g<<" "<<color.b
+ <<"</color>" << endstr;
- textures.insert(std::make_pair(i, name));
- }
- }
+ PopTag();
+ mOutput << startstr << "</ambient>" << endstr;
}
// ------------------------------------------------------------------------------------------------
@@ -290,30 +497,30 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
if(index_str.size() != 0 && index_str[0] == '*')
{
- unsigned int index;
+ unsigned int index;
- index_str = index_str.substr(1, std::string::npos);
+ index_str = index_str.substr(1, std::string::npos);
- try {
- index = (unsigned int) strtoul10_64(index_str.c_str());
- } catch(std::exception& error) {
- throw DeadlyExportError(error.what());
- }
+ try {
+ index = (unsigned int) strtoul10_64(index_str.c_str());
+ } catch(std::exception& error) {
+ throw DeadlyExportError(error.what());
+ }
- std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
+ std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
- if(name != textures.end()) {
- poSurface.texture = name->second;
- } else {
- throw DeadlyExportError("could not find embedded texture at index " + index_str);
- }
+ if(name != textures.end()) {
+ poSurface.texture = name->second;
+ } else {
+ throw DeadlyExportError("could not find embedded texture at index " + index_str);
+ }
} else
{
- poSurface.texture = texfile.C_Str();
+ poSurface.texture = texfile.C_Str();
}
poSurface.channel = uvChannel;
- poSurface.exist = true;
+ poSurface.exist = true;
} else
{
if( pKey )
@@ -322,21 +529,32 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
}
// ------------------------------------------------------------------------------------------------
+// Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version.
+static bool isalnum_C(char c)
+{
+ return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) );
+}
+
+// ------------------------------------------------------------------------------------------------
// Writes an image entry for the given surface
void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd)
{
if( !pSurface.texture.empty() )
{
- mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
- PushTag();
+ mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
+ PushTag();
mOutput << startstr << "<init_from>";
+
+ // URL encode image file name first, then XML encode on top
+ std::stringstream imageUrlEncoded;
for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
{
- if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
- mOutput << *it;
+ if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
+ imageUrlEncoded << *it;
else
- mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
+ imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
}
+ mOutput << XMLEscape(imageUrlEncoded.str());
mOutput << "</init_from>" << endstr;
PopTag();
mOutput << startstr << "</image>" << endstr;
@@ -353,9 +571,10 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
if( pSurface.texture.empty() )
{
mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "</color>" << endstr;
- } else
+ }
+ else
{
- mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
+ mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
}
PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr;
@@ -369,21 +588,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
// if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
if( !pSurface.texture.empty() )
{
- mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
+ mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag();
- mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
+ mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag();
mOutput << startstr << "</surface>" << endstr;
PopTag();
mOutput << startstr << "</newparam>" << endstr;
- mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
+ mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
PushTag();
mOutput << startstr << "<sampler2D>" << endstr;
PushTag();
- mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
+ mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
PopTag();
mOutput << startstr << "</sampler2D>" << endstr;
PopTag();
@@ -395,13 +614,13 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
// Writes a scalar property
void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName)
{
- if(pProperty.exist) {
- mOutput << startstr << "<" << pTypeName << ">" << endstr;
- PushTag();
- mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
- PopTag();
- mOutput << startstr << "</" << pTypeName << ">" << endstr;
- }
+ if(pProperty.exist) {
+ mOutput << startstr << "<" << pTypeName << ">" << endstr;
+ PushTag();
+ mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
+ PopTag();
+ mOutput << startstr << "</" << pTypeName << ">" << endstr;
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -410,8 +629,6 @@ void ColladaExporter::WriteMaterials()
{
materials.resize( mScene->mNumMaterials);
- std::set<std::string> material_names;
-
/// collect all materials from the scene
size_t numTextures = 0;
for( size_t a = 0; a < mScene->mNumMaterials; ++a )
@@ -421,28 +638,26 @@ void ColladaExporter::WriteMaterials()
aiString name;
if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
name = "mat";
- materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
+ materials[a].name = std::string( "m") + std::to_string(a) + name.C_Str();
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
- // isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
- // of char to signed int and take the unsigned char value.
- if( !isalnum( static_cast<uint8_t>(*it) ) ) {
+ if( !isalnum_C( *it ) ) {
*it = '_';
- }
- }
-
- aiShadingMode shading;
- materials[a].shading_model = "phong";
- if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
- if(shading == aiShadingMode_Phong) {
- materials[a].shading_model = "phong";
- } else if(shading == aiShadingMode_Blinn) {
- materials[a].shading_model = "blinn";
- } else if(shading == aiShadingMode_NoShading) {
- materials[a].shading_model = "constant";
- } else if(shading == aiShadingMode_Gouraud) {
- materials[a].shading_model = "lambert";
- }
- }
+ }
+ }
+
+ aiShadingMode shading = aiShadingMode_Flat;
+ materials[a].shading_model = "phong";
+ if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
+ if(shading == aiShadingMode_Phong) {
+ materials[a].shading_model = "phong";
+ } else if(shading == aiShadingMode_Blinn) {
+ materials[a].shading_model = "blinn";
+ } else if(shading == aiShadingMode_NoShading) {
+ materials[a].shading_model = "constant";
+ } else if(shading == aiShadingMode_Gouraud) {
+ materials[a].shading_model = "lambert";
+ }
+ }
ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
if( !materials[a].ambient.texture.empty() ) numTextures++;
@@ -454,31 +669,31 @@ void ColladaExporter::WriteMaterials()
if( !materials[a].emissive.texture.empty() ) numTextures++;
ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE);
if( !materials[a].reflective.texture.empty() ) numTextures++;
- ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT);
+ ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT);
if( !materials[a].transparent.texture.empty() ) numTextures++;
ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0);
if( !materials[a].normal.texture.empty() ) numTextures++;
- materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS;
- materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS;
- materials[a].transparency.value = 1 - materials[a].transparency.value;
- materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
+ materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS;
+ materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS;
+ materials[a].transparency.value = 1 - materials[a].transparency.value;
+ materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
}
// output textures if present
if( numTextures > 0 )
{
- mOutput << startstr << "<library_images>" << endstr;
+ mOutput << startstr << "<library_images>" << endstr;
PushTag();
for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
- {
+ {
const Material& mat = *it;
WriteImageEntry( mat.ambient, mat.name + "-ambient-image");
WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image");
WriteImageEntry( mat.specular, mat.name + "-specular-image");
WriteImageEntry( mat.emissive, mat.name + "-emission-image");
WriteImageEntry( mat.reflective, mat.name + "-reflective-image");
- WriteImageEntry( mat.transparent, mat.name + "-transparent-image");
+ WriteImageEntry( mat.transparent, mat.name + "-transparent-image");
WriteImageEntry( mat.normal, mat.name + "-normal-image");
}
PopTag();
@@ -494,7 +709,7 @@ void ColladaExporter::WriteMaterials()
{
const Material& mat = *it;
// this is so ridiculous it must be right
- mOutput << startstr << "<effect id=\"" << mat.name << "-fx\" name=\"" << mat.name << "\">" << endstr;
+ mOutput << startstr << "<effect id=\"" << XMLEscape(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
PushTag();
mOutput << startstr << "<profile_COMMON>" << endstr;
PushTag();
@@ -505,27 +720,27 @@ void ColladaExporter::WriteMaterials()
WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name);
WriteTextureParamEntry( mat.specular, "specular", mat.name);
WriteTextureParamEntry( mat.reflective, "reflective", mat.name);
- WriteTextureParamEntry( mat.transparent, "transparent", mat.name);
- WriteTextureParamEntry( mat.normal, "normal", mat.name);
+ WriteTextureParamEntry( mat.transparent, "transparent", mat.name);
+ WriteTextureParamEntry( mat.normal, "normal", mat.name);
mOutput << startstr << "<technique sid=\"standard\">" << endstr;
PushTag();
- mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
+ mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
PushTag();
WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler");
WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler");
WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler");
WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler");
- WriteFloatEntry(mat.shininess, "shininess");
+ WriteFloatEntry(mat.shininess, "shininess");
WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler");
- WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler");
- WriteFloatEntry(mat.transparency, "transparency");
- WriteFloatEntry(mat.index_refraction, "index_of_refraction");
+ WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler");
+ WriteFloatEntry(mat.transparency, "transparency");
+ WriteFloatEntry(mat.index_refraction, "index_of_refraction");
- if(! mat.normal.texture.empty()) {
- WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler");
- }
+ if(! mat.normal.texture.empty()) {
+ WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler");
+ }
PopTag();
mOutput << startstr << "</" << mat.shading_model << ">" << endstr;
@@ -545,9 +760,9 @@ void ColladaExporter::WriteMaterials()
for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
{
const Material& mat = *it;
- mOutput << startstr << "<material id=\"" << mat.name << "\" name=\"" << mat.name << "\">" << endstr;
+ mOutput << startstr << "<material id=\"" << XMLEscape(mat.name) << "\" name=\"" << mat.name << "\">" << endstr;
PushTag();
- mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
+ mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
PopTag();
mOutput << startstr << "</material>" << endstr;
}
@@ -560,262 +775,368 @@ void ColladaExporter::WriteMaterials()
// Writes the geometry library
void ColladaExporter::WriteGeometryLibrary()
{
- mOutput << startstr << "<library_geometries>" << endstr;
- PushTag();
+ mOutput << startstr << "<library_geometries>" << endstr;
+ PushTag();
- for( size_t a = 0; a < mScene->mNumMeshes; ++a)
- WriteGeometry( a);
+ for( size_t a = 0; a < mScene->mNumMeshes; ++a)
+ WriteGeometry( a);
- PopTag();
- mOutput << startstr << "</library_geometries>" << endstr;
+ PopTag();
+ mOutput << startstr << "</library_geometries>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes the given mesh
void ColladaExporter::WriteGeometry( size_t pIndex)
{
- const aiMesh* mesh = mScene->mMeshes[pIndex];
- std::string idstr = GetMeshId( pIndex);
+ const aiMesh* mesh = mScene->mMeshes[pIndex];
+ const std::string idstr = GetMeshId( pIndex);
+ const std::string idstrEscaped = XMLEscape(idstr);
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
return;
- // opening tag
- mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
- PushTag();
-
- mOutput << startstr << "<mesh>" << endstr;
- PushTag();
-
- // Positions
- WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices);
- // Normals, if any
- if( mesh->HasNormals() )
- WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices);
-
- // texture coords
- for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
- {
- if( mesh->HasTextureCoords( a) )
- {
- WriteFloatArray( idstr + "-tex" + boost::lexical_cast<std::string> (a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
- (float*) mesh->mTextureCoords[a], mesh->mNumVertices);
- }
- }
-
- // vertex colors
- for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
- {
- if( mesh->HasVertexColors( a) )
- WriteFloatArray( idstr + "-color" + boost::lexical_cast<std::string> (a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices);
- }
-
- // assemble vertex structure
- mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
- PushTag();
- mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
- if( mesh->HasNormals() )
- mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstr << "-normals\" />" << endstr;
- for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
- {
- if( mesh->HasTextureCoords( a) )
- mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstr << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
- }
- for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
- {
- if( mesh->HasVertexColors( a) )
- mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstr << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
- }
-
- PopTag();
- mOutput << startstr << "</vertices>" << endstr;
-
- // write face setup
- mOutput << startstr << "<polylist count=\"" << mesh->mNumFaces << "\" material=\"theresonlyone\">" << endstr;
- PushTag();
- mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
-
- mOutput << startstr << "<vcount>";
- for( size_t a = 0; a < mesh->mNumFaces; ++a )
- mOutput << mesh->mFaces[a].mNumIndices << " ";
- mOutput << "</vcount>" << endstr;
-
- mOutput << startstr << "<p>";
- for( size_t a = 0; a < mesh->mNumFaces; ++a )
- {
- const aiFace& face = mesh->mFaces[a];
- for( size_t b = 0; b < face.mNumIndices; ++b )
- mOutput << face.mIndices[b] << " ";
- }
- mOutput << "</p>" << endstr;
- PopTag();
- mOutput << startstr << "</polylist>" << endstr;
-
- // closing tags
- PopTag();
- mOutput << startstr << "</mesh>" << endstr;
- PopTag();
- mOutput << startstr << "</geometry>" << endstr;
+ // opening tag
+ mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
+ PushTag();
+
+ mOutput << startstr << "<mesh>" << endstr;
+ PushTag();
+
+ // Positions
+ WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices);
+ // Normals, if any
+ if( mesh->HasNormals() )
+ WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices);
+
+ // texture coords
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
+ {
+ if( mesh->HasTextureCoords( a) )
+ {
+ WriteFloatArray( idstr + "-tex" + std::to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
+ (float*) mesh->mTextureCoords[a], mesh->mNumVertices);
+ }
+ }
+
+ // vertex colors
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
+ {
+ if( mesh->HasVertexColors( a) )
+ WriteFloatArray( idstr + "-color" + std::to_string(a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices);
+ }
+
+ // assemble vertex structure
+ mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
+ PushTag();
+ mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
+ if( mesh->HasNormals() )
+ mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+ {
+ if( mesh->HasTextureCoords( a) )
+ mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
+ }
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
+ {
+ if( mesh->HasVertexColors( a) )
+ mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
+ }
+
+ PopTag();
+ mOutput << startstr << "</vertices>" << endstr;
+
+ // count the number of lines, triangles and polygon meshes
+ int countLines = 0;
+ int countPoly = 0;
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ if (mesh->mFaces[a].mNumIndices == 2) countLines++;
+ else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++;
+ }
+
+ // lines
+ if (countLines)
+ {
+ mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
+ PushTag();
+ mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+ mOutput << startstr << "<p>";
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ const aiFace& face = mesh->mFaces[a];
+ if (face.mNumIndices != 2) continue;
+ for( size_t b = 0; b < face.mNumIndices; ++b )
+ mOutput << face.mIndices[b] << " ";
+ }
+ mOutput << "</p>" << endstr;
+ PopTag();
+ mOutput << startstr << "</lines>" << endstr;
+ }
+
+ // triangle - don't use it, because compatibility problems
+
+ // polygons
+ if (countPoly)
+ {
+ mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
+ PushTag();
+ mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+ {
+ if( mesh->HasTextureCoords( a) )
+ mOutput << startstr << "<input offset=\"0\" semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" set=\"" << a << "\" />" << endstr;
+ }
+
+ mOutput << startstr << "<vcount>";
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ if (mesh->mFaces[a].mNumIndices < 3) continue;
+ mOutput << mesh->mFaces[a].mNumIndices << " ";
+ }
+ mOutput << "</vcount>" << endstr;
+
+ mOutput << startstr << "<p>";
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ const aiFace& face = mesh->mFaces[a];
+ if (face.mNumIndices < 3) continue;
+ for( size_t b = 0; b < face.mNumIndices; ++b )
+ mOutput << face.mIndices[b] << " ";
+ }
+ mOutput << "</p>" << endstr;
+ PopTag();
+ mOutput << startstr << "</polylist>" << endstr;
+ }
+
+ // closing tags
+ PopTag();
+ mOutput << startstr << "</mesh>" << endstr;
+ PopTag();
+ mOutput << startstr << "</geometry>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes a float array of the given type
void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount)
{
- size_t floatsPerElement = 0;
- switch( pType )
- {
- case FloatType_Vector: floatsPerElement = 3; break;
- case FloatType_TexCoord2: floatsPerElement = 2; break;
- case FloatType_TexCoord3: floatsPerElement = 3; break;
- case FloatType_Color: floatsPerElement = 3; break;
- default:
- return;
- }
-
- std::string arrayId = pIdString + "-array";
-
- mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
- PushTag();
-
- // source array
- mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
- PushTag();
-
- if( pType == FloatType_TexCoord2 )
- {
- for( size_t a = 0; a < pElementCount; ++a )
- {
- mOutput << pData[a*3+0] << " ";
- mOutput << pData[a*3+1] << " ";
- }
- }
- else if( pType == FloatType_Color )
- {
- for( size_t a = 0; a < pElementCount; ++a )
- {
- mOutput << pData[a*4+0] << " ";
- mOutput << pData[a*4+1] << " ";
- mOutput << pData[a*4+2] << " ";
- }
- }
- else
- {
- for( size_t a = 0; a < pElementCount * floatsPerElement; ++a )
- mOutput << pData[a] << " ";
- }
- mOutput << "</float_array>" << endstr;
- PopTag();
-
- // the usual Collada fun. Let's bloat it even more!
- mOutput << startstr << "<technique_common>" << endstr;
- PushTag();
- mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr;
- PushTag();
-
- switch( pType )
- {
- case FloatType_Vector:
- mOutput << startstr << "<param name=\"X\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"Y\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"Z\" type=\"float\" />" << endstr;
- break;
-
- case FloatType_TexCoord2:
- mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
- break;
-
- case FloatType_TexCoord3:
- mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"P\" type=\"float\" />" << endstr;
- break;
-
- case FloatType_Color:
- mOutput << startstr << "<param name=\"R\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
- mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
- break;
- }
-
- PopTag();
- mOutput << startstr << "</accessor>" << endstr;
- PopTag();
- mOutput << startstr << "</technique_common>" << endstr;
- PopTag();
- mOutput << startstr << "</source>" << endstr;
+ size_t floatsPerElement = 0;
+ switch( pType )
+ {
+ case FloatType_Vector: floatsPerElement = 3; break;
+ case FloatType_TexCoord2: floatsPerElement = 2; break;
+ case FloatType_TexCoord3: floatsPerElement = 3; break;
+ case FloatType_Color: floatsPerElement = 3; break;
+ default:
+ return;
+ }
+
+ std::string arrayId = pIdString + "-array";
+
+ mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
+ PushTag();
+
+ // source array
+ mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
+ PushTag();
+
+ if( pType == FloatType_TexCoord2 )
+ {
+ for( size_t a = 0; a < pElementCount; ++a )
+ {
+ mOutput << pData[a*3+0] << " ";
+ mOutput << pData[a*3+1] << " ";
+ }
+ }
+ else if( pType == FloatType_Color )
+ {
+ for( size_t a = 0; a < pElementCount; ++a )
+ {
+ mOutput << pData[a*4+0] << " ";
+ mOutput << pData[a*4+1] << " ";
+ mOutput << pData[a*4+2] << " ";
+ }
+ }
+ else
+ {
+ for( size_t a = 0; a < pElementCount * floatsPerElement; ++a )
+ mOutput << pData[a] << " ";
+ }
+ mOutput << "</float_array>" << endstr;
+ PopTag();
+
+ // the usual Collada fun. Let's bloat it even more!
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+ mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr;
+ PushTag();
+
+ switch( pType )
+ {
+ case FloatType_Vector:
+ mOutput << startstr << "<param name=\"X\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"Y\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"Z\" type=\"float\" />" << endstr;
+ break;
+
+ case FloatType_TexCoord2:
+ mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
+ break;
+
+ case FloatType_TexCoord3:
+ mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"P\" type=\"float\" />" << endstr;
+ break;
+
+ case FloatType_Color:
+ mOutput << startstr << "<param name=\"R\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
+ mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
+ break;
+ }
+
+ PopTag();
+ mOutput << startstr << "</accessor>" << endstr;
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+ PopTag();
+ mOutput << startstr << "</source>" << endstr;
}
// ------------------------------------------------------------------------------------------------
// Writes the scene library
void ColladaExporter::WriteSceneLibrary()
{
- std::string scene_name = mScene->mRootNode->mName.C_Str();
+ const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
+
+ mOutput << startstr << "<library_visual_scenes>" << endstr;
+ PushTag();
+ mOutput << startstr << "<visual_scene id=\"" + scene_name_escaped + "\" name=\"" + scene_name_escaped + "\">" << endstr;
+ PushTag();
- mOutput << startstr << "<library_visual_scenes>" << endstr;
- PushTag();
- mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << endstr;
- PushTag();
+ // start recursive write at the root node
+ for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a )
+ WriteNode( mScene, mScene->mRootNode->mChildren[a]);
- // start recursive write at the root node
- for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a )
- WriteNode( mScene->mRootNode->mChildren[a]);
+ PopTag();
+ mOutput << startstr << "</visual_scene>" << endstr;
+ PopTag();
+ mOutput << startstr << "</library_visual_scenes>" << endstr;
+}
- PopTag();
- mOutput << startstr << "</visual_scene>" << endstr;
- PopTag();
- mOutput << startstr << "</library_visual_scenes>" << endstr;
+// ------------------------------------------------------------------------------------------------
+// Helper to find a bone by name in the scene
+aiBone* findBone( const aiScene* scene, const char * name) {
+ for (size_t m=0; m<scene->mNumMeshes; m++) {
+ aiMesh * mesh = scene->mMeshes[m];
+ for (size_t b=0; b<mesh->mNumBones; b++) {
+ aiBone * bone = mesh->mBones[b];
+ if (0 == strcmp(name, bone->mName.C_Str())) {
+ return bone;
+ }
+ }
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
// Recursively writes the given node
-void ColladaExporter::WriteNode( const aiNode* pNode)
+void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
{
- mOutput << startstr << "<node id=\"" << pNode->mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr;
- PushTag();
-
- // write transformation - we can directly put the matrix there
- // TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards
- const aiMatrix4x4& mat = pNode->mTransformation;
- mOutput << startstr << "<matrix>";
- mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " ";
- mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " ";
- mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " ";
- mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4;
- mOutput << "</matrix>" << endstr;
-
- // instance every geometry
- for( size_t a = 0; a < pNode->mNumMeshes; ++a )
- {
- const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
- // do not instanciate mesh if empty. I wonder how this could happen
- if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
- continue;
-
- mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
- PushTag();
- mOutput << startstr << "<bind_material>" << endstr;
- PushTag();
- mOutput << startstr << "<technique_common>" << endstr;
- PushTag();
- mOutput << startstr << "<instance_material symbol=\"theresonlyone\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
- PopTag();
- mOutput << startstr << "</technique_common>" << endstr;
- PopTag();
- mOutput << startstr << "</bind_material>" << endstr;
- PopTag();
- mOutput << startstr << "</instance_geometry>" << endstr;
- }
-
- // recurse into subnodes
- for( size_t a = 0; a < pNode->mNumChildren; ++a )
- WriteNode( pNode->mChildren[a]);
-
- PopTag();
- mOutput << startstr << "</node>" << endstr;
+ // the node must have a name
+ if (pNode->mName.length == 0)
+ {
+ std::stringstream ss;
+ ss << "Node_" << pNode;
+ pNode->mName.Set(ss.str());
+ }
+
+ // If the node is associated with a bone, it is a joint node (JOINT)
+ // otherwise it is a normal node (NODE)
+ const char * node_type;
+ if (NULL == findBone(pScene, pNode->mName.C_Str())) {
+ node_type = "NODE";
+ } else {
+ node_type = "JOINT";
+ }
+
+ const std::string node_name_escaped = XMLEscape(pNode->mName.data);
+ mOutput << startstr
+ << "<node id=\"" << node_name_escaped
+ << "\" name=\"" << node_name_escaped
+ << "\" type=\"" << node_type
+ << "\">" << endstr;
+ PushTag();
+
+ // write transformation - we can directly put the matrix there
+ // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards
+ const aiMatrix4x4& mat = pNode->mTransformation;
+ mOutput << startstr << "<matrix>";
+ mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " ";
+ mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " ";
+ mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " ";
+ mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4;
+ mOutput << "</matrix>" << endstr;
+
+ if(pNode->mNumMeshes==0){
+ //check if it is a camera node
+ for(size_t i=0; i<mScene->mNumCameras; i++){
+ if(mScene->mCameras[i]->mName == pNode->mName){
+ mOutput << startstr <<"<instance_camera url=\"#" << node_name_escaped << "-camera\"/>" << endstr;
+ break;
+ }
+ }
+ //check if it is a light node
+ for(size_t i=0; i<mScene->mNumLights; i++){
+ if(mScene->mLights[i]->mName == pNode->mName){
+ mOutput << startstr <<"<instance_light url=\"#" << node_name_escaped << "-light\"/>" << endstr;
+ break;
+ }
+ }
+
+ }else
+ // instance every geometry
+ for( size_t a = 0; a < pNode->mNumMeshes; ++a )
+ {
+ const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
+ // do not instanciate mesh if empty. I wonder how this could happen
+ if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+ continue;
+ mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
+ PushTag();
+ mOutput << startstr << "<bind_material>" << endstr;
+ PushTag();
+ mOutput << startstr << "<technique_common>" << endstr;
+ PushTag();
+ mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
+ PushTag();
+ for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+ {
+ if( mesh->HasTextureCoords( a) )
+ // semantic as in <texture texcoord=...>
+ // input_semantic as in <input semantic=...>
+ // input_set as in <input set=...>
+ mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << a << "\" input_semantic=\"TEXCOORD\" input_set=\"" << a << "\"/>" << endstr;
+ }
+ PopTag();
+ mOutput << startstr << "</instance_material>" << endstr;
+ PopTag();
+ mOutput << startstr << "</technique_common>" << endstr;
+ PopTag();
+ mOutput << startstr << "</bind_material>" << endstr;
+ PopTag();
+ mOutput << startstr << "</instance_geometry>" << endstr;
+ }
+
+ // recurse into subnodes
+ for( size_t a = 0; a < pNode->mNumChildren; ++a )
+ WriteNode( pScene, pNode->mChildren[a]);
+
+ PopTag();
+ mOutput << startstr << "</node>" << endstr;
}
#endif
#endif
-
diff --git a/src/3rdparty/assimp/code/ColladaExporter.h b/src/3rdparty/assimp/code/ColladaExporter.h
index acd1bad4c..5e73628eb 100644
--- a/src/3rdparty/assimp/code/ColladaExporter.h
+++ b/src/3rdparty/assimp/code/ColladaExporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,13 +44,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_COLLADAEXPORTER_H_INC
#define AI_COLLADAEXPORTER_H_INC
-#include "../include/assimp/ai_assert.h"
+#include <assimp/ai_assert.h>
+#include <assimp/material.h>
+#include <assimp/mesh.h>
+#include <assimp/light.h>
+#include <assimp/Exporter.hpp>
#include <sstream>
+#include <vector>
+#include <map>
struct aiScene;
struct aiNode;
-namespace Assimp
+namespace Assimp
{
/// Helper class to export a given scene to a Collada file. Just for my personal
@@ -58,97 +64,116 @@ namespace Assimp
class ColladaExporter
{
public:
- /// Constructor for a specific scene to export
- ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
+ /// Constructor for a specific scene to export
+ ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
- /// Destructor
- virtual ~ColladaExporter();
+ /// Destructor
+ virtual ~ColladaExporter();
protected:
- /// Starts writing the contents
- void WriteFile();
+ /// Starts writing the contents
+ void WriteFile();
- /// Writes the asset header
- void WriteHeader();
+ /// Writes the asset header
+ void WriteHeader();
- /// Writes the embedded textures
- void WriteTextures();
+ /// Writes the embedded textures
+ void WriteTextures();
- /// Writes the material setup
- void WriteMaterials();
+ /// Writes the material setup
+ void WriteMaterials();
- /// Writes the geometry library
- void WriteGeometryLibrary();
+ /// Writes the cameras library
+ void WriteCamerasLibrary();
- /// Writes the given mesh
- void WriteGeometry( size_t pIndex);
+ // Write a camera entry
+ void WriteCamera(size_t pIndex);
- enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
+ /// Writes the cameras library
+ void WriteLightsLibrary();
- /// Writes a float array of the given type
- void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
+ // Write a camera entry
+ void WriteLight(size_t pIndex);
+ void WritePointLight(const aiLight *const light);
+ void WriteDirectionalLight(const aiLight *const light);
+ void WriteSpotLight(const aiLight *const light);
+ void WriteAmbienttLight(const aiLight *const light);
- /// Writes the scene library
- void WriteSceneLibrary();
+ /// Writes the geometry library
+ void WriteGeometryLibrary();
- /// Recursively writes the given node
- void WriteNode( const aiNode* pNode);
+ /// Writes the given mesh
+ void WriteGeometry( size_t pIndex);
- /// Enters a new xml element, which increases the indentation
- void PushTag() { startstr.append( " "); }
- /// Leaves an element, decreasing the indentation
- void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
+ enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
- /// Creates a mesh ID for the given mesh
- std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast<std::string> (pIndex); }
+ /// Writes a float array of the given type
+ void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
+
+ /// Writes the scene library
+ void WriteSceneLibrary();
+
+ /// Recursively writes the given node
+ void WriteNode( const aiScene* scene, aiNode* pNode);
+
+ /// Enters a new xml element, which increases the indentation
+ void PushTag() { startstr.append( " "); }
+ /// Leaves an element, decreasing the indentation
+ void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
+
+ /// Creates a mesh ID for the given mesh
+ std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + std::to_string(pIndex); }
public:
- /// Stringstream to write all output into
- std::stringstream mOutput;
+ /// Stringstream to write all output into
+ std::stringstream mOutput;
protected:
- /// The IOSystem for output
- IOSystem* mIOSystem;
+ /// The IOSystem for output
+ IOSystem* mIOSystem;
- /// Path of the directory where the scene will be exported
- const std::string mPath;
+ /// Path of the directory where the scene will be exported
+ const std::string mPath;
- /// Name of the file (without extension) where the scene will be exported
- const std::string mFile;
+ /// Name of the file (without extension) where the scene will be exported
+ const std::string mFile;
- /// The scene to be written
- const aiScene* mScene;
- bool mSceneOwned;
+ /// The scene to be written
+ const aiScene* mScene;
+ bool mSceneOwned;
- /// current line start string, contains the current indentation for simple stream insertion
- std::string startstr;
- /// current line end string for simple stream insertion
- std::string endstr;
+ /// current line start string, contains the current indentation for simple stream insertion
+ std::string startstr;
+ /// current line end string for simple stream insertion
+ std::string endstr;
// pair of color and texture - texture precedences color
- struct Surface
- {
+ struct Surface
+ {
bool exist;
- aiColor4D color;
- std::string texture;
- size_t channel;
+ aiColor4D color;
+ std::string texture;
+ size_t channel;
Surface() { exist = false; channel = 0; }
};
struct Property
{
bool exist;
- float value;
- Property() { exist = false; }
+ float value;
+ Property()
+ : exist(false)
+ , value(0.0f)
+ {}
};
- // summarize a material in an convinient way.
+ // summarize a material in an convinient way.
struct Material
{
std::string name;
std::string shading_model;
Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
- Property shininess, transparency, index_refraction;
+ Property shininess, transparency, index_refraction;
Material() {}
};
diff --git a/src/3rdparty/assimp/code/ColladaHelper.h b/src/3rdparty/assimp/code/ColladaHelper.h
index 2f05d46a7..130363186 100644
--- a/src/3rdparty/assimp/code/ColladaHelper.h
+++ b/src/3rdparty/assimp/code/ColladaHelper.h
@@ -4,11 +4,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,40 +43,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_COLLADAHELPER_H_INC
#define AI_COLLADAHELPER_H_INC
-namespace Assimp {
-namespace Collada {
+#include <string>
+#include <map>
+#include <vector>
+#include <stdint.h>
+#include <assimp/light.h>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+
+struct aiMaterial;
+
+namespace Assimp {
+namespace Collada {
/** Collada file versions which evolved during the years ... */
enum FormatVersion
{
- FV_1_5_n,
- FV_1_4_n,
- FV_1_3_n
+ FV_1_5_n,
+ FV_1_4_n,
+ FV_1_3_n
};
/** Transformation types that can be applied to a node */
enum TransformType
{
- TF_LOOKAT,
- TF_ROTATE,
- TF_TRANSLATE,
- TF_SCALE,
- TF_SKEW,
- TF_MATRIX
+ TF_LOOKAT,
+ TF_ROTATE,
+ TF_TRANSLATE,
+ TF_SCALE,
+ TF_SKEW,
+ TF_MATRIX
};
/** Different types of input data to a vertex or face */
enum InputType
{
- IT_Invalid,
- IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
- IT_Position,
- IT_Normal,
- IT_Texcoord,
- IT_Color,
- IT_Tangent,
- IT_Bitangent
+ IT_Invalid,
+ IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
+ IT_Position,
+ IT_Normal,
+ IT_Texcoord,
+ IT_Color,
+ IT_Tangent,
+ IT_Bitangent
};
/** Supported controller types */
@@ -96,110 +106,111 @@ enum MorphMethod
/** Contains all data for one of the different transformation types */
struct Transform
{
- std::string mID; ///< SID of the transform step, by which anim channels address their target node
- TransformType mType;
- float f[16]; ///< Interpretation of data depends on the type of the transformation
+ std::string mID; ///< SID of the transform step, by which anim channels address their target node
+ TransformType mType;
+ float f[16]; ///< Interpretation of data depends on the type of the transformation
};
/** A collada camera. */
struct Camera
{
- Camera()
- : mOrtho (false)
- , mHorFov (10e10f)
- , mVerFov (10e10f)
- , mAspect (10e10f)
- , mZNear (0.1f)
- , mZFar (1000.f)
- {}
+ Camera()
+ : mOrtho (false)
+ , mHorFov (10e10f)
+ , mVerFov (10e10f)
+ , mAspect (10e10f)
+ , mZNear (0.1f)
+ , mZFar (1000.f)
+ {}
- // Name of camera
- std::string mName;
+ // Name of camera
+ std::string mName;
- // True if it is an orthografic camera
- bool mOrtho;
+ // True if it is an orthografic camera
+ bool mOrtho;
- //! Horizontal field of view in degrees
- float mHorFov;
+ //! Horizontal field of view in degrees
+ float mHorFov;
- //! Vertical field of view in degrees
- float mVerFov;
+ //! Vertical field of view in degrees
+ float mVerFov;
- //! Screen aspect
- float mAspect;
+ //! Screen aspect
+ float mAspect;
- //! Near& far z
- float mZNear, mZFar;
+ //! Near& far z
+ float mZNear, mZFar;
};
-#define aiLightSource_AMBIENT 0xdeaddead
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
/** A collada light source. */
struct Light
-{
- Light()
- : mAttConstant (1.f)
- , mAttLinear (0.f)
- , mAttQuadratic (0.f)
- , mFalloffAngle (180.f)
- , mFalloffExponent (0.f)
- , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
- , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
- , mIntensity (1.f)
- {}
+{
+ Light()
+ : mType (aiLightSource_UNDEFINED)
+ , mAttConstant (1.f)
+ , mAttLinear (0.f)
+ , mAttQuadratic (0.f)
+ , mFalloffAngle (180.f)
+ , mFalloffExponent (0.f)
+ , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
+ , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
+ , mIntensity (1.f)
+ {}
- //! Type of the light source aiLightSourceType + ambient
- unsigned int mType;
+ //! Type of the light source aiLightSourceType + ambient
+ unsigned int mType;
- //! Color of the light
- aiColor3D mColor;
+ //! Color of the light
+ aiColor3D mColor;
- //! Light attenuation
- float mAttConstant,mAttLinear,mAttQuadratic;
+ //! Light attenuation
+ float mAttConstant,mAttLinear,mAttQuadratic;
- //! Spot light falloff
- float mFalloffAngle;
- float mFalloffExponent;
+ //! Spot light falloff
+ float mFalloffAngle;
+ float mFalloffExponent;
- // -----------------------------------------------------
- // FCOLLADA extension from here
+ // -----------------------------------------------------
+ // FCOLLADA extension from here
- //! ... related stuff from maja and max extensions
- float mPenumbraAngle;
- float mOuterAngle;
+ //! ... related stuff from maja and max extensions
+ float mPenumbraAngle;
+ float mOuterAngle;
- //! Common light intensity
- float mIntensity;
+ //! Common light intensity
+ float mIntensity;
};
/** Short vertex index description */
struct InputSemanticMapEntry
{
- InputSemanticMapEntry()
- : mSet (0)
- {}
+ InputSemanticMapEntry()
+ : mSet(0)
+ , mType(IT_Invalid)
+ {}
- //! Index of set, optional
- unsigned int mSet;
+ //! Index of set, optional
+ unsigned int mSet;
- //! Name of referenced vertex input
- InputType mType;
+ //! Type of referenced vertex input
+ InputType mType;
};
/** Table to map from effect to vertex input semantics */
struct SemanticMappingTable
{
- //! Name of material
- std::string mMatName;
+ //! Name of material
+ std::string mMatName;
- //! List of semantic map commands, grouped by effect semantic name
- std::map<std::string, InputSemanticMapEntry> mMap;
+ //! List of semantic map commands, grouped by effect semantic name
+ std::map<std::string, InputSemanticMapEntry> mMap;
- //! For std::find
- bool operator == (const std::string& s) const {
- return s == mMatName;
- }
+ //! For std::find
+ bool operator == (const std::string& s) const {
+ return s == mMatName;
+ }
};
/** A reference to a mesh inside a node, including materials assigned to the various subgroups.
@@ -207,177 +218,177 @@ struct SemanticMappingTable
*/
struct MeshInstance
{
- ///< ID of the mesh or controller to be instanced
- std::string mMeshOrController;
+ ///< ID of the mesh or controller to be instanced
+ std::string mMeshOrController;
- ///< Map of materials by the subgroup ID they're applied to
- std::map<std::string, SemanticMappingTable> mMaterials;
+ ///< Map of materials by the subgroup ID they're applied to
+ std::map<std::string, SemanticMappingTable> mMaterials;
};
/** A reference to a camera inside a node*/
struct CameraInstance
{
- ///< ID of the camera
- std::string mCamera;
+ ///< ID of the camera
+ std::string mCamera;
};
/** A reference to a light inside a node*/
struct LightInstance
{
- ///< ID of the camera
- std::string mLight;
+ ///< ID of the camera
+ std::string mLight;
};
/** A reference to a node inside a node*/
struct NodeInstance
{
- ///< ID of the node
- std::string mNode;
+ ///< ID of the node
+ std::string mNode;
};
/** A node in a scene hierarchy */
struct Node
{
- std::string mName;
- std::string mID;
- std::string mSID;
- Node* mParent;
- std::vector<Node*> mChildren;
+ std::string mName;
+ std::string mID;
+ std::string mSID;
+ Node* mParent;
+ std::vector<Node*> mChildren;
- /** Operations in order to calculate the resulting transformation to parent. */
- std::vector<Transform> mTransforms;
+ /** Operations in order to calculate the resulting transformation to parent. */
+ std::vector<Transform> mTransforms;
- /** Meshes at this node */
- std::vector<MeshInstance> mMeshes;
+ /** Meshes at this node */
+ std::vector<MeshInstance> mMeshes;
- /** Lights at this node */
- std::vector<LightInstance> mLights;
+ /** Lights at this node */
+ std::vector<LightInstance> mLights;
- /** Cameras at this node */
- std::vector<CameraInstance> mCameras;
+ /** Cameras at this node */
+ std::vector<CameraInstance> mCameras;
- /** Node instances at this node */
- std::vector<NodeInstance> mNodeInstances;
+ /** Node instances at this node */
+ std::vector<NodeInstance> mNodeInstances;
- /** Rootnodes: Name of primary camera, if any */
- std::string mPrimaryCamera;
+ /** Rootnodes: Name of primary camera, if any */
+ std::string mPrimaryCamera;
- //! Constructor. Begin with a zero parent
- Node() {
- mParent = NULL;
- }
+ //! Constructor. Begin with a zero parent
+ Node() {
+ mParent = NULL;
+ }
- //! Destructor: delete all children subsequently
- ~Node() {
- for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
- delete *it;
- }
+ //! Destructor: delete all children subsequently
+ ~Node() {
+ for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
+ delete *it;
+ }
};
/** Data source array: either floats or strings */
struct Data
{
- bool mIsStringArray;
- std::vector<float> mValues;
- std::vector<std::string> mStrings;
+ bool mIsStringArray;
+ std::vector<float> mValues;
+ std::vector<std::string> mStrings;
};
/** Accessor to a data array */
struct Accessor
{
- size_t mCount; // in number of objects
- size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
- size_t mOffset; // in number of values
- size_t mStride; // Stride in number of values
- std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
- size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
- // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
- std::string mSource; // URL of the source array
- mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
-
- Accessor()
- {
- mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL;
- mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
- }
+ size_t mCount; // in number of objects
+ size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
+ size_t mOffset; // in number of values
+ size_t mStride; // Stride in number of values
+ std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
+ size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
+ // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
+ std::string mSource; // URL of the source array
+ mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
+
+ Accessor()
+ {
+ mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL;
+ mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
+ }
};
/** A single face in a mesh */
struct Face
{
- std::vector<size_t> mIndices;
+ std::vector<size_t> mIndices;
};
/** An input channel for mesh data, referring to a single accessor */
struct InputChannel
{
- InputType mType; // Type of the data
- size_t mIndex; // Optional index, if multiple sets of the same data type are given
- size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
- std::string mAccessor; // ID of the accessor where to read the actual values from.
- mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
+ InputType mType; // Type of the data
+ size_t mIndex; // Optional index, if multiple sets of the same data type are given
+ size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
+ std::string mAccessor; // ID of the accessor where to read the actual values from.
+ mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
- InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
+ InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
};
/** Subset of a mesh with a certain material */
struct SubMesh
{
- std::string mMaterial; ///< subgroup identifier
- size_t mNumFaces; ///< number of faces in this submesh
+ std::string mMaterial; ///< subgroup identifier
+ size_t mNumFaces; ///< number of faces in this submesh
};
/** Contains data for a single mesh */
struct Mesh
{
- Mesh()
- {
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
- mNumUVComponents[i] = 2;
- }
-
+ Mesh()
+ {
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ mNumUVComponents[i] = 2;
+ }
+
std::string mName;
- // just to check if there's some sophisticated addressing involved...
- // which we don't support, and therefore should warn about.
- std::string mVertexID;
+ // just to check if there's some sophisticated addressing involved...
+ // which we don't support, and therefore should warn about.
+ std::string mVertexID;
+
+ // Vertex data addressed by vertex indices
+ std::vector<InputChannel> mPerVertexData;
- // Vertex data addressed by vertex indices
- std::vector<InputChannel> mPerVertexData;
+ // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
+ std::vector<aiVector3D> mPositions;
+ std::vector<aiVector3D> mNormals;
+ std::vector<aiVector3D> mTangents;
+ std::vector<aiVector3D> mBitangents;
+ std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
- // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
- std::vector<aiVector3D> mPositions;
- std::vector<aiVector3D> mNormals;
- std::vector<aiVector3D> mTangents;
- std::vector<aiVector3D> mBitangents;
- std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ // Faces. Stored are only the number of vertices for each face.
+ // 1 == point, 2 == line, 3 == triangle, 4+ == poly
+ std::vector<size_t> mFaceSize;
- // Faces. Stored are only the number of vertices for each face.
- // 1 == point, 2 == line, 3 == triangle, 4+ == poly
- std::vector<size_t> mFaceSize;
-
- // Position indices for all faces in the sequence given in mFaceSize -
- // necessary for bone weight assignment
- std::vector<size_t> mFacePosIndices;
+ // Position indices for all faces in the sequence given in mFaceSize -
+ // necessary for bone weight assignment
+ std::vector<size_t> mFacePosIndices;
- // Submeshes in this mesh, each with a given material
- std::vector<SubMesh> mSubMeshes;
+ // Submeshes in this mesh, each with a given material
+ std::vector<SubMesh> mSubMeshes;
};
/** Which type of primitives the ReadPrimitives() function is going to read */
enum PrimitiveType
{
- Prim_Invalid,
- Prim_Lines,
- Prim_LineStrip,
- Prim_Triangles,
- Prim_TriStrips,
- Prim_TriFans,
- Prim_Polylist,
- Prim_Polygon
+ Prim_Invalid,
+ Prim_Lines,
+ Prim_LineStrip,
+ Prim_Triangles,
+ Prim_TriStrips,
+ Prim_TriFans,
+ Prim_Polylist,
+ Prim_Polygon
};
/** A skeleton or morph controller to deform a mesh with the use of joints or morph targets */
@@ -390,24 +401,24 @@ struct Controller
MorphMethod mMethod;
// the URL of the mesh deformed by the controller.
- std::string mMeshId;
+ std::string mMeshId;
- // accessor URL of the joint names
- std::string mJointNameSource;
+ // accessor URL of the joint names
+ std::string mJointNameSource;
///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases
float mBindShapeMatrix[16];
- // accessor URL of the joint inverse bind matrices
- std::string mJointOffsetMatrixSource;
+ // accessor URL of the joint inverse bind matrices
+ std::string mJointOffsetMatrixSource;
- // input channel: joint names.
- InputChannel mWeightInputJoints;
- // input channel: joint weights
- InputChannel mWeightInputWeights;
+ // input channel: joint names.
+ InputChannel mWeightInputJoints;
+ // input channel: joint weights
+ InputChannel mWeightInputWeights;
- // Number of weights per vertex.
- std::vector<size_t> mWeightCounts;
+ // Number of weights per vertex.
+ std::vector<size_t> mWeightCounts;
// JointIndex-WeightIndex pairs for all vertices
std::vector< std::pair<size_t, size_t> > mWeights;
@@ -419,162 +430,169 @@ struct Controller
/** A collada material. Pretty much the only member is a reference to an effect. */
struct Material
{
- std::string mEffect;
+ std::string mName;
+ std::string mEffect;
};
/** Type of the effect param */
enum ParamType
{
- Param_Sampler,
- Param_Surface
+ Param_Sampler,
+ Param_Surface
};
/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
struct EffectParam
{
- ParamType mType;
- std::string mReference; // to which other thing the param is referring to.
+ ParamType mType;
+ std::string mReference; // to which other thing the param is referring to.
};
/** Shading type supported by the standard effect spec of Collada */
enum ShadeType
{
- Shade_Invalid,
- Shade_Constant,
- Shade_Lambert,
- Shade_Phong,
- Shade_Blinn
+ Shade_Invalid,
+ Shade_Constant,
+ Shade_Lambert,
+ Shade_Phong,
+ Shade_Blinn
};
/** Represents a texture sampler in collada */
struct Sampler
{
- Sampler()
- : mWrapU (true)
- , mWrapV (true)
- , mMirrorU ()
- , mMirrorV ()
- , mOp (aiTextureOp_Multiply)
- , mUVId (UINT_MAX)
- , mWeighting (1.f)
- , mMixWithPrevious (1.f)
- {}
-
- /** Name of image reference
- */
- std::string mName;
+ Sampler()
+ : mWrapU (true)
+ , mWrapV (true)
+ , mMirrorU ()
+ , mMirrorV ()
+ , mOp (aiTextureOp_Multiply)
+ , mUVId (UINT_MAX)
+ , mWeighting (1.f)
+ , mMixWithPrevious (1.f)
+ {}
+
+ /** Name of image reference
+ */
+ std::string mName;
- /** Wrap U?
- */
- bool mWrapU;
+ /** Wrap U?
+ */
+ bool mWrapU;
- /** Wrap V?
- */
- bool mWrapV;
+ /** Wrap V?
+ */
+ bool mWrapV;
- /** Mirror U?
- */
- bool mMirrorU;
+ /** Mirror U?
+ */
+ bool mMirrorU;
- /** Mirror V?
- */
- bool mMirrorV;
+ /** Mirror V?
+ */
+ bool mMirrorV;
- /** Blend mode
- */
- aiTextureOp mOp;
+ /** Blend mode
+ */
+ aiTextureOp mOp;
- /** UV transformation
- */
- aiUVTransform mTransform;
+ /** UV transformation
+ */
+ aiUVTransform mTransform;
- /** Name of source UV channel
- */
- std::string mUVChannel;
+ /** Name of source UV channel
+ */
+ std::string mUVChannel;
- /** Resolved UV channel index or UINT_MAX if not known
- */
- unsigned int mUVId;
+ /** Resolved UV channel index or UINT_MAX if not known
+ */
+ unsigned int mUVId;
- // OKINO/MAX3D extensions from here
- // -------------------------------------------------------
+ // OKINO/MAX3D extensions from here
+ // -------------------------------------------------------
- /** Weighting factor
- */
- float mWeighting;
+ /** Weighting factor
+ */
+ float mWeighting;
- /** Mixing factor from OKINO
- */
- float mMixWithPrevious;
+ /** Mixing factor from OKINO
+ */
+ float mMixWithPrevious;
};
/** A collada effect. Can contain about anything according to the Collada spec,
but we limit our version to a reasonable subset. */
struct Effect
{
- // Shading mode
- ShadeType mShadeType;
-
- // Colors
- aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
- mTransparent, mReflective;
-
- // Textures
- Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
- mTexTransparent, mTexBump, mTexReflective;
-
- // Scalar factory
- float mShininess, mRefractIndex, mReflectivity;
- float mTransparency;
-
- // local params referring to each other by their SID
- typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
- ParamLibrary mParams;
-
- // MAX3D extensions
- // ---------------------------------------------------------
- // Double-sided?
- bool mDoubleSided, mWireframe, mFaceted;
-
- Effect()
- : mShadeType (Shade_Phong)
- , mEmissive ( 0, 0, 0, 1)
- , mAmbient ( 0.1f, 0.1f, 0.1f, 1)
- , mDiffuse ( 0.6f, 0.6f, 0.6f, 1)
- , mSpecular ( 0.4f, 0.4f, 0.4f, 1)
- , mTransparent ( 0, 0, 0, 1)
- , mShininess (10.0f)
- , mRefractIndex (1.f)
- , mReflectivity (1.f)
- , mTransparency (0.f)
- , mDoubleSided (false)
- , mWireframe (false)
- , mFaceted (false)
- {
- }
+ // Shading mode
+ ShadeType mShadeType;
+
+ // Colors
+ aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
+ mTransparent, mReflective;
+
+ // Textures
+ Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
+ mTexTransparent, mTexBump, mTexReflective;
+
+ // Scalar factory
+ float mShininess, mRefractIndex, mReflectivity;
+ float mTransparency;
+ bool mHasTransparency;
+ bool mRGBTransparency;
+ bool mInvertTransparency;
+
+ // local params referring to each other by their SID
+ typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
+ ParamLibrary mParams;
+
+ // MAX3D extensions
+ // ---------------------------------------------------------
+ // Double-sided?
+ bool mDoubleSided, mWireframe, mFaceted;
+
+ Effect()
+ : mShadeType (Shade_Phong)
+ , mEmissive ( 0, 0, 0, 1)
+ , mAmbient ( 0.1f, 0.1f, 0.1f, 1)
+ , mDiffuse ( 0.6f, 0.6f, 0.6f, 1)
+ , mSpecular ( 0.4f, 0.4f, 0.4f, 1)
+ , mTransparent ( 0, 0, 0, 1)
+ , mShininess (10.0f)
+ , mRefractIndex (1.f)
+ , mReflectivity (0.f)
+ , mTransparency (1.f)
+ , mHasTransparency (false)
+ , mRGBTransparency(false)
+ , mInvertTransparency(false)
+ , mDoubleSided (false)
+ , mWireframe (false)
+ , mFaceted (false)
+ {
+ }
};
/** An image, meaning texture */
struct Image
{
- std::string mFileName;
+ std::string mFileName;
- /** If image file name is zero, embedded image data
- */
- std::vector<uint8_t> mImageData;
+ /** If image file name is zero, embedded image data
+ */
+ std::vector<uint8_t> mImageData;
- /** If image file name is zero, file format of
- * embedded image data.
- */
- std::string mEmbeddedFormat;
+ /** If image file name is zero, file format of
+ * embedded image data.
+ */
+ std::string mEmbeddedFormat;
};
/** An animation channel. */
struct AnimationChannel
{
- /** URL of the data to animate. Could be about anything, but we support only the
- * "NodeID/TransformID.SubElement" notation
+ /** URL of the data to animate. Could be about anything, but we support only the
+ * "NodeID/TransformID.SubElement" notation
*/
std::string mTarget;
@@ -582,42 +600,84 @@ struct AnimationChannel
std::string mSourceTimes;
/** Source URL of the value values. Collada calls them "output". */
std::string mSourceValues;
- /** Source URL of the IN_TANGENT semantic values. */
- std::string mInTanValues;
- /** Source URL of the OUT_TANGENT semantic values. */
- std::string mOutTanValues;
- /** Source URL of the INTERPOLATION semantic values. */
- std::string mInterpolationValues;
+ /** Source URL of the IN_TANGENT semantic values. */
+ std::string mInTanValues;
+ /** Source URL of the OUT_TANGENT semantic values. */
+ std::string mOutTanValues;
+ /** Source URL of the INTERPOLATION semantic values. */
+ std::string mInterpolationValues;
};
/** An animation. Container for 0-x animation channels or 0-x animations */
struct Animation
{
- /** Anim name */
- std::string mName;
+ /** Anim name */
+ std::string mName;
+
+ /** the animation channels, if any */
+ std::vector<AnimationChannel> mChannels;
+
+ /** the sub-animations, if any */
+ std::vector<Animation*> mSubAnims;
- /** the animation channels, if any */
- std::vector<AnimationChannel> mChannels;
+ /** Destructor */
+ ~Animation()
+ {
+ for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
+ delete *it;
+ }
- /** the sub-animations, if any */
- std::vector<Animation*> mSubAnims;
+ /** Collect all channels in the animation hierarchy into a single channel list. */
+ void CollectChannelsRecursively(std::vector<AnimationChannel> &channels)
+ {
+ channels.insert(channels.end(), mChannels.begin(), mChannels.end());
+
+ for (std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
+ {
+ Animation *pAnim = (*it);
+
+ pAnim->CollectChannelsRecursively(channels);
+ }
+ }
- /** Destructor */
- ~Animation()
+ /** Combine all single-channel animations' channel into the same (parent) animation channel list. */
+ void CombineSingleChannelAnimations()
{
- for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
- delete *it;
+ CombineSingleChannelAnimationsRecursively(this);
+ }
+
+ void CombineSingleChannelAnimationsRecursively(Animation *pParent)
+ {
+ for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();)
+ {
+ Animation *anim = *it;
+
+ CombineSingleChannelAnimationsRecursively(anim);
+
+ if (anim->mChannels.size() == 1)
+ {
+ pParent->mChannels.push_back(anim->mChannels[0]);
+
+ it = pParent->mSubAnims.erase(it);
+
+ delete anim;
+ }
+ else
+ {
+ ++it;
+ }
+ }
}
};
/** Description of a collada animation channel which has been determined to affect the current node */
struct ChannelEntry
{
- const Collada::AnimationChannel* mChannel; ///> the source channel
+ const Collada::AnimationChannel* mChannel; ///> the source channel
std::string mTargetId;
- std::string mTransformId; // the ID of the transformation step of the node which is influenced
- size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
- size_t mSubElement; // starting index inside the transform data
+ std::string mTransformId; // the ID of the transformation step of the node which is influenced
+ size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
+ size_t mSubElement; // starting index inside the transform data
// resolved data references
const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
diff --git a/src/3rdparty/assimp/code/ColladaLoader.cpp b/src/3rdparty/assimp/code/ColladaLoader.cpp
index c8b9c10f2..50d5116a6 100644
--- a/src/3rdparty/assimp/code/ColladaLoader.cpp
+++ b/src/3rdparty/assimp/code/ColladaLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,27 +25,30 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the Collada loader */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
-#include "../include/assimp/anim.h"
#include "ColladaLoader.h"
+#include <assimp/anim.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
#include "ColladaParser.h"
#include "fast_atof.h"
@@ -54,27 +57,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "CreateAnimMesh.h"
#include "time.h"
+#include "math.h"
+#include <numeric>
+#include "Defines.h"
+
using namespace Assimp;
+using namespace Assimp::Formatter;
static const aiImporterDesc desc = {
- "Collada Importer",
- "",
- "",
- "http://collada.org",
- aiImporterFlags_SupportTextFlavour,
- 1,
- 3,
- 1,
- 5,
- "dae"
+ "Collada Importer",
+ "",
+ "",
+ "http://collada.org",
+ aiImporterFlags_SupportTextFlavour,
+ 1,
+ 3,
+ 1,
+ 5,
+ "dae"
};
-
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader()
-: noSkeletonMesh(), ignoreUpDirection(false)
+ : mFileName()
+ , mMeshIndexByID()
+ , mMaterialIndexByName()
+ , mMeshes()
+ , newMats()
+ , mCameras()
+ , mLights()
+ , mTextures()
+ , mAnims()
+ , noSkeletonMesh( false )
+ , ignoreUpDirection(false)
+ , mNodeNameCounter( 0 )
{}
// ------------------------------------------------------------------------------------------------
@@ -83,33 +101,33 @@ ColladaLoader::~ColladaLoader()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- // check file extension
- std::string extension = GetExtension(pFile);
-
- if( extension == "dae")
- return true;
-
- // XML - too generic, we need to open the file and search for typical keywords
- if( extension == "xml" || !extension.length() || checkSig) {
- /* If CanRead() is called in order to check whether we
- * support a specific file extension in general pIOHandler
- * might be NULL and it's our duty to return true here.
- */
- if (!pIOHandler)return true;
- const char* tokens[] = {"collada"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ std::string extension = GetExtension(pFile);
+
+ if( extension == "dae")
+ return true;
+
+ // XML - too generic, we need to open the file and search for typical keywords
+ if( extension == "xml" || !extension.length() || checkSig) {
+ /* If CanRead() is called in order to check whether we
+ * support a specific file extension in general pIOHandler
+ * might be NULL and it's our duty to return true here.
+ */
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"collada"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer* pImp)
{
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
- ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
}
@@ -117,14 +135,14 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
// Get file extension list
const aiImporterDesc* ColladaLoader::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
+// Imports the given file into the given scene structure.
void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- mFileName = pFile;
+ mFileName = pFile;
// clean all member arrays - just for safety, it should work even if we did not
mMeshIndexByID.clear();
@@ -137,408 +155,411 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
mTextures.clear();
mAnims.clear();
- // parse the input file
- ColladaParser parser( pIOHandler, pFile);
+ // parse the input file
+ ColladaParser parser( pIOHandler, pFile);
- if( !parser.mRootNode)
- throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
+ if( !parser.mRootNode)
+ throw DeadlyImportError( "Collada: File came out empty. Something is wrong here.");
- // reserve some storage to avoid unnecessary reallocs
- newMats.reserve(parser.mMaterialLibrary.size()*2);
- mMeshes.reserve(parser.mMeshLibrary.size()*2);
+ // reserve some storage to avoid unnecessary reallocs
+ newMats.reserve(parser.mMaterialLibrary.size()*2);
+ mMeshes.reserve(parser.mMeshLibrary.size()*2);
- mCameras.reserve(parser.mCameraLibrary.size());
- mLights.reserve(parser.mLightLibrary.size());
+ mCameras.reserve(parser.mCameraLibrary.size());
+ mLights.reserve(parser.mLightLibrary.size());
- // create the materials first, for the meshes to find
- BuildMaterials( parser, pScene);
+ // create the materials first, for the meshes to find
+ BuildMaterials( parser, pScene);
- // build the node hierarchy from it
- pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
+ // build the node hierarchy from it
+ pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
- // ... then fill the materials with the now adjusted settings
- FillMaterials(parser, pScene);
+ // ... then fill the materials with the now adjusted settings
+ FillMaterials(parser, pScene);
// Apply unitsize scale calculation
- pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
+ pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
0, parser.mUnitSize, 0, 0,
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
if( !ignoreUpDirection ) {
// Convert to Y_UP, if different orientation
- if( parser.mUpDirection == ColladaParser::UP_X)
- pScene->mRootNode->mTransformation *= aiMatrix4x4(
- 0, -1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
- else if( parser.mUpDirection == ColladaParser::UP_Z)
- pScene->mRootNode->mTransformation *= aiMatrix4x4(
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, -1, 0, 0,
- 0, 0, 0, 1);
+ if( parser.mUpDirection == ColladaParser::UP_X)
+ pScene->mRootNode->mTransformation *= aiMatrix4x4(
+ 0, -1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+ else if( parser.mUpDirection == ColladaParser::UP_Z)
+ pScene->mRootNode->mTransformation *= aiMatrix4x4(
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, -1, 0, 0,
+ 0, 0, 0, 1);
}
- // store all meshes
- StoreSceneMeshes( pScene);
+ // store all meshes
+ StoreSceneMeshes( pScene);
- // store all materials
- StoreSceneMaterials( pScene);
+ // store all materials
+ StoreSceneMaterials( pScene);
- // store all lights
- StoreSceneLights( pScene);
+ // store all lights
+ StoreSceneLights( pScene);
- // store all cameras
- StoreSceneCameras( pScene);
+ // store all cameras
+ StoreSceneCameras( pScene);
- // store all animations
- StoreAnimations( pScene, parser);
+ // store all animations
+ StoreAnimations( pScene, parser);
- // If no meshes have been loaded, it's probably just an animated skeleton.
- if (!pScene->mNumMeshes) {
-
- if (!noSkeletonMesh) {
- SkeletonMeshBuilder hero(pScene);
- }
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- }
+ // If no meshes have been loaded, it's probably just an animated skeleton.
+ if (!pScene->mNumMeshes) {
+
+ if (!noSkeletonMesh) {
+ SkeletonMeshBuilder hero(pScene);
+ }
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
}
// ------------------------------------------------------------------------------------------------
// Recursively constructs a scene node for the given parser node and returns it.
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode)
{
- // create a node for it
- aiNode* node = new aiNode();
+ // create a node for it
+ aiNode* node = new aiNode();
- // find a name for the new node. It's more complicated than you might think
- node->mName.Set( FindNameForNode( pNode));
+ // find a name for the new node. It's more complicated than you might think
+ node->mName.Set( FindNameForNode( pNode));
- // calculate the transformation matrix for it
- node->mTransformation = pParser.CalculateResultTransform( pNode->mTransforms);
+ // calculate the transformation matrix for it
+ node->mTransformation = pParser.CalculateResultTransform( pNode->mTransforms);
- // now resolve node instances
- std::vector<const Collada::Node*> instances;
- ResolveNodeInstances(pParser,pNode,instances);
+ // now resolve node instances
+ std::vector<const Collada::Node*> instances;
+ ResolveNodeInstances(pParser,pNode,instances);
- // add children. first the *real* ones
- node->mNumChildren = pNode->mChildren.size()+instances.size();
- node->mChildren = new aiNode*[node->mNumChildren];
+ // add children. first the *real* ones
+ node->mNumChildren = pNode->mChildren.size()+instances.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
- for( size_t a = 0; a < pNode->mChildren.size(); a++)
- {
- node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
- node->mChildren[a]->mParent = node;
- }
+ for( size_t a = 0; a < pNode->mChildren.size(); a++)
+ {
+ node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
+ node->mChildren[a]->mParent = node;
+ }
- // ... and finally the resolved node instances
- for( size_t a = 0; a < instances.size(); a++)
- {
- node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
- node->mChildren[pNode->mChildren.size() + a]->mParent = node;
- }
+ // ... and finally the resolved node instances
+ for( size_t a = 0; a < instances.size(); a++)
+ {
+ node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
+ node->mChildren[pNode->mChildren.size() + a]->mParent = node;
+ }
- // construct meshes
- BuildMeshesForNode( pParser, pNode, node);
+ // construct meshes
+ BuildMeshesForNode( pParser, pNode, node);
- // construct cameras
- BuildCamerasForNode(pParser, pNode, node);
+ // construct cameras
+ BuildCamerasForNode(pParser, pNode, node);
- // construct lights
- BuildLightsForNode(pParser, pNode, node);
- return node;
+ // construct lights
+ BuildLightsForNode(pParser, pNode, node);
+ return node;
}
// ------------------------------------------------------------------------------------------------
// Resolve node instances
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
- std::vector<const Collada::Node*>& resolved)
+ std::vector<const Collada::Node*>& resolved)
{
- // reserve enough storage
- resolved.reserve(pNode->mNodeInstances.size());
+ // reserve enough storage
+ resolved.reserve(pNode->mNodeInstances.size());
- // ... and iterate through all nodes to be instanced as children of pNode
- for (std::vector<Collada::NodeInstance>::const_iterator it = pNode->mNodeInstances.begin(),
- end = pNode->mNodeInstances.end(); it != end; ++it)
- {
- // find the corresponding node in the library
- const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find((*it).mNode);
- const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
-
- // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
- // need to check for both name and ID to catch all. To avoid breaking valid files,
- // the workaround is only enabled when the first attempt to resolve the node has failed.
- if (!nd) {
- nd = FindNode(pParser.mRootNode,(*it).mNode);
- }
- if (!nd)
- DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + (*it).mNode);
-
- else {
- // attach this node to the list of children
- resolved.push_back(nd);
- }
- }
+ // ... and iterate through all nodes to be instanced as children of pNode
+ for (const auto &nodeInst: pNode->mNodeInstances)
+ {
+ // find the corresponding node in the library
+ const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
+ const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
+
+ // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
+ // need to check for both name and ID to catch all. To avoid breaking valid files,
+ // the workaround is only enabled when the first attempt to resolve the node has failed.
+ if (!nd) {
+ nd = FindNode(pParser.mRootNode, nodeInst.mNode);
+ }
+ if (!nd)
+ DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + nodeInst.mNode);
+
+ else {
+ // attach this node to the list of children
+ resolved.push_back(nd);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
- const Collada::SemanticMappingTable& table)
+ const Collada::SemanticMappingTable& table)
{
- std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
- if (it != table.mMap.end()) {
- if (it->second.mType != Collada::IT_Texcoord)
- DefaultLogger::get()->error("Collada: Unexpected effect input mapping");
+ std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
+ if (it != table.mMap.end()) {
+ if (it->second.mType != Collada::IT_Texcoord)
+ DefaultLogger::get()->error("Collada: Unexpected effect input mapping");
- sampler.mUVId = it->second.mSet;
- }
+ sampler.mUVId = it->second.mSet;
+ }
}
// ------------------------------------------------------------------------------------------------
// Builds lights for the given node and references them
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
- BOOST_FOREACH( const Collada::LightInstance& lid, pNode->mLights)
- {
- // find the referred light
- ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
- if( srcLightIt == pParser.mLightLibrary.end())
- {
- DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping.");
- continue;
- }
- const Collada::Light* srcLight = &srcLightIt->second;
- if (srcLight->mType == aiLightSource_AMBIENT) {
- DefaultLogger::get()->error("Collada: Skipping ambient light for the moment");
- continue;
- }
-
- // now fill our ai data structure
- aiLight* out = new aiLight();
- out->mName = pTarget->mName;
- out->mType = (aiLightSourceType)srcLight->mType;
+ for( const Collada::LightInstance& lid : pNode->mLights)
+ {
+ // find the referred light
+ ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
+ if( srcLightIt == pParser.mLightLibrary.end())
+ {
+ DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping.");
+ continue;
+ }
+ const Collada::Light* srcLight = &srcLightIt->second;
- // collada lights point in -Z by default, rest is specified in node transform
- out->mDirection = aiVector3D(0.f,0.f,-1.f);
+ // now fill our ai data structure
+ aiLight* out = new aiLight();
+ out->mName = pTarget->mName;
+ out->mType = (aiLightSourceType)srcLight->mType;
- out->mAttenuationConstant = srcLight->mAttConstant;
- out->mAttenuationLinear = srcLight->mAttLinear;
- out->mAttenuationQuadratic = srcLight->mAttQuadratic;
+ // collada lights point in -Z by default, rest is specified in node transform
+ out->mDirection = aiVector3D(0.f,0.f,-1.f);
- // collada doesn't differenciate between these color types
- out->mColorDiffuse = out->mColorSpecular = out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
+ out->mAttenuationConstant = srcLight->mAttConstant;
+ out->mAttenuationLinear = srcLight->mAttLinear;
+ out->mAttenuationQuadratic = srcLight->mAttQuadratic;
+
+ out->mColorDiffuse = out->mColorSpecular = out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
+ if (out->mType == aiLightSource_AMBIENT) {
+ out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
+ out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
+ }
+ else {
+ // collada doesn't differentiate between these color types
+ out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
+ out->mColorAmbient = aiColor3D(0, 0, 0);
+ }
- // convert falloff angle and falloff exponent in our representation, if given
- if (out->mType == aiLightSource_SPOT) {
-
- out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
+ // convert falloff angle and falloff exponent in our representation, if given
+ if (out->mType == aiLightSource_SPOT) {
- // ... some extension magic.
- if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
- {
- // ... some deprecation magic.
- if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
- {
- // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
- // epsilon chosen to be 0.1
- out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
- srcLight->mFalloffAngle);
- }
- else {
- out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
- if (out->mAngleOuterCone < out->mAngleInnerCone)
- std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
- }
- }
- else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
- }
+ out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
- // add to light list
- mLights.push_back(out);
- }
+ // ... some extension magic.
+ if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
+ {
+ // ... some deprecation magic.
+ if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
+ {
+ // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
+ // epsilon chosen to be 0.1
+ out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
+ out->mAngleInnerCone;
+ }
+ else {
+ out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
+ if (out->mAngleOuterCone < out->mAngleInnerCone)
+ std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
+ }
+ }
+ else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
+ }
+
+ // add to light list
+ mLights.push_back(out);
+ }
}
// ------------------------------------------------------------------------------------------------
// Builds cameras for the given node and references them
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
- BOOST_FOREACH( const Collada::CameraInstance& cid, pNode->mCameras)
- {
- // find the referred light
- ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
- if( srcCameraIt == pParser.mCameraLibrary.end())
- {
- DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping.");
- continue;
- }
- const Collada::Camera* srcCamera = &srcCameraIt->second;
+ for( const Collada::CameraInstance& cid : pNode->mCameras)
+ {
+ // find the referred light
+ ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
+ if( srcCameraIt == pParser.mCameraLibrary.end())
+ {
+ DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping.");
+ continue;
+ }
+ const Collada::Camera* srcCamera = &srcCameraIt->second;
- // orthographic cameras not yet supported in Assimp
- if (srcCamera->mOrtho) {
- DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported.");
- }
+ // orthographic cameras not yet supported in Assimp
+ if (srcCamera->mOrtho) {
+ DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported.");
+ }
- // now fill our ai data structure
- aiCamera* out = new aiCamera();
- out->mName = pTarget->mName;
+ // now fill our ai data structure
+ aiCamera* out = new aiCamera();
+ out->mName = pTarget->mName;
- // collada cameras point in -Z by default, rest is specified in node transform
- out->mLookAt = aiVector3D(0.f,0.f,-1.f);
+ // collada cameras point in -Z by default, rest is specified in node transform
+ out->mLookAt = aiVector3D(0.f,0.f,-1.f);
- // near/far z is already ok
- out->mClipPlaneFar = srcCamera->mZFar;
- out->mClipPlaneNear = srcCamera->mZNear;
+ // near/far z is already ok
+ out->mClipPlaneFar = srcCamera->mZFar;
+ out->mClipPlaneNear = srcCamera->mZNear;
- // ... but for the rest some values are optional
- // and we need to compute the others in any combination.
- if (srcCamera->mAspect != 10e10f)
- out->mAspect = srcCamera->mAspect;
+ // ... but for the rest some values are optional
+ // and we need to compute the others in any combination.
+ if (srcCamera->mAspect != 10e10f)
+ out->mAspect = srcCamera->mAspect;
- if (srcCamera->mHorFov != 10e10f) {
- out->mHorizontalFOV = srcCamera->mHorFov;
+ if (srcCamera->mHorFov != 10e10f) {
+ out->mHorizontalFOV = srcCamera->mHorFov;
- if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) {
- out->mAspect = tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
+ if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) {
+ out->mAspect = tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
- }
- }
- else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
- out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(atan(srcCamera->mAspect *
+ }
+ }
+ else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
+ out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(atan(srcCamera->mAspect *
tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
- }
+ }
- // Collada uses degrees, we use radians
- out->mHorizontalFOV = AI_DEG_TO_RAD(out->mHorizontalFOV);
+ // Collada uses degrees, we use radians
+ out->mHorizontalFOV = AI_DEG_TO_RAD(out->mHorizontalFOV);
- // add to camera list
- mCameras.push_back(out);
- }
+ // add to camera list
+ mCameras.push_back(out);
+ }
}
// ------------------------------------------------------------------------------------------------
// Builds meshes for the given node and references them
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
{
- // accumulated mesh references by this node
- std::vector<size_t> newMeshRefs;
- newMeshRefs.reserve(pNode->mMeshes.size());
+ // accumulated mesh references by this node
+ std::vector<size_t> newMeshRefs;
+ newMeshRefs.reserve(pNode->mMeshes.size());
- // add a mesh for each subgroup in each collada mesh
- BOOST_FOREACH( const Collada::MeshInstance& mid, pNode->mMeshes)
- {
- const Collada::Mesh* srcMesh = NULL;
- const Collada::Controller* srcController = NULL;
+ // add a mesh for each subgroup in each collada mesh
+ for( const Collada::MeshInstance& mid : pNode->mMeshes)
+ {
+ const Collada::Mesh* srcMesh = NULL;
+ const Collada::Controller* srcController = NULL;
- // find the referred mesh
- ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
- if( srcMeshIt == pParser.mMeshLibrary.end())
- {
- // if not found in the mesh-library, it might also be a controller referring to a mesh
- ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
- if( srcContrIt != pParser.mControllerLibrary.end())
- {
- srcController = &srcContrIt->second;
- srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
- if( srcMeshIt != pParser.mMeshLibrary.end())
- srcMesh = srcMeshIt->second;
- }
+ // find the referred mesh
+ ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
+ if( srcMeshIt == pParser.mMeshLibrary.end())
+ {
+ // if not found in the mesh-library, it might also be a controller referring to a mesh
+ ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
+ if( srcContrIt != pParser.mControllerLibrary.end())
+ {
+ srcController = &srcContrIt->second;
+ srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
+ if( srcMeshIt != pParser.mMeshLibrary.end())
+ srcMesh = srcMeshIt->second;
+ }
- if( !srcMesh)
- {
- DefaultLogger::get()->warn( boost::str( boost::format( "Collada: Unable to find geometry for ID \"%s\". Skipping.") % mid.mMeshOrController));
- continue;
- }
- } else
- {
- // ID found in the mesh library -> direct reference to an unskinned mesh
- srcMesh = srcMeshIt->second;
- }
+ if( !srcMesh)
+ {
+ DefaultLogger::get()->warn( format() << "Collada: Unable to find geometry for ID \"" << mid.mMeshOrController << "\". Skipping." );
+ continue;
+ }
+ } else
+ {
+ // ID found in the mesh library -> direct reference to an unskinned mesh
+ srcMesh = srcMeshIt->second;
+ }
- // build a mesh for each of its subgroups
- size_t vertexStart = 0, faceStart = 0;
- for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm)
- {
- const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
- if( submesh.mNumFaces == 0)
- continue;
+ // build a mesh for each of its subgroups
+ size_t vertexStart = 0, faceStart = 0;
+ for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm)
+ {
+ const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
+ if( submesh.mNumFaces == 0)
+ continue;
- // find material assigned to this submesh
- std::string meshMaterial;
- std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
+ // find material assigned to this submesh
+ std::string meshMaterial;
+ std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
- const Collada::SemanticMappingTable* table = NULL;
- if( meshMatIt != mid.mMaterials.end())
- {
- table = &meshMatIt->second;
- meshMaterial = table->mMatName;
- }
- else
- {
- DefaultLogger::get()->warn( boost::str( boost::format( "Collada: No material specified for subgroup <%s> in geometry <%s>.") % submesh.mMaterial % mid.mMeshOrController));
- if( !mid.mMaterials.empty() )
- meshMaterial = mid.mMaterials.begin()->second.mMatName;
- }
+ const Collada::SemanticMappingTable* table = NULL;
+ if( meshMatIt != mid.mMaterials.end())
+ {
+ table = &meshMatIt->second;
+ meshMaterial = table->mMatName;
+ }
+ else
+ {
+ DefaultLogger::get()->warn( format() << "Collada: No material specified for subgroup <" << submesh.mMaterial << "> in geometry <" << mid.mMeshOrController << ">." );
+ if( !mid.mMaterials.empty() )
+ meshMaterial = mid.mMaterials.begin()->second.mMatName;
+ }
- // OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
- // given. The only mapping stuff which we do actually support is the UV channel.
- std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
- unsigned int matIdx;
- if( matIt != mMaterialIndexByName.end())
- matIdx = matIt->second;
- else
- matIdx = 0;
-
- if (table && !table->mMap.empty() ) {
- std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
-
- // Iterate through all texture channels assigned to the effect and
- // check whether we have mapping information for it.
- ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
- ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
- ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
- ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
- ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent,*table);
- ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
- }
+ // OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
+ // given. The only mapping stuff which we do actually support is the UV channel.
+ std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
+ unsigned int matIdx;
+ if( matIt != mMaterialIndexByName.end())
+ matIdx = matIt->second;
+ else
+ matIdx = 0;
+
+ if (table && !table->mMap.empty() ) {
+ std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
+
+ // Iterate through all texture channels assigned to the effect and
+ // check whether we have mapping information for it.
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent,*table);
+ ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
+ }
- // built lookup index of the Mesh-Submesh-Material combination
- ColladaMeshIndex index( mid.mMeshOrController, sm, meshMaterial);
+ // built lookup index of the Mesh-Submesh-Material combination
+ ColladaMeshIndex index( mid.mMeshOrController, sm, meshMaterial);
- // if we already have the mesh at the library, just add its index to the node's array
- std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
- if( dstMeshIt != mMeshIndexByID.end()) {
- newMeshRefs.push_back( dstMeshIt->second);
- }
- else
- {
- // else we have to add the mesh to the collection and store its newly assigned index at the node
- aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
+ // if we already have the mesh at the library, just add its index to the node's array
+ std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
+ if( dstMeshIt != mMeshIndexByID.end()) {
+ newMeshRefs.push_back( dstMeshIt->second);
+ }
+ else
+ {
+ // else we have to add the mesh to the collection and store its newly assigned index at the node
+ aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
- // store the mesh, and store its new index in the node
- newMeshRefs.push_back( mMeshes.size());
- mMeshIndexByID[index] = mMeshes.size();
- mMeshes.push_back( dstMesh);
- vertexStart += dstMesh->mNumVertices; faceStart += submesh.mNumFaces;
+ // store the mesh, and store its new index in the node
+ newMeshRefs.push_back( mMeshes.size());
+ mMeshIndexByID[index] = mMeshes.size();
+ mMeshes.push_back( dstMesh);
+ vertexStart += dstMesh->mNumVertices; faceStart += submesh.mNumFaces;
- // assign the material index
- dstMesh->mMaterialIndex = matIdx;
+ // assign the material index
+ dstMesh->mMaterialIndex = matIdx;
if(dstMesh->mName.length == 0)
{
dstMesh->mName = mid.mMeshOrController;
}
}
- }
- }
+ }
+ }
- // now place all mesh references we gathered in the target node
- pTarget->mNumMeshes = newMeshRefs.size();
- if( newMeshRefs.size())
- {
- pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes];
- std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes);
- }
+ // now place all mesh references we gathered in the target node
+ pTarget->mNumMeshes = newMeshRefs.size();
+ if( newMeshRefs.size())
+ {
+ pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes];
+ std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes);
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -558,47 +579,47 @@ aiMesh *ColladaLoader::findMesh(std::string meshid)
// ------------------------------------------------------------------------------------------------
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
-aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
- const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
+aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
+ const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
{
- aiMesh* dstMesh = new aiMesh;
-
+ aiMesh* dstMesh = new aiMesh;
+
dstMesh->mName = pSrcMesh->mName;
// count the vertices addressed by its faces
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
- pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0);
+ pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0);
// copy positions
dstMesh->mNumVertices = numVertices;
dstMesh->mVertices = new aiVector3D[numVertices];
- std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() +
- pStartVertex + numVertices, dstMesh->mVertices);
+ std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() +
+ pStartVertex + numVertices, dstMesh->mVertices);
- // normals, if given. HACK: (thom) Due to the glorious Collada spec we never
- // know if we have the same number of normals as there are positions. So we
+ // normals, if given. HACK: (thom) Due to the glorious Collada spec we never
+ // know if we have the same number of normals as there are positions. So we
// also ignore any vertex attribute if it has a different count
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices)
{
dstMesh->mNormals = new aiVector3D[numVertices];
std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() +
- pStartVertex + numVertices, dstMesh->mNormals);
+ pStartVertex + numVertices, dstMesh->mNormals);
}
- // tangents, if given.
+ // tangents, if given.
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices)
{
dstMesh->mTangents = new aiVector3D[numVertices];
- std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
- pStartVertex + numVertices, dstMesh->mTangents);
+ std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
+ pStartVertex + numVertices, dstMesh->mTangents);
}
- // bitangents, if given.
+ // bitangents, if given.
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices)
{
dstMesh->mBitangents = new aiVector3D[numVertices];
- std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
- pStartVertex + numVertices, dstMesh->mBitangents);
+ std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
+ pStartVertex + numVertices, dstMesh->mBitangents);
}
// same for texturecoords, as many as we have
@@ -610,7 +631,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
for( size_t b = 0; b < numVertices; ++b)
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
-
+
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real;
}
@@ -703,10 +724,10 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
}
- // create bones if given
+ // create bones if given
if( pSrcController && pSrcController->mType == Collada::Skin)
- {
- // refuse if the vertex count does not match
+ {
+ // refuse if the vertex count does not match
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
@@ -719,7 +740,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// joint vertex_weight name list - should refer to the same list as the joint names above. If not, report and reconsider
const Collada::Accessor& weightNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputJoints.mAccessor);
if( &weightNamesAcc != &jointNamesAcc)
- throw DeadlyImportError( "Temporary implementational lazyness. If you read this, please report to the author.");
+ throw DeadlyImportError( "Temporary implementational laziness. If you read this, please report to the author.");
// vertex weights
const Collada::Accessor& weightsAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor);
const Collada::Data& weights = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightsAcc.mSource);
@@ -841,166 +862,166 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
if( bnode)
bone->mName.Set( FindNameForNode( bnode));
else
- DefaultLogger::get()->warn( boost::str( boost::format( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"%s\".") % bone->mName.data));
+ DefaultLogger::get()->warn( format() << "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"" << bone->mName.data << "\"." );
// and insert bone
dstMesh->mBones[boneCount++] = bone;
}
- }
+ }
- return dstMesh;
+ return dstMesh;
}
// ------------------------------------------------------------------------------------------------
// Stores all meshes in the given scene
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
{
- pScene->mNumMeshes = mMeshes.size();
- if( mMeshes.size() > 0)
- {
- pScene->mMeshes = new aiMesh*[mMeshes.size()];
- std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
- mMeshes.clear();
- }
+ pScene->mNumMeshes = mMeshes.size();
+ if( mMeshes.size() > 0)
+ {
+ pScene->mMeshes = new aiMesh*[mMeshes.size()];
+ std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
+ mMeshes.clear();
+ }
}
// ------------------------------------------------------------------------------------------------
// Stores all cameras in the given scene
void ColladaLoader::StoreSceneCameras( aiScene* pScene)
{
- pScene->mNumCameras = mCameras.size();
- if( mCameras.size() > 0)
- {
- pScene->mCameras = new aiCamera*[mCameras.size()];
- std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
- mCameras.clear();
- }
+ pScene->mNumCameras = mCameras.size();
+ if( mCameras.size() > 0)
+ {
+ pScene->mCameras = new aiCamera*[mCameras.size()];
+ std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras);
+ mCameras.clear();
+ }
}
// ------------------------------------------------------------------------------------------------
// Stores all lights in the given scene
void ColladaLoader::StoreSceneLights( aiScene* pScene)
{
- pScene->mNumLights = mLights.size();
- if( mLights.size() > 0)
- {
- pScene->mLights = new aiLight*[mLights.size()];
- std::copy( mLights.begin(), mLights.end(), pScene->mLights);
- mLights.clear();
- }
+ pScene->mNumLights = mLights.size();
+ if( mLights.size() > 0)
+ {
+ pScene->mLights = new aiLight*[mLights.size()];
+ std::copy( mLights.begin(), mLights.end(), pScene->mLights);
+ mLights.clear();
+ }
}
// ------------------------------------------------------------------------------------------------
// Stores all textures in the given scene
void ColladaLoader::StoreSceneTextures( aiScene* pScene)
{
- pScene->mNumTextures = mTextures.size();
- if( mTextures.size() > 0)
- {
- pScene->mTextures = new aiTexture*[mTextures.size()];
- std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
- mTextures.clear();
- }
+ pScene->mNumTextures = mTextures.size();
+ if( mTextures.size() > 0)
+ {
+ pScene->mTextures = new aiTexture*[mTextures.size()];
+ std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures);
+ mTextures.clear();
+ }
}
// ------------------------------------------------------------------------------------------------
// Stores all materials in the given scene
void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
{
- pScene->mNumMaterials = newMats.size();
+ pScene->mNumMaterials = newMats.size();
- if (newMats.size() > 0) {
- pScene->mMaterials = new aiMaterial*[newMats.size()];
- for (unsigned int i = 0; i < newMats.size();++i)
- pScene->mMaterials[i] = newMats[i].second;
+ if (newMats.size() > 0) {
+ pScene->mMaterials = new aiMaterial*[newMats.size()];
+ for (unsigned int i = 0; i < newMats.size();++i)
+ pScene->mMaterials[i] = newMats[i].second;
- newMats.clear();
- }
+ newMats.clear();
+ }
}
// ------------------------------------------------------------------------------------------------
-// Stores all animations
+// Stores all animations
void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
{
- // recursivly collect all animations from the collada scene
- StoreAnimations( pScene, pParser, &pParser.mAnims, "");
+ // recursivly collect all animations from the collada scene
+ StoreAnimations( pScene, pParser, &pParser.mAnims, "");
- // catch special case: many animations with the same length, each affecting only a single node.
- // we need to unite all those single-node-anims to a proper combined animation
- for( size_t a = 0; a < mAnims.size(); ++a)
- {
- aiAnimation* templateAnim = mAnims[a];
- if( templateAnim->mNumChannels == 1)
- {
- // search for other single-channel-anims with the same duration
- std::vector<size_t> collectedAnimIndices;
- for( size_t b = a+1; b < mAnims.size(); ++b)
- {
- aiAnimation* other = mAnims[b];
- if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond )
- collectedAnimIndices.push_back( b);
- }
+ // catch special case: many animations with the same length, each affecting only a single node.
+ // we need to unite all those single-node-anims to a proper combined animation
+ for( size_t a = 0; a < mAnims.size(); ++a)
+ {
+ aiAnimation* templateAnim = mAnims[a];
+ if( templateAnim->mNumChannels == 1)
+ {
+ // search for other single-channel-anims with the same duration
+ std::vector<size_t> collectedAnimIndices;
+ for( size_t b = a+1; b < mAnims.size(); ++b)
+ {
+ aiAnimation* other = mAnims[b];
+ if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond )
+ collectedAnimIndices.push_back( b);
+ }
- // if there are other animations which fit the template anim, combine all channels into a single anim
- if( !collectedAnimIndices.empty() )
- {
- aiAnimation* combinedAnim = new aiAnimation();
- combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a));
- combinedAnim->mDuration = templateAnim->mDuration;
- combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
- combinedAnim->mNumChannels = collectedAnimIndices.size() + 1;
- combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels];
- // add the template anim as first channel by moving its aiNodeAnim to the combined animation
- combinedAnim->mChannels[0] = templateAnim->mChannels[0];
- templateAnim->mChannels[0] = NULL;
- delete templateAnim;
- // combined animation replaces template animation in the anim array
- mAnims[a] = combinedAnim;
-
- // move the memory of all other anims to the combined anim and erase them from the source anims
- for( size_t b = 0; b < collectedAnimIndices.size(); ++b)
- {
- aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]];
- combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0];
- srcAnimation->mChannels[0] = NULL;
- delete srcAnimation;
- }
-
- // in a second go, delete all the single-channel-anims that we've stripped from their channels
- // back to front to preserve indices - you know, removing an element from a vector moves all elements behind the removed one
- while( !collectedAnimIndices.empty() )
- {
- mAnims.erase( mAnims.begin() + collectedAnimIndices.back());
- collectedAnimIndices.pop_back();
- }
- }
- }
- }
+ // if there are other animations which fit the template anim, combine all channels into a single anim
+ if( !collectedAnimIndices.empty() )
+ {
+ aiAnimation* combinedAnim = new aiAnimation();
+ combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a));
+ combinedAnim->mDuration = templateAnim->mDuration;
+ combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
+ combinedAnim->mNumChannels = collectedAnimIndices.size() + 1;
+ combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels];
+ // add the template anim as first channel by moving its aiNodeAnim to the combined animation
+ combinedAnim->mChannels[0] = templateAnim->mChannels[0];
+ templateAnim->mChannels[0] = NULL;
+ delete templateAnim;
+ // combined animation replaces template animation in the anim array
+ mAnims[a] = combinedAnim;
+
+ // move the memory of all other anims to the combined anim and erase them from the source anims
+ for( size_t b = 0; b < collectedAnimIndices.size(); ++b)
+ {
+ aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]];
+ combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0];
+ srcAnimation->mChannels[0] = NULL;
+ delete srcAnimation;
+ }
- // now store all anims in the scene
- if( !mAnims.empty())
- {
- pScene->mNumAnimations = mAnims.size();
- pScene->mAnimations = new aiAnimation*[mAnims.size()];
- std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
- }
+ // in a second go, delete all the single-channel-anims that we've stripped from their channels
+ // back to front to preserve indices - you know, removing an element from a vector moves all elements behind the removed one
+ while( !collectedAnimIndices.empty() )
+ {
+ mAnims.erase( mAnims.begin() + collectedAnimIndices.back());
+ collectedAnimIndices.pop_back();
+ }
+ }
+ }
+ }
+
+ // now store all anims in the scene
+ if( !mAnims.empty())
+ {
+ pScene->mNumAnimations = mAnims.size();
+ pScene->mAnimations = new aiAnimation*[mAnims.size()];
+ std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
+ }
- mAnims.clear();
+ mAnims.clear();
}
// ------------------------------------------------------------------------------------------------
-// Constructs the animations for the given source anim
-void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string pPrefix)
+// Constructs the animations for the given source anim
+void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string &pPrefix)
{
- std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName;
+ std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName;
- // create nested animations, if given
- for( std::vector<Collada::Animation*>::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it)
- StoreAnimations( pScene, pParser, *it, animName);
+ // create nested animations, if given
+ for( std::vector<Collada::Animation*>::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it)
+ StoreAnimations( pScene, pParser, *it, animName);
- // create animation channels, if any
- if( !pSrcAnim->mChannels.empty())
- CreateAnimation( pScene, pParser, pSrcAnim, animName);
+ // create animation channels, if any
+ if( !pSrcAnim->mChannels.empty())
+ CreateAnimation( pScene, pParser, pSrcAnim, animName);
}
struct MorphTimeValues
@@ -1090,7 +1111,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
// now check all channels if they affect the current node
for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
- cit != pSrcAnim->mChannels.end(); ++cit)
+ cit != pSrcAnim->mChannels.end(); ++cit)
{
const Collada::AnimationChannel& srcChannel = *cit;
Collada::ChannelEntry entry;
@@ -1098,10 +1119,10 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
// we expect the animation target to be of type "nodeName/transformID.subElement". Ignore all others
// find the slash that separates the node name - there should be only one
std::string::size_type slashPos = srcChannel.mTarget.find( '/');
- if( slashPos == std::string::npos) {
- std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID);
- if (targetPos == std::string::npos)
- continue;
+ if( slashPos == std::string::npos) {
+ std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID);
+ if (targetPos == std::string::npos)
+ continue;
// not node transform, but something else. store as unknown animation channel for now
entry.mChannel = &(*cit);
@@ -1112,11 +1133,11 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
entries.push_back(entry);
continue;
}
- if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
- continue;
- std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
- if( targetID != srcNode->mID)
- continue;
+ if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
+ continue;
+ std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
+ if( targetID != srcNode->mID)
+ continue;
// find the dot that separates the transformID - there should be only one or zero
std::string::size_type dotPos = srcChannel.mTarget.find( '.');
@@ -1136,8 +1157,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
entry.mSubElement = 1;
else if( subElement == "Z")
entry.mSubElement = 2;
- else
- DefaultLogger::get()->warn( boost::str( boost::format( "Unknown anim subelement <%s>. Ignoring") % subElement));
+ else
+ DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
} else
{
// no subelement following, transformId is remaining string
@@ -1180,7 +1201,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
// time count and value count must match
if( e.mTimeAccessor->mCount != e.mValueAccessor->mCount)
- throw DeadlyImportError( boost::str( boost::format( "Time count / value count mismatch in animation channel \"%s\".") % e.mChannel->mTarget));
+ throw DeadlyImportError( format() << "Time count / value count mismatch in animation channel \"" << e.mChannel->mTarget << "\"." );
if( e.mTimeAccessor->mCount > 0 )
{
@@ -1249,7 +1270,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
// Calculate resulting transformation
aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms);
- // out of lazyness: we store the time in matrix.d4
+ // out of laziness: we store the time in matrix.d4
mat.d4 = time;
resultTrafos.push_back( mat);
@@ -1282,10 +1303,10 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
}
}
- // there should be some keyframes, but we aren't that fixated on valid input data
-// ai_assert( resultTrafos.size() > 0);
+ // there should be some keyframes, but we aren't that fixated on valid input data
+// ai_assert( resultTrafos.size() > 0);
- // build an animation channel for the given node out of these trafo keys
+ // build an animation channel for the given node out of these trafo keys
if( !resultTrafos.empty() )
{
aiNodeAnim* dstAnim = new aiNodeAnim;
@@ -1377,24 +1398,24 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
morphAnims.push_back(morphAnim);
}
}
- }
+ }
- if( !anims.empty() || !morphAnims.empty())
+ if( !anims.empty() || !morphAnims.empty())
{
aiAnimation* anim = new aiAnimation;
anim->mName.Set( pName);
anim->mNumChannels = anims.size();
- if (anim->mNumChannels > 0)
- {
- anim->mChannels = new aiNodeAnim*[anims.size()];
- std::copy( anims.begin(), anims.end(), anim->mChannels);
- }
- anim->mNumMorphMeshChannels = morphAnims.size();
- if (anim->mNumMorphMeshChannels > 0)
- {
- anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];
- std::copy( morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels);
- }
+ if (anim->mNumChannels > 0)
+ {
+ anim->mChannels = new aiNodeAnim*[anims.size()];
+ std::copy( anims.begin(), anims.end(), anim->mChannels);
+ }
+ anim->mNumMorphMeshChannels = morphAnims.size();
+ if (anim->mNumMorphMeshChannels > 0)
+ {
+ anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];
+ std::copy( morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels);
+ }
anim->mDuration = 0.0f;
for( size_t a = 0; a < anims.size(); ++a)
{
@@ -1402,10 +1423,10 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime);
anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime);
}
- for (size_t a = 0; a < morphAnims.size(); ++a)
- {
- anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys-1].mTime);
- }
+ for (size_t a = 0; a < morphAnims.size(); ++a)
+ {
+ anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys-1].mTime);
+ }
anim->mTicksPerSecond = 1;
mAnims.push_back( anim);
}
@@ -1414,285 +1435,306 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
// ------------------------------------------------------------------------------------------------
// Add a texture to a material structure
void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
- const Collada::Effect& effect,
- const Collada::Sampler& sampler,
- aiTextureType type, unsigned int idx)
+ const Collada::Effect& effect,
+ const Collada::Sampler& sampler,
+ aiTextureType type, unsigned int idx)
{
- // first of all, basic file name
- const aiString name = FindFilenameForEffectTexture( pParser, effect, sampler.mName );
- mat.AddProperty( &name, _AI_MATKEY_TEXTURE_BASE, type, idx );
-
- // mapping mode
- int map = aiTextureMapMode_Clamp;
- if (sampler.mWrapU)
- map = aiTextureMapMode_Wrap;
- if (sampler.mWrapU && sampler.mMirrorU)
- map = aiTextureMapMode_Mirror;
-
- mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_U_BASE, type, idx);
-
- map = aiTextureMapMode_Clamp;
- if (sampler.mWrapV)
- map = aiTextureMapMode_Wrap;
- if (sampler.mWrapV && sampler.mMirrorV)
- map = aiTextureMapMode_Mirror;
-
- mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_V_BASE, type, idx);
-
- // UV transformation
- mat.AddProperty(&sampler.mTransform, 1,
- _AI_MATKEY_UVTRANSFORM_BASE, type, idx);
-
- // Blend mode
- mat.AddProperty((int*)&sampler.mOp , 1,
- _AI_MATKEY_TEXBLEND_BASE, type, idx);
-
- // Blend factor
- mat.AddProperty((float*)&sampler.mWeighting , 1,
- _AI_MATKEY_TEXBLEND_BASE, type, idx);
-
- // UV source index ... if we didn't resolve the mapping, it is actually just
- // a guess but it works in most cases. We search for the frst occurence of a
- // number in the channel name. We assume it is the zero-based index into the
- // UV channel array of all corresponding meshes. It could also be one-based
- // for some exporters, but we won't care of it unless someone complains about.
- if (sampler.mUVId != UINT_MAX)
- map = sampler.mUVId;
- else {
- map = -1;
- for (std::string::const_iterator it = sampler.mUVChannel.begin();it != sampler.mUVChannel.end(); ++it){
- if (IsNumeric(*it)) {
- map = strtoul10(&(*it));
- break;
- }
- }
- if (-1 == map) {
- DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
- map = 0;
- }
- }
- mat.AddProperty(&map,1,_AI_MATKEY_UVWSRC_BASE,type,idx);
+ // first of all, basic file name
+ const aiString name = FindFilenameForEffectTexture( pParser, effect, sampler.mName );
+ mat.AddProperty( &name, _AI_MATKEY_TEXTURE_BASE, type, idx );
+
+ // mapping mode
+ int map = aiTextureMapMode_Clamp;
+ if (sampler.mWrapU)
+ map = aiTextureMapMode_Wrap;
+ if (sampler.mWrapU && sampler.mMirrorU)
+ map = aiTextureMapMode_Mirror;
+
+ mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_U_BASE, type, idx);
+
+ map = aiTextureMapMode_Clamp;
+ if (sampler.mWrapV)
+ map = aiTextureMapMode_Wrap;
+ if (sampler.mWrapV && sampler.mMirrorV)
+ map = aiTextureMapMode_Mirror;
+
+ mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_V_BASE, type, idx);
+
+ // UV transformation
+ mat.AddProperty(&sampler.mTransform, 1,
+ _AI_MATKEY_UVTRANSFORM_BASE, type, idx);
+
+ // Blend mode
+ mat.AddProperty((int*)&sampler.mOp , 1,
+ _AI_MATKEY_TEXBLEND_BASE, type, idx);
+
+ // Blend factor
+ mat.AddProperty((float*)&sampler.mWeighting , 1,
+ _AI_MATKEY_TEXBLEND_BASE, type, idx);
+
+ // UV source index ... if we didn't resolve the mapping, it is actually just
+ // a guess but it works in most cases. We search for the frst occurrence of a
+ // number in the channel name. We assume it is the zero-based index into the
+ // UV channel array of all corresponding meshes. It could also be one-based
+ // for some exporters, but we won't care of it unless someone complains about.
+ if (sampler.mUVId != UINT_MAX)
+ map = sampler.mUVId;
+ else {
+ map = -1;
+ for (std::string::const_iterator it = sampler.mUVChannel.begin();it != sampler.mUVChannel.end(); ++it){
+ if (IsNumeric(*it)) {
+ map = strtoul10(&(*it));
+ break;
+ }
+ }
+ if (-1 == map) {
+ DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
+ map = 0;
+ }
+ }
+ mat.AddProperty(&map,1,_AI_MATKEY_UVWSRC_BASE,type,idx);
}
// ------------------------------------------------------------------------------------------------
// Fills materials from the collada material definitions
void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pScene*/)
{
- for (std::vector<std::pair<Collada::Effect*, aiMaterial*> >::iterator it = newMats.begin(),
- end = newMats.end(); it != end; ++it)
- {
- aiMaterial& mat = (aiMaterial&)*it->second;
- Collada::Effect& effect = *it->first;
-
- // resolve shading mode
- int shadeMode;
- if (effect.mFaceted) /* fixme */
- shadeMode = aiShadingMode_Flat;
- else {
- switch( effect.mShadeType)
- {
- case Collada::Shade_Constant:
- shadeMode = aiShadingMode_NoShading;
- break;
- case Collada::Shade_Lambert:
- shadeMode = aiShadingMode_Gouraud;
- break;
- case Collada::Shade_Blinn:
- shadeMode = aiShadingMode_Blinn;
- break;
- case Collada::Shade_Phong:
- shadeMode = aiShadingMode_Phong;
- break;
-
- default:
- DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading");
- shadeMode = aiShadingMode_Gouraud;
- break;
- }
- }
- mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
-
- // double-sided?
- shadeMode = effect.mDoubleSided;
- mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_TWOSIDED);
-
- // wireframe?
- shadeMode = effect.mWireframe;
- mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_ENABLE_WIREFRAME);
-
- // add material colors
- mat.AddProperty( &effect.mAmbient, 1,AI_MATKEY_COLOR_AMBIENT);
- mat.AddProperty( &effect.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat.AddProperty( &effect.mSpecular, 1,AI_MATKEY_COLOR_SPECULAR);
- mat.AddProperty( &effect.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
- mat.AddProperty( &effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT);
- mat.AddProperty( &effect.mReflective, 1, AI_MATKEY_COLOR_REFLECTIVE);
-
- // scalar properties
- mat.AddProperty( &effect.mShininess, 1, AI_MATKEY_SHININESS);
- mat.AddProperty( &effect.mReflectivity, 1, AI_MATKEY_REFLECTIVITY);
- mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI);
-
- // transparency, a very hard one. seemingly not all files are following the
- // specification here .. but we can trick.
- if (effect.mTransparency >= 0.f && effect.mTransparency < 1.f) {
- effect.mTransparency = 1.f- effect.mTransparency;
- mat.AddProperty( &effect.mTransparency, 1, AI_MATKEY_OPACITY );
- mat.AddProperty( &effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
- }
+ for (auto &elem : newMats)
+ {
+ aiMaterial& mat = (aiMaterial&)*elem.second;
+ Collada::Effect& effect = *elem.first;
+
+ // resolve shading mode
+ int shadeMode;
+ if (effect.mFaceted) /* fixme */
+ shadeMode = aiShadingMode_Flat;
+ else {
+ switch( effect.mShadeType)
+ {
+ case Collada::Shade_Constant:
+ shadeMode = aiShadingMode_NoShading;
+ break;
+ case Collada::Shade_Lambert:
+ shadeMode = aiShadingMode_Gouraud;
+ break;
+ case Collada::Shade_Blinn:
+ shadeMode = aiShadingMode_Blinn;
+ break;
+ case Collada::Shade_Phong:
+ shadeMode = aiShadingMode_Phong;
+ break;
+
+ default:
+ DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading");
+ shadeMode = aiShadingMode_Gouraud;
+ break;
+ }
+ }
+ mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ // double-sided?
+ shadeMode = effect.mDoubleSided;
+ mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_TWOSIDED);
+
+ // wireframe?
+ shadeMode = effect.mWireframe;
+ mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_ENABLE_WIREFRAME);
+
+ // add material colors
+ mat.AddProperty( &effect.mAmbient, 1,AI_MATKEY_COLOR_AMBIENT);
+ mat.AddProperty( &effect.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat.AddProperty( &effect.mSpecular, 1,AI_MATKEY_COLOR_SPECULAR);
+ mat.AddProperty( &effect.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+ mat.AddProperty( &effect.mReflective, 1, AI_MATKEY_COLOR_REFLECTIVE);
+
+ // scalar properties
+ mat.AddProperty( &effect.mShininess, 1, AI_MATKEY_SHININESS);
+ mat.AddProperty( &effect.mReflectivity, 1, AI_MATKEY_REFLECTIVITY);
+ mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI);
+
+ // transparency, a very hard one. seemingly not all files are following the
+ // specification here (1.0 transparency => completly opaque)...
+ // therefore, we let the opportunity for the user to manually invert
+ // the transparency if necessary and we add preliminary support for RGB_ZERO mode
+ if(effect.mTransparency >= 0.f && effect.mTransparency <= 1.f) {
+ // handle RGB transparency completely, cf Collada specs 1.5.0 pages 249 and 304
+ if(effect.mRGBTransparency) {
+ // use luminance as defined by ISO/CIE color standards (see ITU-R Recommendation BT.709-4)
+ effect.mTransparency *= (
+ 0.212671f * effect.mTransparent.r +
+ 0.715160f * effect.mTransparent.g +
+ 0.072169f * effect.mTransparent.b
+ );
+
+ effect.mTransparent.a = 1.f;
+
+ mat.AddProperty( &effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT );
+ } else {
+ effect.mTransparency *= effect.mTransparent.a;
+ }
- // add textures, if given
- if( !effect.mTexAmbient.mName.empty())
- /* It is merely a lightmap */
- AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
+ if(effect.mInvertTransparency) {
+ effect.mTransparency = 1.f - effect.mTransparency;
+ }
- if( !effect.mTexEmissive.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
+ // Is the material finally transparent ?
+ if (effect.mHasTransparency || effect.mTransparency < 1.f) {
+ mat.AddProperty( &effect.mTransparency, 1, AI_MATKEY_OPACITY );
+ }
+ }
- if( !effect.mTexSpecular.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexSpecular, aiTextureType_SPECULAR);
+ // add textures, if given
+ if( !effect.mTexAmbient.mName.empty())
+ /* It is merely a lightmap */
+ AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
- if( !effect.mTexDiffuse.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexDiffuse, aiTextureType_DIFFUSE);
+ if( !effect.mTexEmissive.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
- if( !effect.mTexBump.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexBump, aiTextureType_NORMALS);
+ if( !effect.mTexSpecular.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexSpecular, aiTextureType_SPECULAR);
- if( !effect.mTexTransparent.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexTransparent, aiTextureType_OPACITY);
+ if( !effect.mTexDiffuse.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexDiffuse, aiTextureType_DIFFUSE);
- if( !effect.mTexReflective.mName.empty())
- AddTexture( mat, pParser, effect, effect.mTexReflective, aiTextureType_REFLECTION);
- }
+ if( !effect.mTexBump.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexBump, aiTextureType_NORMALS);
+
+ if( !effect.mTexTransparent.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexTransparent, aiTextureType_OPACITY);
+
+ if( !effect.mTexReflective.mName.empty())
+ AddTexture( mat, pParser, effect, effect.mTexReflective, aiTextureType_REFLECTION);
+ }
}
// ------------------------------------------------------------------------------------------------
// Constructs materials from the collada material definitions
void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
{
- newMats.reserve(pParser.mMaterialLibrary.size());
-
- for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
- {
- const Collada::Material& material = matIt->second;
- // a material is only a reference to an effect
- ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
- if( effIt == pParser.mEffectLibrary.end())
- continue;
- Collada::Effect& effect = effIt->second;
+ newMats.reserve(pParser.mMaterialLibrary.size());
- // create material
- aiMaterial* mat = new aiMaterial;
- aiString name( matIt->first);
- mat->AddProperty(&name,AI_MATKEY_NAME);
-
- // store the material
- mMaterialIndexByName[matIt->first] = newMats.size();
- newMats.push_back( std::pair<Collada::Effect*, aiMaterial*>( &effect,mat) );
- }
- // ScenePreprocessor generates a default material automatically if none is there.
- // All further code here in this loader works well without a valid material so
- // we can safely let it to ScenePreprocessor.
+ for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
+ {
+ const Collada::Material& material = matIt->second;
+ // a material is only a reference to an effect
+ ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
+ if( effIt == pParser.mEffectLibrary.end())
+ continue;
+ Collada::Effect& effect = effIt->second;
+
+ // create material
+ aiMaterial* mat = new aiMaterial;
+ aiString name( material.mName.empty() ? matIt->first : material.mName );
+ mat->AddProperty(&name,AI_MATKEY_NAME);
+
+ // store the material
+ mMaterialIndexByName[matIt->first] = newMats.size();
+ newMats.push_back( std::pair<Collada::Effect*, aiMaterial*>( &effect,mat) );
+ }
+ // ScenePreprocessor generates a default material automatically if none is there.
+ // All further code here in this loader works well without a valid material so
+ // we can safely let it to ScenePreprocessor.
#if 0
- if( newMats.size() == 0)
- {
- aiMaterial* mat = new aiMaterial;
- aiString name( AI_DEFAULT_MATERIAL_NAME );
- mat->AddProperty( &name, AI_MATKEY_NAME);
-
- const int shadeMode = aiShadingMode_Phong;
- mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
- aiColor4D colAmbient( 0.2f, 0.2f, 0.2f, 1.0f), colDiffuse( 0.8f, 0.8f, 0.8f, 1.0f), colSpecular( 0.5f, 0.5f, 0.5f, 0.5f);
- mat->AddProperty( &colAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
- mat->AddProperty( &colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat->AddProperty( &colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
- const float specExp = 5.0f;
- mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
- }
+ if( newMats.size() == 0)
+ {
+ aiMaterial* mat = new aiMaterial;
+ aiString name( AI_DEFAULT_MATERIAL_NAME );
+ mat->AddProperty( &name, AI_MATKEY_NAME);
+
+ const int shadeMode = aiShadingMode_Phong;
+ mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+ aiColor4D colAmbient( 0.2f, 0.2f, 0.2f, 1.0f), colDiffuse( 0.8f, 0.8f, 0.8f, 1.0f), colSpecular( 0.5f, 0.5f, 0.5f, 0.5f);
+ mat->AddProperty( &colAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+ mat->AddProperty( &colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat->AddProperty( &colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+ const float specExp = 5.0f;
+ mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
+ }
#endif
}
// ------------------------------------------------------------------------------------------------
// Resolves the texture name for the given effect texture entry
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
- const Collada::Effect& pEffect, const std::string& pName)
+ const Collada::Effect& pEffect, const std::string& pName)
{
- // recurse through the param references until we end up at an image
- std::string name = pName;
- while( 1)
- {
- // the given string is a param entry. Find it
- Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find( name);
- // if not found, we're at the end of the recursion. The resulting string should be the image ID
- if( it == pEffect.mParams.end())
- break;
-
- // else recurse on
- name = it->second.mReference;
- }
+ // recurse through the param references until we end up at an image
+ std::string name = pName;
+ while( 1)
+ {
+ // the given string is a param entry. Find it
+ Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find( name);
+ // if not found, we're at the end of the recursion. The resulting string should be the image ID
+ if( it == pEffect.mParams.end())
+ break;
+
+ // else recurse on
+ name = it->second.mReference;
+ }
- // find the image referred by this name in the image library of the scene
- ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
- if( imIt == pParser.mImageLibrary.end())
- {
- throw DeadlyImportError( boost::str( boost::format(
- "Collada: Unable to resolve effect texture entry \"%s\", ended up at ID \"%s\".") % pName % name));
- }
+ // find the image referred by this name in the image library of the scene
+ ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
+ if( imIt == pParser.mImageLibrary.end())
+ {
+ throw DeadlyImportError( format() <<
+ "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
+ }
- aiString result;
+ aiString result;
- // if this is an embedded texture image setup an aiTexture for it
- if (imIt->second.mFileName.empty())
- {
- if (imIt->second.mImageData.empty()) {
- throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
- }
+ // if this is an embedded texture image setup an aiTexture for it
+ if (imIt->second.mFileName.empty())
+ {
+ if (imIt->second.mImageData.empty()) {
+ throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
+ }
- aiTexture* tex = new aiTexture();
+ aiTexture* tex = new aiTexture();
- // setup format hint
- if (imIt->second.mEmbeddedFormat.length() > 3) {
- DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters");
- }
- strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
+ // setup format hint
+ if (imIt->second.mEmbeddedFormat.length() > 3) {
+ DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters");
+ }
+ strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
- // and copy texture data
- tex->mHeight = 0;
- tex->mWidth = imIt->second.mImageData.size();
- tex->pcData = (aiTexel*)new char[tex->mWidth];
- memcpy(tex->pcData,&imIt->second.mImageData[0],tex->mWidth);
+ // and copy texture data
+ tex->mHeight = 0;
+ tex->mWidth = imIt->second.mImageData.size();
+ tex->pcData = (aiTexel*)new char[tex->mWidth];
+ memcpy(tex->pcData,&imIt->second.mImageData[0],tex->mWidth);
- // setup texture reference string
- result.data[0] = '*';
- result.length = 1 + ASSIMP_itoa10(result.data+1,MAXLEN-1,mTextures.size());
+ // setup texture reference string
+ result.data[0] = '*';
+ result.length = 1 + ASSIMP_itoa10(result.data+1,MAXLEN-1,mTextures.size());
- // and add this texture to the list
- mTextures.push_back(tex);
- }
- else
- {
- result.Set( imIt->second.mFileName );
- ConvertPath(result);
- }
- return result;
+ // and add this texture to the list
+ mTextures.push_back(tex);
+ }
+ else
+ {
+ result.Set( imIt->second.mFileName );
+ ConvertPath(result);
+ }
+ return result;
}
// ------------------------------------------------------------------------------------------------
// Convert a path read from a collada file to the usual representation
void ColladaLoader::ConvertPath (aiString& ss)
{
- // TODO: collada spec, p 22. Handle URI correctly.
- // For the moment we're just stripping the file:// away to make it work.
- // Windoes doesn't seem to be able to find stuff like
- // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
- if (0 == strncmp(ss.data,"file://",7))
- {
- ss.length -= 7;
- memmove(ss.data,ss.data+7,ss.length);
- ss.data[ss.length] = '\0';
- }
+ // TODO: collada spec, p 22. Handle URI correctly.
+ // For the moment we're just stripping the file:// away to make it work.
+ // Windoes doesn't seem to be able to find stuff like
+ // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
+ if (0 == strncmp(ss.data,"file://",7))
+ {
+ ss.length -= 7;
+ memmove(ss.data,ss.data+7,ss.length);
+ ss.data[ss.length] = '\0';
+ }
- // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
+ // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
// I need to filter it without destroying linux paths starting with "/somewhere"
if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
{
@@ -1727,46 +1769,46 @@ void ColladaLoader::ConvertPath (aiString& ss)
// Reads a float value from an accessor and its data array.
float ColladaLoader::ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const
{
- // FIXME: (thom) Test for data type here in every access? For the moment, I leave this to the caller
- size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
- ai_assert( pos < pData.mValues.size());
- return pData.mValues[pos];
+ // FIXME: (thom) Test for data type here in every access? For the moment, I leave this to the caller
+ size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
+ ai_assert( pos < pData.mValues.size());
+ return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Reads a string value from an accessor and its data array.
const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const
{
- size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset;
- ai_assert( pos < pData.mStrings.size());
- return pData.mStrings[pos];
+ size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset;
+ ai_assert( pos < pData.mStrings.size());
+ return pData.mStrings[pos];
}
// ------------------------------------------------------------------------------------------------
// Collects all nodes into the given array
void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const
{
- poNodes.push_back( pNode);
+ poNodes.push_back( pNode);
- for( size_t a = 0; a < pNode->mNumChildren; ++a)
- CollectNodes( pNode->mChildren[a], poNodes);
+ for( size_t a = 0; a < pNode->mNumChildren; ++a)
+ CollectNodes( pNode->mChildren[a], poNodes);
}
// ------------------------------------------------------------------------------------------------
// Finds a node in the collada scene by the given name
const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const std::string& pName) const
{
- if( pNode->mName == pName || pNode->mID == pName)
- return pNode;
+ if( pNode->mName == pName || pNode->mID == pName)
+ return pNode;
- for( size_t a = 0; a < pNode->mChildren.size(); ++a)
- {
- const Collada::Node* node = FindNode( pNode->mChildren[a], pName);
- if( node)
- return node;
- }
+ for( size_t a = 0; a < pNode->mChildren.size(); ++a)
+ {
+ const Collada::Node* node = FindNode( pNode->mChildren[a], pName);
+ if( node)
+ return node;
+ }
- return NULL;
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
@@ -1788,22 +1830,22 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
// ------------------------------------------------------------------------------------------------
// Finds a proper name for a node derived from the collada-node's properties
-std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) const
+std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
{
- // now setup the name of the node. We take the name if not empty, otherwise the collada ID
- // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
- if (!pNode->mName.empty() && pNode->mName != "untitled")
- return pNode->mName;
- else if (!pNode->mID.empty())
- return pNode->mID;
- else if (!pNode->mSID.empty())
+ // now setup the name of the node. We take the name if not empty, otherwise the collada ID
+ // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
+ if (!pNode->mName.empty() && pNode->mName != "untitled")
+ return pNode->mName;
+ else if (!pNode->mID.empty())
+ return pNode->mID;
+ else if (!pNode->mSID.empty())
return pNode->mSID;
else
- {
- // No need to worry. Unnamed nodes are no problem at all, except
- // if cameras or lights need to be assigned to them.
- return boost::str( boost::format( "$ColladaAutoName$_%d") % clock());
- }
+ {
+ // No need to worry. Unnamed nodes are no problem at all, except
+ // if cameras or lights need to be assigned to them.
+ return format() << "$ColladaAutoName$_" << mNodeNameCounter++;
+ }
}
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ColladaLoader.h b/src/3rdparty/assimp/code/ColladaLoader.h
index 3c993d100..16750906f 100644
--- a/src/3rdparty/assimp/code/ColladaLoader.h
+++ b/src/3rdparty/assimp/code/ColladaLoader.h
@@ -4,11 +4,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,47 +46,53 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "ColladaParser.h"
+struct aiNode;
+struct aiCamera;
+struct aiLight;
+struct aiTexture;
+struct aiAnimation;
+
namespace Assimp
{
struct ColladaMeshIndex
{
- std::string mMeshID;
- size_t mSubMesh;
- std::string mMaterial;
- ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
- : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
- { }
-
- bool operator < (const ColladaMeshIndex& p) const
- {
- if( mMeshID == p.mMeshID)
- {
- if( mSubMesh == p.mSubMesh)
- return mMaterial < p.mMaterial;
- else
- return mSubMesh < p.mSubMesh;
- } else
- {
- return mMeshID < p.mMeshID;
- }
- }
+ std::string mMeshID;
+ size_t mSubMesh;
+ std::string mMaterial;
+ ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
+ : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
+ { }
+
+ bool operator < (const ColladaMeshIndex& p) const
+ {
+ if( mMeshID == p.mMeshID)
+ {
+ if( mSubMesh == p.mSubMesh)
+ return mMaterial < p.mMaterial;
+ else
+ return mSubMesh < p.mSubMesh;
+ } else
+ {
+ return mMeshID < p.mMeshID;
+ }
+ }
};
/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
- * more useless stuff, so I limited the data to what I think is useful for games.
+ * more useless stuff, so I limited the data to what I think is useful for games.
*/
class ColladaLoader : public BaseImporter
{
public:
- ColladaLoader();
- ~ColladaLoader();
+ ColladaLoader();
+ ~ColladaLoader();
public:
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected:
/** Return importer meta information.
@@ -96,7 +102,7 @@ protected:
void SetupProperties(const Importer* pImp);
- /** Imports the given file into the given scene structure.
+ /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
@@ -106,25 +112,25 @@ protected:
/** Resolve node instances */
void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
- std::vector<const Collada::Node*>& resolved);
+ std::vector<const Collada::Node*>& resolved);
/** Builds meshes for the given node and references them */
- void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
- aiNode* pTarget);
+ void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+ aiNode* pTarget);
- aiMesh *findMesh(std::string meshid);
+ aiMesh *findMesh(std::string meshid);
/** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
- aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
- const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
+ aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
+ const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
/** Builds cameras for the given node and references them */
- void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode,
- aiNode* pTarget);
+ void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+ aiNode* pTarget);
/** Builds lights for the given node and references them */
- void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode,
- aiNode* pTarget);
+ void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+ aiNode* pTarget);
/** Stores all meshes in the given scene */
void StoreSceneMeshes( aiScene* pScene);
@@ -141,7 +147,7 @@ protected:
/** Stores all textures in the given scene */
void StoreSceneTextures( aiScene* pScene);
- /** Stores all animations
+ /** Stores all animations
* @param pScene target scene to store the anims
*/
void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
@@ -151,11 +157,11 @@ protected:
* @param pSrcAnim the source animation to process
* @param pPrefix Prefix to the name in case of nested animations
*/
- void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string pPrefix);
+ void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string &pPrefix);
/** Constructs the animation for the given source anim */
void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName);
-
+
/** Constructs materials from the collada material definitions */
void BuildMaterials( ColladaParser& pParser, aiScene* pScene);
@@ -164,17 +170,17 @@ protected:
/** Resolve UV channel mappings*/
void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
- const Collada::SemanticMappingTable& table);
+ const Collada::SemanticMappingTable& table);
/** Add a texture and all of its sampling properties to a material*/
void AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
- const Collada::Effect& effect,
- const Collada::Sampler& sampler,
- aiTextureType type, unsigned int idx = 0);
+ const Collada::Effect& effect,
+ const Collada::Sampler& sampler,
+ aiTextureType type, unsigned int idx = 0);
/** Resolves the texture name for the given effect texture entry */
- aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
- const Collada::Effect& pEffect, const std::string& pName);
+ aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
+ const Collada::Effect& pEffect, const std::string& pName);
/** Converts a path read from a collada file to the usual representation */
void ConvertPath( aiString& ss);
@@ -205,41 +211,44 @@ protected:
const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
/** Finds a proper name for a node derived from the collada-node's properties */
- std::string FindNameForNode( const Collada::Node* pNode) const;
+ std::string FindNameForNode( const Collada::Node* pNode);
protected:
- /** Filename, for a verbose error message */
- std::string mFileName;
+ /** Filename, for a verbose error message */
+ std::string mFileName;
- /** Which mesh-material compound was stored under which mesh ID */
- std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
+ /** Which mesh-material compound was stored under which mesh ID */
+ std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
- /** Which material was stored under which index in the scene */
- std::map<std::string, size_t> mMaterialIndexByName;
+ /** Which material was stored under which index in the scene */
+ std::map<std::string, size_t> mMaterialIndexByName;
- /** Accumulated meshes for the target scene */
- std::vector<aiMesh*> mMeshes;
+ /** Accumulated meshes for the target scene */
+ std::vector<aiMesh*> mMeshes;
- /** Accumulated morph target meshes */
- std::vector<aiMesh*> mTargetMeshes;
+ /** Accumulated morph target meshes */
+ std::vector<aiMesh*> mTargetMeshes;
/** Temporary material list */
std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
- /** Temporary camera list */
- std::vector<aiCamera*> mCameras;
+ /** Temporary camera list */
+ std::vector<aiCamera*> mCameras;
+
+ /** Temporary light list */
+ std::vector<aiLight*> mLights;
- /** Temporary light list */
- std::vector<aiLight*> mLights;
+ /** Temporary texture list */
+ std::vector<aiTexture*> mTextures;
- /** Temporary texture list */
- std::vector<aiTexture*> mTextures;
+ /** Accumulated animations for the target scene */
+ std::vector<aiAnimation*> mAnims;
- /** Accumulated animations for the target scene */
- std::vector<aiAnimation*> mAnims;
+ bool noSkeletonMesh;
+ bool ignoreUpDirection;
- bool noSkeletonMesh;
- bool ignoreUpDirection;
+ /** Used by FindNameForNode() to generate unique node names */
+ unsigned int mNodeNameCounter;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ColladaParser.cpp b/src/3rdparty/assimp/code/ColladaParser.cpp
index 5369ee64c..aec57e684 100644
--- a/src/3rdparty/assimp/code/ColladaParser.cpp
+++ b/src/3rdparty/assimp/code/ColladaParser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,235 +43,317 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Collada parser helper
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
+#include <sstream>
+#include <stdarg.h>
#include "ColladaParser.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
+#include "StringUtils.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/light.h>
+#include "TinyFormatter.h"
+
+#include <memory>
+
using namespace Assimp;
using namespace Assimp::Collada;
+using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
- : mFileName( pFile)
+ : mFileName( pFile )
+ , mReader( NULL )
+ , mDataLibrary()
+ , mAccessorLibrary()
+ , mMeshLibrary()
+ , mNodeLibrary()
+ , mImageLibrary()
+ , mEffectLibrary()
+ , mMaterialLibrary()
+ , mLightLibrary()
+ , mCameraLibrary()
+ , mControllerLibrary()
+ , mRootNode( NULL )
+ , mAnims()
+ , mUnitSize( 1.0f )
+ , mUpDirection( UP_Y )
+ , mFormat(FV_1_5_n ) // We assume the newest file format by default
{
- mRootNode = NULL;
- mUnitSize = 1.0f;
- mUpDirection = UP_Z;
-
- // We assume the newest file format by default
- mFormat = FV_1_5_n;
-
- // open the file
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
-
- // generate a XML reader for it
- boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
- mReader = irr::io::createIrrXMLReader( mIOWrapper.get());
- if( !mReader)
- ThrowException( "Collada: Unable to open file.");
-
- // start reading
- ReadContents();
+ // validate io-handler instance
+ if ( NULL == pIOHandler ) {
+ throw DeadlyImportError("IOSystem is NULL." );
+ }
+
+ // open the file
+ std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
+ if (file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open file " + pFile + "." );
+ }
+
+ // generate a XML reader for it
+ std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
+ mReader = irr::io::createIrrXMLReader( mIOWrapper.get());
+ if (!mReader) {
+ ThrowException("Collada: Unable to open file.");
+ }
+
+ // start reading
+ ReadContents();
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ColladaParser::~ColladaParser()
{
- delete mReader;
- for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it)
- delete it->second;
- for( MeshLibrary::iterator it = mMeshLibrary.begin(); it != mMeshLibrary.end(); ++it)
- delete it->second;
+ delete mReader;
+ for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it)
+ delete it->second;
+ for( MeshLibrary::iterator it = mMeshLibrary.begin(); it != mMeshLibrary.end(); ++it)
+ delete it->second;
}
// ------------------------------------------------------------------------------------------------
// Read bool from text contents of current element
bool ColladaParser::ReadBoolFromTextContent()
{
- const char* cur = GetTextContent();
- return (!ASSIMP_strincmp(cur,"true",4) || '0' != *cur);
+ const char* cur = GetTextContent();
+ return (!ASSIMP_strincmp(cur,"true",4) || '0' != *cur);
}
// ------------------------------------------------------------------------------------------------
// Read float from text contents of current element
float ColladaParser::ReadFloatFromTextContent()
{
- const char* cur = GetTextContent();
- return fast_atof(cur);
+ const char* cur = GetTextContent();
+ return fast_atof(cur);
}
// ------------------------------------------------------------------------------------------------
// Reads the contents of the file
void ColladaParser::ReadContents()
{
- while( mReader->read())
- {
- // handle the root element "COLLADA"
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "COLLADA"))
- {
- // check for 'version' attribute
- const int attrib = TestAttribute("version");
- if (attrib != -1) {
- const char* version = mReader->getAttributeValue(attrib);
-
- if (!::strncmp(version,"1.5",3)) {
- mFormat = FV_1_5_n;
- DefaultLogger::get()->debug("Collada schema version is 1.5.n");
- }
- else if (!::strncmp(version,"1.4",3)) {
- mFormat = FV_1_4_n;
- DefaultLogger::get()->debug("Collada schema version is 1.4.n");
- }
- else if (!::strncmp(version,"1.3",3)) {
- mFormat = FV_1_3_n;
- DefaultLogger::get()->debug("Collada schema version is 1.3.n");
- }
- }
+ while( mReader->read())
+ {
+ // handle the root element "COLLADA"
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "COLLADA"))
+ {
+ // check for 'version' attribute
+ const int attrib = TestAttribute("version");
+ if (attrib != -1) {
+ const char* version = mReader->getAttributeValue(attrib);
+
+ if (!::strncmp(version,"1.5",3)) {
+ mFormat = FV_1_5_n;
+ DefaultLogger::get()->debug("Collada schema version is 1.5.n");
+ }
+ else if (!::strncmp(version,"1.4",3)) {
+ mFormat = FV_1_4_n;
+ DefaultLogger::get()->debug("Collada schema version is 1.4.n");
+ }
+ else if (!::strncmp(version,"1.3",3)) {
+ mFormat = FV_1_3_n;
+ DefaultLogger::get()->debug("Collada schema version is 1.3.n");
+ }
+ }
- ReadStructure();
- } else
- {
- DefaultLogger::get()->debug( boost::str( boost::format( "Ignoring global element <%s>.") % mReader->getNodeName()));
- SkipElement();
- }
- } else
- {
- // skip everything else silently
- }
- }
+ ReadStructure();
+ } else
+ {
+ DefaultLogger::get()->debug( format() << "Ignoring global element <" << mReader->getNodeName() << ">." );
+ SkipElement();
+ }
+ } else
+ {
+ // skip everything else silently
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the structure of the file
void ColladaParser::ReadStructure()
{
- while( mReader->read())
- {
- // beginning of elements
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "asset"))
- ReadAssetInfo();
- else if( IsElement( "library_animations"))
- ReadAnimationLibrary();
- else if( IsElement( "library_controllers"))
- ReadControllerLibrary();
- else if( IsElement( "library_images"))
- ReadImageLibrary();
- else if( IsElement( "library_materials"))
- ReadMaterialLibrary();
- else if( IsElement( "library_effects"))
- ReadEffectLibrary();
- else if( IsElement( "library_geometries"))
- ReadGeometryLibrary();
- else if( IsElement( "library_visual_scenes"))
- ReadSceneLibrary();
- else if( IsElement( "library_lights"))
- ReadLightLibrary();
- else if( IsElement( "library_cameras"))
- ReadCameraLibrary();
- else if( IsElement( "library_nodes"))
- ReadSceneNode(NULL); /* some hacking to reuse this piece of code */
- else if( IsElement( "scene"))
- ReadScene();
- else
- SkipElement();
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- break;
- }
- }
+ while( mReader->read())
+ {
+ // beginning of elements
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "asset"))
+ ReadAssetInfo();
+ else if( IsElement( "library_animations"))
+ ReadAnimationLibrary();
+ else if (IsElement("library_animation_clips"))
+ ReadAnimationClipLibrary();
+ else if( IsElement( "library_controllers"))
+ ReadControllerLibrary();
+ else if( IsElement( "library_images"))
+ ReadImageLibrary();
+ else if( IsElement( "library_materials"))
+ ReadMaterialLibrary();
+ else if( IsElement( "library_effects"))
+ ReadEffectLibrary();
+ else if( IsElement( "library_geometries"))
+ ReadGeometryLibrary();
+ else if( IsElement( "library_visual_scenes"))
+ ReadSceneLibrary();
+ else if( IsElement( "library_lights"))
+ ReadLightLibrary();
+ else if( IsElement( "library_cameras"))
+ ReadCameraLibrary();
+ else if( IsElement( "library_nodes"))
+ ReadSceneNode(NULL); /* some hacking to reuse this piece of code */
+ else if( IsElement( "scene"))
+ ReadScene();
+ else
+ SkipElement();
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ break;
+ }
+ }
+
+ PostProcessRootAnimations();
}
// ------------------------------------------------------------------------------------------------
// Reads asset informations such as coordinate system informations and legal blah
void ColladaParser::ReadAssetInfo()
{
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "unit"))
- {
- // read unit data from the element's attributes
- const int attrIndex = TestAttribute( "meter");
- if (attrIndex == -1) {
- mUnitSize = 1.f;
- }
- else {
- mUnitSize = mReader->getAttributeValueAsFloat( attrIndex);
- }
-
- // consume the trailing stuff
- if( !mReader->isEmptyElement())
- SkipElement();
- }
- else if( IsElement( "up_axis"))
- {
- // read content, strip whitespace, compare
- const char* content = GetTextContent();
- if( strncmp( content, "X_UP", 4) == 0)
- mUpDirection = UP_X;
- else if( strncmp( content, "Y_UP", 4) == 0)
- mUpDirection = UP_Y;
- else
- mUpDirection = UP_Z;
-
- // check element end
- TestClosing( "up_axis");
- } else
- {
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "asset") != 0)
- ThrowException( "Expected end of <asset> element.");
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "unit"))
+ {
+ // read unit data from the element's attributes
+ const int attrIndex = TestAttribute( "meter");
+ if (attrIndex == -1) {
+ mUnitSize = 1.f;
+ }
+ else {
+ mUnitSize = mReader->getAttributeValueAsFloat( attrIndex);
+ }
- break;
- }
- }
+ // consume the trailing stuff
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else if( IsElement( "up_axis"))
+ {
+ // read content, strip whitespace, compare
+ const char* content = GetTextContent();
+ if( strncmp( content, "X_UP", 4) == 0)
+ mUpDirection = UP_X;
+ else if( strncmp( content, "Z_UP", 4) == 0)
+ mUpDirection = UP_Z;
+ else
+ mUpDirection = UP_Y;
+
+ // check element end
+ TestClosing( "up_axis");
+ } else
+ {
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "asset") != 0)
+ ThrowException( "Expected end of <asset> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Reads the animation library
-void ColladaParser::ReadAnimationLibrary()
+// Reads the animation clips
+void ColladaParser::ReadAnimationClipLibrary()
{
if (mReader->isEmptyElement())
return;
- while( mReader->read())
+ while (mReader->read())
{
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
- if( IsElement( "animation"))
- {
- // delegate the reading. Depending on the inner elements it will be a container or a anim channel
- ReadAnimation( &mAnims);
- } else
+ if (IsElement("animation_clip"))
+ {
+ // optional name given as an attribute
+ std::string animName;
+ int indexName = TestAttribute("name");
+ int indexID = TestAttribute("id");
+ if (indexName >= 0)
+ animName = mReader->getAttributeValue(indexName);
+ else if (indexID >= 0)
+ animName = mReader->getAttributeValue(indexID);
+ else
+ animName = std::string("animation_") + std::to_string(mAnimationClipLibrary.size());
+
+ std::pair<std::string, std::vector<std::string> > clip;
+
+ clip.first = animName;
+
+ while (mReader->read())
+ {
+ if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if (IsElement("instance_animation"))
+ {
+ int indexUrl = TestAttribute("url");
+ if (indexUrl >= 0)
+ {
+ const char* url = mReader->getAttributeValue(indexUrl);
+ if (url[0] != '#')
+ ThrowException("Unknown reference format");
+
+ url++;
+
+ clip.second.push_back(url);
+ }
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if (strcmp(mReader->getNodeName(), "animation_clip") != 0)
+ ThrowException("Expected end of <animation_clip> element.");
+
+ break;
+ }
+ }
+
+ if (clip.second.size() > 0)
+ {
+ mAnimationClipLibrary.push_back(clip);
+ }
+ }
+ else
{
// ignore the rest
SkipElement();
}
}
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
- if( strcmp( mReader->getNodeName(), "library_animations") != 0)
- ThrowException( "Expected end of <library_animations> element.");
+ if (strcmp(mReader->getNodeName(), "library_animation_clips") != 0)
+ ThrowException("Expected end of <library_animation_clips> element.");
break;
}
@@ -279,113 +361,205 @@ void ColladaParser::ReadAnimationLibrary()
}
// ------------------------------------------------------------------------------------------------
-// Reads an animation into the given parent structure
-void ColladaParser::ReadAnimation( Collada::Animation* pParent)
+// Re-build animations from animation clip library, if present, otherwise combine single-channel animations
+void ColladaParser::PostProcessRootAnimations()
{
- if( mReader->isEmptyElement())
- return;
-
- // an <animation> element may be a container for grouping sub-elements or an animation channel
- // this is the channel collection by ID, in case it has channels
- typedef std::map<std::string, AnimationChannel> ChannelMap;
- ChannelMap channels;
- // this is the anim container in case we're a container
- Animation* anim = NULL;
-
- // optional name given as an attribute
- std::string animName;
- int indexName = TestAttribute( "name");
- int indexID = TestAttribute( "id");
- if( indexName >= 0)
- animName = mReader->getAttributeValue( indexName);
- else if( indexID >= 0)
- animName = mReader->getAttributeValue( indexID);
- else
- animName = "animation";
-
- while( mReader->read())
+ if (mAnimationClipLibrary.size() > 0)
{
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ Animation temp;
+
+ for (AnimationClipLibrary::iterator it = mAnimationClipLibrary.begin(); it != mAnimationClipLibrary.end(); ++it)
{
- // we have subanimations
- if( IsElement( "animation"))
+ std::string clipName = it->first;
+
+ Animation *clip = new Animation();
+ clip->mName = clipName;
+
+ temp.mSubAnims.push_back(clip);
+
+ for (std::vector<std::string>::iterator a = it->second.begin(); a != it->second.end(); ++a)
{
- // create container from our element
- if( !anim)
+ std::string animationID = *a;
+
+ AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
+
+ if (animation != mAnimationLibrary.end())
{
- anim = new Animation;
- anim->mName = animName;
- pParent->mSubAnims.push_back( anim);
- }
+ Animation *pSourceAnimation = animation->second;
- // recurse into the subelement
- ReadAnimation( anim);
- }
- else if( IsElement( "source"))
- {
- // possible animation data - we'll never know. Better store it
- ReadSource();
- }
- else if( IsElement( "sampler"))
- {
- // read the ID to assign the corresponding collada channel afterwards.
- int indexID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( indexID);
- ChannelMap::iterator newChannel = channels.insert( std::make_pair( id, AnimationChannel())).first;
-
- // have it read into a channel
- ReadAnimationSampler( newChannel->second);
- }
- else if( IsElement( "channel"))
- {
- // the binding element whose whole purpose is to provide the target to animate
- // Thanks, Collada! A directly posted information would have been too simple, I guess.
- // Better add another indirection to that! Can't have enough of those.
- int indexTarget = GetAttribute( "target");
- int indexSource = GetAttribute( "source");
- const char* sourceId = mReader->getAttributeValue( indexSource);
- if( sourceId[0] == '#')
- sourceId++;
- ChannelMap::iterator cit = channels.find( sourceId);
- if( cit != channels.end())
- cit->second.mTarget = mReader->getAttributeValue( indexTarget);
-
- if( !mReader->isEmptyElement())
- SkipElement();
- }
- else
- {
- // ignore the rest
- SkipElement();
+ pSourceAnimation->CollectChannelsRecursively(clip->mChannels);
+ }
}
}
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "animation") != 0)
- ThrowException( "Expected end of <animation> element.");
- break;
- }
- }
+ mAnims = temp;
- // it turned out to have channels - add them
- if( !channels.empty())
+ // Ensure no double deletes.
+ temp.mSubAnims.clear();
+ }
+ else
{
- // special filtering for stupid exporters packing each channel into a separate animation
- if( channels.size() == 1)
- {
- pParent->mChannels.push_back( channels.begin()->second);
- } else
- {
- // else create the animation, if not done yet, and store the channels
- if( !anim)
+ mAnims.CombineSingleChannelAnimations();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads the animation library
+void ColladaParser::ReadAnimationLibrary()
+{
+ if (mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "animation"))
+ {
+ // delegate the reading. Depending on the inner elements it will be a container or a anim channel
+ ReadAnimation( &mAnims);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "library_animations") != 0)
+ ThrowException( "Expected end of <library_animations> element.");
+
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads an animation into the given parent structure
+void ColladaParser::ReadAnimation( Collada::Animation* pParent)
+{
+ if( mReader->isEmptyElement())
+ return;
+
+ // an <animation> element may be a container for grouping sub-elements or an animation channel
+ // this is the channel collection by ID, in case it has channels
+ typedef std::map<std::string, AnimationChannel> ChannelMap;
+ ChannelMap channels;
+ // this is the anim container in case we're a container
+ Animation* anim = NULL;
+
+ // optional name given as an attribute
+ std::string animName;
+ std::string animID;
+ int indexName = TestAttribute( "name");
+ int indexID = TestAttribute( "id");
+
+ if (indexID >= 0)
+ animID = mReader->getAttributeValue(indexID);
+
+ if( indexName >= 0)
+ animName = mReader->getAttributeValue( indexName);
+ else if( indexID >= 0)
+ animName = animID;
+ else
+ animName = "animation";
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // we have subanimations
+ if( IsElement( "animation"))
+ {
+ // create container from our element
+ if( !anim)
+ {
+ anim = new Animation;
+ anim->mName = animName;
+ pParent->mSubAnims.push_back( anim);
+ }
+
+ // recurse into the subelement
+ ReadAnimation( anim);
+ }
+ else if( IsElement( "source"))
+ {
+ // possible animation data - we'll never know. Better store it
+ ReadSource();
+ }
+ else if( IsElement( "sampler"))
+ {
+ // read the ID to assign the corresponding collada channel afterwards.
+ int indexID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( indexID);
+ ChannelMap::iterator newChannel = channels.insert( std::make_pair( id, AnimationChannel())).first;
+
+ // have it read into a channel
+ ReadAnimationSampler( newChannel->second);
+ }
+ else if( IsElement( "channel"))
+ {
+ // the binding element whose whole purpose is to provide the target to animate
+ // Thanks, Collada! A directly posted information would have been too simple, I guess.
+ // Better add another indirection to that! Can't have enough of those.
+ int indexTarget = GetAttribute( "target");
+ int indexSource = GetAttribute( "source");
+ const char* sourceId = mReader->getAttributeValue( indexSource);
+ if( sourceId[0] == '#')
+ sourceId++;
+ ChannelMap::iterator cit = channels.find( sourceId);
+ if( cit != channels.end())
+ cit->second.mTarget = mReader->getAttributeValue( indexTarget);
+
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "animation") != 0)
+ ThrowException( "Expected end of <animation> element.");
+
+ break;
+ }
+ }
+
+ // it turned out to have channels - add them
+ if( !channels.empty())
+ {
+ // FIXME: Is this essentially doing the same as "single-anim-node" codepath in
+ // ColladaLoader::StoreAnimations? For now, this has been deferred to after
+ // all animations and all clips have been read. Due to handling of
+ // <library_animation_clips> this cannot be done here, as the channel owner
+ // is lost, and some exporters make up animations by referring to multiple
+ // single-channel animations from an <instance_animation>.
+/*
+ // special filtering for stupid exporters packing each channel into a separate animation
+ if( channels.size() == 1)
+ {
+ pParent->mChannels.push_back( channels.begin()->second);
+ } else
+*/
+ {
+ // else create the animation, if not done yet, and store the channels
+ if( !anim)
+ {
+ anim = new Animation;
+ anim->mName = animName;
+ pParent->mSubAnims.push_back( anim);
+ }
+ for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
+ anim->mChannels.push_back( it->second);
+
+ if (indexID >= 0)
{
- anim = new Animation;
- anim->mName = animName;
- pParent->mSubAnims.push_back( anim);
+ mAnimationLibrary[animID] = anim;
}
- for( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it)
- anim->mChannels.push_back( it->second);
}
}
}
@@ -394,24 +568,24 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent)
// Reads an animation sampler into the given anim channel
void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "input"))
- {
- int indexSemantic = GetAttribute( "semantic");
- const char* semantic = mReader->getAttributeValue( indexSemantic);
- int indexSource = GetAttribute( "source");
- const char* source = mReader->getAttributeValue( indexSource);
- if( source[0] != '#')
- ThrowException( "Unsupported URL format");
- source++;
-
- if( strcmp( semantic, "INPUT") == 0)
- pChannel.mSourceTimes = source;
- else if( strcmp( semantic, "OUTPUT") == 0)
- pChannel.mSourceValues = source;
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "input"))
+ {
+ int indexSemantic = GetAttribute( "semantic");
+ const char* semantic = mReader->getAttributeValue( indexSemantic);
+ int indexSource = GetAttribute( "source");
+ const char* source = mReader->getAttributeValue( indexSource);
+ if( source[0] != '#')
+ ThrowException( "Unsupported URL format");
+ source++;
+
+ if( strcmp( semantic, "INPUT") == 0)
+ pChannel.mSourceTimes = source;
+ else if( strcmp( semantic, "OUTPUT") == 0)
+ pChannel.mSourceValues = source;
else if( strcmp( semantic, "IN_TANGENT") == 0)
pChannel.mInTanValues = source;
else if( strcmp( semantic, "OUT_TANGENT") == 0)
@@ -419,61 +593,61 @@ void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel)
else if( strcmp( semantic, "INTERPOLATION") == 0)
pChannel.mInterpolationValues = source;
- if( !mReader->isEmptyElement())
- SkipElement();
- }
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "sampler") != 0)
- ThrowException( "Expected end of <sampler> element.");
-
- break;
- }
- }
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "sampler") != 0)
+ ThrowException( "Expected end of <sampler> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the skeleton controller library
void ColladaParser::ReadControllerLibrary()
{
- if (mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "controller"))
- {
- // read ID. Ask the spec if it's neccessary or optional... you might be surprised.
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
+ if (mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "controller"))
+ {
+ // read ID. Ask the spec if it's necessary or optional... you might be surprised.
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- // create an entry and store it in the library under its ID
- mControllerLibrary[id] = Controller();
+ // create an entry and store it in the library under its ID
+ mControllerLibrary[id] = Controller();
- // read on from there
- ReadController( mControllerLibrary[id]);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "library_controllers") != 0)
- ThrowException( "Expected end of <library_controllers> element.");
-
- break;
- }
- }
+ // read on from there
+ ReadController( mControllerLibrary[id]);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "library_controllers") != 0)
+ ThrowException( "Expected end of <library_controllers> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -483,13 +657,13 @@ void ColladaParser::ReadController( Collada::Controller& pController)
// initial values
pController.mType = Skin;
pController.mMethod = Normalized;
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
- if( IsElement( "morph"))
- {
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
+ if( IsElement( "morph"))
+ {
pController.mType = Morph;
int baseIndex = GetAttribute("source");
pController.mMeshId = mReader->getAttributeValue(baseIndex) + 1;
@@ -499,35 +673,35 @@ void ColladaParser::ReadController( Collada::Controller& pController)
if (strcmp(method, "RELATIVE") == 0)
pController.mMethod = Relative;
}
- }
- else if( IsElement( "skin"))
- {
- // read the mesh it refers to. According to the spec this could also be another
- // controller, but I refuse to implement every single idea they've come up with
- int sourceIndex = GetAttribute( "source");
- pController.mMeshId = mReader->getAttributeValue( sourceIndex) + 1;
- }
- else if( IsElement( "bind_shape_matrix"))
- {
- // content is 16 floats to define a matrix... it seems to be important for some models
- const char* content = GetTextContent();
-
- // read the 16 floats
- for( unsigned int a = 0; a < 16; a++)
- {
- // read a number
- content = fast_atoreal_move<float>( content, pController.mBindShapeMatrix[a]);
- // skip whitespace after it
- SkipSpacesAndLineEnd( &content);
- }
-
- TestClosing( "bind_shape_matrix");
- }
+ }
+ else if( IsElement( "skin"))
+ {
+ // read the mesh it refers to. According to the spec this could also be another
+ // controller, but I refuse to implement every single idea they've come up with
+ int sourceIndex = GetAttribute( "source");
+ pController.mMeshId = mReader->getAttributeValue( sourceIndex) + 1;
+ }
+ else if( IsElement( "bind_shape_matrix"))
+ {
+ // content is 16 floats to define a matrix... it seems to be important for some models
+ const char* content = GetTextContent();
+
+ // read the 16 floats
+ for( unsigned int a = 0; a < 16; a++)
+ {
+ // read a number
+ content = fast_atoreal_move<float>( content, pController.mBindShapeMatrix[a]);
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
+
+ TestClosing( "bind_shape_matrix");
+ }
else if( IsElement( "source"))
{
// data array - we have specialists to handle this
ReadSource();
- }
+ }
else if( IsElement( "joints"))
{
ReadControllerJoints( pController);
@@ -535,14 +709,14 @@ void ColladaParser::ReadController( Collada::Controller& pController)
else if( IsElement( "vertex_weights"))
{
ReadControllerWeights( pController);
- }
- else if ( IsElement( "targets" ))
- {
- while (mReader->read()) {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if ( IsElement( "input")) {
- int semanticsIndex = GetAttribute("semantic");
- int sourceIndex = GetAttribute("source");
+ }
+ else if ( IsElement( "targets" ))
+ {
+ while (mReader->read()) {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if ( IsElement( "input")) {
+ int semanticsIndex = GetAttribute("semantic");
+ int sourceIndex = GetAttribute("source");
const char *semantics = mReader->getAttributeValue(semanticsIndex);
const char *source = mReader->getAttributeValue(sourceIndex);
@@ -562,979 +736,1052 @@ void ColladaParser::ReadController( Collada::Controller& pController)
}
}
}
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "controller") == 0)
- break;
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "controller") == 0)
+ break;
else if( strcmp( mReader->getNodeName(), "skin") != 0 && strcmp( mReader->getNodeName(), "morph") != 0)
- ThrowException( "Expected end of <controller> element.");
- }
- }
+ ThrowException( "Expected end of <controller> element.");
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the joint definitions for the given controller
void ColladaParser::ReadControllerJoints( Collada::Controller& pController)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
- if( IsElement( "input"))
- {
- int indexSemantic = GetAttribute( "semantic");
- const char* attrSemantic = mReader->getAttributeValue( indexSemantic);
- int indexSource = GetAttribute( "source");
- const char* attrSource = mReader->getAttributeValue( indexSource);
-
- // local URLS always start with a '#'. We don't support global URLs
- if( attrSource[0] != '#')
- ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\" in source attribute of <joints> data <input> element") % attrSource));
- attrSource++;
-
- // parse source URL to corresponding source
- if( strcmp( attrSemantic, "JOINT") == 0)
- pController.mJointNameSource = attrSource;
- else if( strcmp( attrSemantic, "INV_BIND_MATRIX") == 0)
- pController.mJointOffsetMatrixSource = attrSource;
- else
- ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in <joints> data <input> element") % attrSemantic));
-
- // skip inner data, if present
- if( !mReader->isEmptyElement())
- SkipElement();
- }
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "joints") != 0)
- ThrowException( "Expected end of <joints> element.");
-
- break;
- }
- }
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX"
+ if( IsElement( "input"))
+ {
+ int indexSemantic = GetAttribute( "semantic");
+ const char* attrSemantic = mReader->getAttributeValue( indexSemantic);
+ int indexSource = GetAttribute( "source");
+ const char* attrSource = mReader->getAttributeValue( indexSource);
+
+ // local URLS always start with a '#'. We don't support global URLs
+ if( attrSource[0] != '#')
+ ThrowException( format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <joints> data <input> element" );
+ attrSource++;
+
+ // parse source URL to corresponding source
+ if( strcmp( attrSemantic, "JOINT") == 0)
+ pController.mJointNameSource = attrSource;
+ else if( strcmp( attrSemantic, "INV_BIND_MATRIX") == 0)
+ pController.mJointOffsetMatrixSource = attrSource;
+ else
+ ThrowException( format() << "Unknown semantic \"" << attrSemantic << "\" in <joints> data <input> element" );
+
+ // skip inner data, if present
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "joints") != 0)
+ ThrowException( "Expected end of <joints> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the joint weights for the given controller
void ColladaParser::ReadControllerWeights( Collada::Controller& pController)
{
- // read vertex count from attributes and resize the array accordingly
- int indexCount = GetAttribute( "count");
- size_t vertexCount = (size_t) mReader->getAttributeValueAsInt( indexCount);
- pController.mWeightCounts.resize( vertexCount);
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- // Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT"
- if( IsElement( "input") && vertexCount > 0 )
- {
- InputChannel channel;
-
- int indexSemantic = GetAttribute( "semantic");
- const char* attrSemantic = mReader->getAttributeValue( indexSemantic);
- int indexSource = GetAttribute( "source");
- const char* attrSource = mReader->getAttributeValue( indexSource);
- int indexOffset = TestAttribute( "offset");
- if( indexOffset >= 0)
- channel.mOffset = mReader->getAttributeValueAsInt( indexOffset);
-
- // local URLS always start with a '#'. We don't support global URLs
- if( attrSource[0] != '#')
- ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\" in source attribute of <vertex_weights> data <input> element") % attrSource));
- channel.mAccessor = attrSource + 1;
-
- // parse source URL to corresponding source
- if( strcmp( attrSemantic, "JOINT") == 0)
- pController.mWeightInputJoints = channel;
- else if( strcmp( attrSemantic, "WEIGHT") == 0)
- pController.mWeightInputWeights = channel;
- else
- ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in <vertex_weights> data <input> element") % attrSemantic));
-
- // skip inner data, if present
- if( !mReader->isEmptyElement())
- SkipElement();
- }
- else if( IsElement( "vcount") && vertexCount > 0 )
- {
- // read weight count per vertex
- const char* text = GetTextContent();
- size_t numWeights = 0;
- for( std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it)
- {
- if( *text == 0)
- ThrowException( "Out of data while reading <vcount>");
-
- *it = strtoul10( text, &text);
- numWeights += *it;
- SkipSpacesAndLineEnd( &text);
- }
+ // read vertex count from attributes and resize the array accordingly
+ int indexCount = GetAttribute( "count");
+ size_t vertexCount = (size_t) mReader->getAttributeValueAsInt( indexCount);
+ pController.mWeightCounts.resize( vertexCount);
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT"
+ if( IsElement( "input") && vertexCount > 0 )
+ {
+ InputChannel channel;
+
+ int indexSemantic = GetAttribute( "semantic");
+ const char* attrSemantic = mReader->getAttributeValue( indexSemantic);
+ int indexSource = GetAttribute( "source");
+ const char* attrSource = mReader->getAttributeValue( indexSource);
+ int indexOffset = TestAttribute( "offset");
+ if( indexOffset >= 0)
+ channel.mOffset = mReader->getAttributeValueAsInt( indexOffset);
+
+ // local URLS always start with a '#'. We don't support global URLs
+ if( attrSource[0] != '#')
+ ThrowException( format() << "Unsupported URL format in \"" << attrSource << "\" in source attribute of <vertex_weights> data <input> element" );
+ channel.mAccessor = attrSource + 1;
+
+ // parse source URL to corresponding source
+ if( strcmp( attrSemantic, "JOINT") == 0)
+ pController.mWeightInputJoints = channel;
+ else if( strcmp( attrSemantic, "WEIGHT") == 0)
+ pController.mWeightInputWeights = channel;
+ else
+ ThrowException( format() << "Unknown semantic \"" << attrSemantic << "\" in <vertex_weights> data <input> element" );
+
+ // skip inner data, if present
+ if( !mReader->isEmptyElement())
+ SkipElement();
+ }
+ else if( IsElement( "vcount") && vertexCount > 0 )
+ {
+ // read weight count per vertex
+ const char* text = GetTextContent();
+ size_t numWeights = 0;
+ for( std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it)
+ {
+ if( *text == 0)
+ ThrowException( "Out of data while reading <vcount>");
- TestClosing( "vcount");
+ *it = strtoul10( text, &text);
+ numWeights += *it;
+ SkipSpacesAndLineEnd( &text);
+ }
- // reserve weight count
- pController.mWeights.resize( numWeights);
- }
- else if( IsElement( "v") && vertexCount > 0 )
- {
- // read JointIndex - WeightIndex pairs
- const char* text = GetTextContent();
+ TestClosing( "vcount");
- for( std::vector< std::pair<size_t, size_t> >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it)
- {
- if( *text == 0)
- ThrowException( "Out of data while reading <vertex_weights>");
- it->first = strtoul10( text, &text);
- SkipSpacesAndLineEnd( &text);
- if( *text == 0)
- ThrowException( "Out of data while reading <vertex_weights>");
- it->second = strtoul10( text, &text);
- SkipSpacesAndLineEnd( &text);
- }
+ // reserve weight count
+ pController.mWeights.resize( numWeights);
+ }
+ else if( IsElement( "v") && vertexCount > 0 )
+ {
+ // read JointIndex - WeightIndex pairs
+ const char* text = GetTextContent();
- TestClosing( "v");
- }
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "vertex_weights") != 0)
- ThrowException( "Expected end of <vertex_weights> element.");
+ for( std::vector< std::pair<size_t, size_t> >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it)
+ {
+ if( *text == 0)
+ ThrowException( "Out of data while reading <vertex_weights>");
+ it->first = strtoul10( text, &text);
+ SkipSpacesAndLineEnd( &text);
+ if( *text == 0)
+ ThrowException( "Out of data while reading <vertex_weights>");
+ it->second = strtoul10( text, &text);
+ SkipSpacesAndLineEnd( &text);
+ }
- break;
- }
- }
+ TestClosing( "v");
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "vertex_weights") != 0)
+ ThrowException( "Expected end of <vertex_weights> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the image library contents
void ColladaParser::ReadImageLibrary()
{
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "image"))
- {
- // read ID. Another entry which is "optional" by design but obligatory in reality
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
+ if( mReader->isEmptyElement())
+ return;
- // create an entry and store it in the library under its ID
- mImageLibrary[id] = Image();
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "image"))
+ {
+ // read ID. Another entry which is "optional" by design but obligatory in reality
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- // read on from there
- ReadImage( mImageLibrary[id]);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "library_images") != 0)
- ThrowException( "Expected end of <library_images> element.");
+ // create an entry and store it in the library under its ID
+ mImageLibrary[id] = Image();
- break;
- }
- }
+ // read on from there
+ ReadImage( mImageLibrary[id]);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "library_images") != 0)
+ ThrowException( "Expected end of <library_images> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads an image entry into the given image
void ColladaParser::ReadImage( Collada::Image& pImage)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT){
- // Need to run different code paths here, depending on the Collada XSD version
- if (IsElement("image")) {
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT){
+ // Need to run different code paths here, depending on the Collada XSD version
+ if (IsElement("image")) {
SkipElement();
}
- else if( IsElement( "init_from"))
- {
- if (mFormat == FV_1_4_n)
- {
- // FIX: C4D exporter writes empty <init_from/> tags
- if (!mReader->isEmptyElement()) {
- // element content is filename - hopefully
- const char* sz = TestTextContent();
- if (sz)pImage.mFileName = sz;
- TestClosing( "init_from");
- }
- if (!pImage.mFileName.length()) {
- pImage.mFileName = "unknown_texture";
- }
- }
- else if (mFormat == FV_1_5_n)
- {
- // make sure we skip over mip and array initializations, which
- // we don't support, but which could confuse the loader if
- // they're not skipped.
- int attrib = TestAttribute("array_index");
- if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
- DefaultLogger::get()->warn("Collada: Ignoring texture array index");
- continue;
- }
+ else if( IsElement( "init_from"))
+ {
+ if (mFormat == FV_1_4_n)
+ {
+ // FIX: C4D exporter writes empty <init_from/> tags
+ if (!mReader->isEmptyElement()) {
+ // element content is filename - hopefully
+ const char* sz = TestTextContent();
+ if (sz)pImage.mFileName = sz;
+ TestClosing( "init_from");
+ }
+ if (!pImage.mFileName.length()) {
+ pImage.mFileName = "unknown_texture";
+ }
+ }
+ else if (mFormat == FV_1_5_n)
+ {
+ // make sure we skip over mip and array initializations, which
+ // we don't support, but which could confuse the loader if
+ // they're not skipped.
+ int attrib = TestAttribute("array_index");
+ if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
+ DefaultLogger::get()->warn("Collada: Ignoring texture array index");
+ continue;
+ }
- attrib = TestAttribute("mip_index");
- if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
- DefaultLogger::get()->warn("Collada: Ignoring MIP map layer");
- continue;
- }
+ attrib = TestAttribute("mip_index");
+ if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
+ DefaultLogger::get()->warn("Collada: Ignoring MIP map layer");
+ continue;
+ }
- // TODO: correctly jump over cube and volume maps?
- }
- }
- else if (mFormat == FV_1_5_n)
- {
- if( IsElement( "ref"))
- {
- // element content is filename - hopefully
- const char* sz = TestTextContent();
- if (sz)pImage.mFileName = sz;
- TestClosing( "ref");
- }
- else if( IsElement( "hex") && !pImage.mFileName.length())
- {
- // embedded image. get format
- const int attrib = TestAttribute("format");
- if (-1 == attrib)
- DefaultLogger::get()->warn("Collada: Unknown image file format");
- else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
-
- const char* data = GetTextContent();
-
- // hexadecimal-encoded binary octets. First of all, find the
- // required buffer size to reserve enough storage.
- const char* cur = data;
- while (!IsSpaceOrNewLine(*cur)) cur++;
-
- const unsigned int size = (unsigned int)(cur-data) * 2;
- pImage.mImageData.resize(size);
- for (unsigned int i = 0; i < size;++i)
- pImage.mImageData[i] = HexOctetToDecimal(data+(i<<1));
-
- TestClosing( "hex");
- }
- }
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "image") == 0)
- break;
- }
- }
+ // TODO: correctly jump over cube and volume maps?
+ }
+ }
+ else if (mFormat == FV_1_5_n)
+ {
+ if( IsElement( "ref"))
+ {
+ // element content is filename - hopefully
+ const char* sz = TestTextContent();
+ if (sz)pImage.mFileName = sz;
+ TestClosing( "ref");
+ }
+ else if( IsElement( "hex") && !pImage.mFileName.length())
+ {
+ // embedded image. get format
+ const int attrib = TestAttribute("format");
+ if (-1 == attrib)
+ DefaultLogger::get()->warn("Collada: Unknown image file format");
+ else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
+
+ const char* data = GetTextContent();
+
+ // hexadecimal-encoded binary octets. First of all, find the
+ // required buffer size to reserve enough storage.
+ const char* cur = data;
+ while (!IsSpaceOrNewLine(*cur)) cur++;
+
+ const unsigned int size = (unsigned int)(cur-data) * 2;
+ pImage.mImageData.resize(size);
+ for (unsigned int i = 0; i < size;++i)
+ pImage.mImageData[i] = HexOctetToDecimal(data+(i<<1));
+
+ TestClosing( "hex");
+ }
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "image") == 0)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the material library
void ColladaParser::ReadMaterialLibrary()
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
+
+ std::map<std::string, int> names;
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "material"))
+ {
+ // read ID. By now you probably know my opinion about this "specification"
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "material"))
- {
- // read ID. By now you propably know my opinion about this "specification"
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
+ std::string name;
+ int attrName = TestAttribute("name");
+ if (attrName >= 0)
+ name = mReader->getAttributeValue( attrName);
- // create an entry and store it in the library under its ID
- ReadMaterial(mMaterialLibrary[id] = Material());
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "library_materials") != 0)
- ThrowException( "Expected end of <library_materials> element.");
+ // create an entry and store it in the library under its ID
+ mMaterialLibrary[id] = Material();
- break;
- }
- }
+ if( !name.empty())
+ {
+ std::map<std::string, int>::iterator it = names.find( name);
+ if( it != names.end())
+ {
+ std::ostringstream strStream;
+ strStream << ++it->second;
+ name.append( " " + strStream.str());
+ }
+ else
+ {
+ names[name] = 0;
+ }
+
+ mMaterialLibrary[id].mName = name;
+ }
+
+ ReadMaterial( mMaterialLibrary[id]);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "library_materials") != 0)
+ ThrowException( "Expected end of <library_materials> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the light library
void ColladaParser::ReadLightLibrary()
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "light"))
- {
- // read ID. By now you propably know my opinion about this "specification"
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "light"))
+ {
+ // read ID. By now you probably know my opinion about this "specification"
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- // create an entry and store it in the library under its ID
- ReadLight(mLightLibrary[id] = Light());
+ // create an entry and store it in the library under its ID
+ ReadLight(mLightLibrary[id] = Light());
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "library_lights") != 0)
- ThrowException( "Expected end of <library_lights> element.");
-
- break;
- }
- }
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "library_lights") != 0)
+ ThrowException( "Expected end of <library_lights> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the camera library
void ColladaParser::ReadCameraLibrary()
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "camera"))
- {
- // read ID. By now you propably know my opinion about this "specification"
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
-
- // create an entry and store it in the library under its ID
- Camera& cam = mCameraLibrary[id];
- attrID = TestAttribute( "name");
- if (attrID != -1)
- cam.mName = mReader->getAttributeValue( attrID);
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "camera"))
+ {
+ // read ID. By now you probably know my opinion about this "specification"
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- ReadCamera(cam);
+ // create an entry and store it in the library under its ID
+ Camera& cam = mCameraLibrary[id];
+ attrID = TestAttribute( "name");
+ if (attrID != -1)
+ cam.mName = mReader->getAttributeValue( attrID);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "library_cameras") != 0)
- ThrowException( "Expected end of <library_cameras> element.");
+ ReadCamera(cam);
- break;
- }
- }
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "library_cameras") != 0)
+ ThrowException( "Expected end of <library_cameras> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a material entry into the given material
void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if (IsElement("material")) {
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if (IsElement("material")) {
SkipElement();
}
- else if( IsElement( "instance_effect"))
- {
- // referred effect by URL
- int attrUrl = GetAttribute( "url");
- const char* url = mReader->getAttributeValue( attrUrl);
- if( url[0] != '#')
- ThrowException( "Unknown reference format");
+ else if( IsElement( "instance_effect"))
+ {
+ // referred effect by URL
+ int attrUrl = GetAttribute( "url");
+ const char* url = mReader->getAttributeValue( attrUrl);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format");
- pMaterial.mEffect = url+1;
+ pMaterial.mEffect = url+1;
- SkipElement();
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "material") != 0)
- ThrowException( "Expected end of <material> element.");
-
- break;
- }
- }
+ SkipElement();
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "material") != 0)
+ ThrowException( "Expected end of <material> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a light entry into the given light
void ColladaParser::ReadLight( Collada::Light& pLight)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
if (IsElement("light")) {
SkipElement();
}
- else if (IsElement("spot")) {
- pLight.mType = aiLightSource_SPOT;
- }
- else if (IsElement("ambient")) {
- pLight.mType = aiLightSource_AMBIENT;
- }
- else if (IsElement("directional")) {
- pLight.mType = aiLightSource_DIRECTIONAL;
- }
- else if (IsElement("point")) {
- pLight.mType = aiLightSource_POINT;
- }
- else if (IsElement("color")) {
- // text content contains 3 floats
- const char* content = GetTextContent();
-
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.r);
- SkipSpacesAndLineEnd( &content);
-
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.g);
- SkipSpacesAndLineEnd( &content);
-
- content = fast_atoreal_move<float>( content, (float&)pLight.mColor.b);
- SkipSpacesAndLineEnd( &content);
-
- TestClosing( "color");
- }
- else if (IsElement("constant_attenuation")) {
- pLight.mAttConstant = ReadFloatFromTextContent();
- TestClosing("constant_attenuation");
- }
- else if (IsElement("linear_attenuation")) {
- pLight.mAttLinear = ReadFloatFromTextContent();
- TestClosing("linear_attenuation");
- }
- else if (IsElement("quadratic_attenuation")) {
- pLight.mAttQuadratic = ReadFloatFromTextContent();
- TestClosing("quadratic_attenuation");
- }
- else if (IsElement("falloff_angle")) {
- pLight.mFalloffAngle = ReadFloatFromTextContent();
- TestClosing("falloff_angle");
- }
- else if (IsElement("falloff_exponent")) {
- pLight.mFalloffExponent = ReadFloatFromTextContent();
- TestClosing("falloff_exponent");
- }
- // FCOLLADA extensions
- // -------------------------------------------------------
- else if (IsElement("outer_cone")) {
- pLight.mOuterAngle = ReadFloatFromTextContent();
- TestClosing("outer_cone");
- }
- // ... and this one is even deprecated
- else if (IsElement("penumbra_angle")) {
- pLight.mPenumbraAngle = ReadFloatFromTextContent();
- TestClosing("penumbra_angle");
- }
- else if (IsElement("intensity")) {
- pLight.mIntensity = ReadFloatFromTextContent();
- TestClosing("intensity");
- }
- else if (IsElement("falloff")) {
- pLight.mOuterAngle = ReadFloatFromTextContent();
- TestClosing("falloff");
- }
- else if (IsElement("hotspot_beam")) {
- pLight.mFalloffAngle = ReadFloatFromTextContent();
- TestClosing("hotspot_beam");
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "light") == 0)
- break;
- }
- }
+ else if (IsElement("spot")) {
+ pLight.mType = aiLightSource_SPOT;
+ }
+ else if (IsElement("ambient")) {
+ pLight.mType = aiLightSource_AMBIENT;
+ }
+ else if (IsElement("directional")) {
+ pLight.mType = aiLightSource_DIRECTIONAL;
+ }
+ else if (IsElement("point")) {
+ pLight.mType = aiLightSource_POINT;
+ }
+ else if (IsElement("color")) {
+ // text content contains 3 floats
+ const char* content = GetTextContent();
+
+ content = fast_atoreal_move<float>( content, (float&)pLight.mColor.r);
+ SkipSpacesAndLineEnd( &content);
+
+ content = fast_atoreal_move<float>( content, (float&)pLight.mColor.g);
+ SkipSpacesAndLineEnd( &content);
+
+ content = fast_atoreal_move<float>( content, (float&)pLight.mColor.b);
+ SkipSpacesAndLineEnd( &content);
+
+ TestClosing( "color");
+ }
+ else if (IsElement("constant_attenuation")) {
+ pLight.mAttConstant = ReadFloatFromTextContent();
+ TestClosing("constant_attenuation");
+ }
+ else if (IsElement("linear_attenuation")) {
+ pLight.mAttLinear = ReadFloatFromTextContent();
+ TestClosing("linear_attenuation");
+ }
+ else if (IsElement("quadratic_attenuation")) {
+ pLight.mAttQuadratic = ReadFloatFromTextContent();
+ TestClosing("quadratic_attenuation");
+ }
+ else if (IsElement("falloff_angle")) {
+ pLight.mFalloffAngle = ReadFloatFromTextContent();
+ TestClosing("falloff_angle");
+ }
+ else if (IsElement("falloff_exponent")) {
+ pLight.mFalloffExponent = ReadFloatFromTextContent();
+ TestClosing("falloff_exponent");
+ }
+ // FCOLLADA extensions
+ // -------------------------------------------------------
+ else if (IsElement("outer_cone")) {
+ pLight.mOuterAngle = ReadFloatFromTextContent();
+ TestClosing("outer_cone");
+ }
+ // ... and this one is even deprecated
+ else if (IsElement("penumbra_angle")) {
+ pLight.mPenumbraAngle = ReadFloatFromTextContent();
+ TestClosing("penumbra_angle");
+ }
+ else if (IsElement("intensity")) {
+ pLight.mIntensity = ReadFloatFromTextContent();
+ TestClosing("intensity");
+ }
+ else if (IsElement("falloff")) {
+ pLight.mOuterAngle = ReadFloatFromTextContent();
+ TestClosing("falloff");
+ }
+ else if (IsElement("hotspot_beam")) {
+ pLight.mFalloffAngle = ReadFloatFromTextContent();
+ TestClosing("hotspot_beam");
+ }
+ // OpenCOLLADA extensions
+ // -------------------------------------------------------
+ else if (IsElement("decay_falloff")) {
+ pLight.mOuterAngle = ReadFloatFromTextContent();
+ TestClosing("decay_falloff");
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "light") == 0)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a camera entry into the given light
void ColladaParser::ReadCamera( Collada::Camera& pCamera)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if (IsElement("camera")) {
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if (IsElement("camera")) {
SkipElement();
}
- else if (IsElement("orthographic")) {
- pCamera.mOrtho = true;
- }
- else if (IsElement("xfov") || IsElement("xmag")) {
- pCamera.mHorFov = ReadFloatFromTextContent();
- TestClosing((pCamera.mOrtho ? "xmag" : "xfov"));
- }
- else if (IsElement("yfov") || IsElement("ymag")) {
- pCamera.mVerFov = ReadFloatFromTextContent();
- TestClosing((pCamera.mOrtho ? "ymag" : "yfov"));
- }
- else if (IsElement("aspect_ratio")) {
- pCamera.mAspect = ReadFloatFromTextContent();
- TestClosing("aspect_ratio");
- }
- else if (IsElement("znear")) {
- pCamera.mZNear = ReadFloatFromTextContent();
- TestClosing("znear");
- }
- else if (IsElement("zfar")) {
- pCamera.mZFar = ReadFloatFromTextContent();
- TestClosing("zfar");
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "camera") == 0)
- break;
- }
- }
+ else if (IsElement("orthographic")) {
+ pCamera.mOrtho = true;
+ }
+ else if (IsElement("xfov") || IsElement("xmag")) {
+ pCamera.mHorFov = ReadFloatFromTextContent();
+ TestClosing((pCamera.mOrtho ? "xmag" : "xfov"));
+ }
+ else if (IsElement("yfov") || IsElement("ymag")) {
+ pCamera.mVerFov = ReadFloatFromTextContent();
+ TestClosing((pCamera.mOrtho ? "ymag" : "yfov"));
+ }
+ else if (IsElement("aspect_ratio")) {
+ pCamera.mAspect = ReadFloatFromTextContent();
+ TestClosing("aspect_ratio");
+ }
+ else if (IsElement("znear")) {
+ pCamera.mZNear = ReadFloatFromTextContent();
+ TestClosing("znear");
+ }
+ else if (IsElement("zfar")) {
+ pCamera.mZFar = ReadFloatFromTextContent();
+ TestClosing("zfar");
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "camera") == 0)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the effect library
void ColladaParser::ReadEffectLibrary()
{
- if (mReader->isEmptyElement()) {
- return;
- }
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "effect"))
- {
- // read ID. Do I have to repeat my ranting about "optional" attributes?
- int attrID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( attrID);
-
- // create an entry and store it in the library under its ID
- mEffectLibrary[id] = Effect();
- // read on from there
- ReadEffect( mEffectLibrary[id]);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "library_effects") != 0)
- ThrowException( "Expected end of <library_effects> element.");
-
- break;
- }
- }
+ if (mReader->isEmptyElement()) {
+ return;
+ }
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "effect"))
+ {
+ // read ID. Do I have to repeat my ranting about "optional" attributes?
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
+
+ // create an entry and store it in the library under its ID
+ mEffectLibrary[id] = Effect();
+ // read on from there
+ ReadEffect( mEffectLibrary[id]);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "library_effects") != 0)
+ ThrowException( "Expected end of <library_effects> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry into the given effect
void ColladaParser::ReadEffect( Collada::Effect& pEffect)
{
- // for the moment we don't support any other type of effect.
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "profile_COMMON"))
- ReadEffectProfileCommon( pEffect);
- else
- SkipElement();
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "effect") != 0)
- ThrowException( "Expected end of <effect> element.");
-
- break;
- }
- }
+ // for the moment we don't support any other type of effect.
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "profile_COMMON"))
+ ReadEffectProfileCommon( pEffect);
+ else
+ SkipElement();
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "effect") != 0)
+ ThrowException( "Expected end of <effect> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads an COMMON effect profile
void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "newparam")) {
- // save ID
- int attrSID = GetAttribute( "sid");
- std::string sid = mReader->getAttributeValue( attrSID);
- pEffect.mParams[sid] = EffectParam();
- ReadEffectParam( pEffect.mParams[sid]);
- }
- else if( IsElement( "technique") || IsElement( "extra"))
- {
- // just syntactic sugar
- }
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "newparam")) {
+ // save ID
+ int attrSID = GetAttribute( "sid");
+ std::string sid = mReader->getAttributeValue( attrSID);
+ pEffect.mParams[sid] = EffectParam();
+ ReadEffectParam( pEffect.mParams[sid]);
+ }
+ else if( IsElement( "technique") || IsElement( "extra"))
+ {
+ // just syntactic sugar
+ }
- /* Shading modes */
- else if( IsElement( "phong"))
- pEffect.mShadeType = Shade_Phong;
- else if( IsElement( "constant"))
- pEffect.mShadeType = Shade_Constant;
- else if( IsElement( "lambert"))
- pEffect.mShadeType = Shade_Lambert;
- else if( IsElement( "blinn"))
- pEffect.mShadeType = Shade_Blinn;
-
- /* Color + texture properties */
- else if( IsElement( "emission"))
- ReadEffectColor( pEffect.mEmissive, pEffect.mTexEmissive);
- else if( IsElement( "ambient"))
- ReadEffectColor( pEffect.mAmbient, pEffect.mTexAmbient);
- else if( IsElement( "diffuse"))
- ReadEffectColor( pEffect.mDiffuse, pEffect.mTexDiffuse);
- else if( IsElement( "specular"))
- ReadEffectColor( pEffect.mSpecular, pEffect.mTexSpecular);
- else if( IsElement( "reflective")) {
- ReadEffectColor( pEffect.mReflective, pEffect.mTexReflective);
- }
- else if( IsElement( "transparent")) {
- ReadEffectColor( pEffect.mTransparent,pEffect.mTexTransparent);
- }
- else if( IsElement( "shininess"))
- ReadEffectFloat( pEffect.mShininess);
- else if( IsElement( "reflectivity"))
- ReadEffectFloat( pEffect.mReflectivity);
-
- /* Single scalar properties */
- else if( IsElement( "transparency"))
- ReadEffectFloat( pEffect.mTransparency);
- else if( IsElement( "index_of_refraction"))
- ReadEffectFloat( pEffect.mRefractIndex);
-
- // GOOGLEEARTH/OKINO extensions
- // -------------------------------------------------------
- else if( IsElement( "double_sided"))
- pEffect.mDoubleSided = ReadBoolFromTextContent();
-
- // FCOLLADA extensions
- // -------------------------------------------------------
- else if( IsElement( "bump")) {
- aiColor4D dummy;
- ReadEffectColor( dummy,pEffect.mTexBump);
- }
+ else if( mFormat == FV_1_4_n && IsElement( "image"))
+ {
+ // read ID. Another entry which is "optional" by design but obligatory in reality
+ int attrID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( attrID);
- // MAX3D extensions
- // -------------------------------------------------------
- else if( IsElement( "wireframe")) {
- pEffect.mWireframe = ReadBoolFromTextContent();
- TestClosing( "wireframe");
- }
- else if( IsElement( "faceted")) {
- pEffect.mFaceted = ReadBoolFromTextContent();
- TestClosing( "faceted");
- }
- else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "profile_COMMON") == 0)
- {
- break;
- }
- }
- }
+ // create an entry and store it in the library under its ID
+ mImageLibrary[id] = Image();
+
+ // read on from there
+ ReadImage( mImageLibrary[id]);
+ }
+
+ /* Shading modes */
+ else if( IsElement( "phong"))
+ pEffect.mShadeType = Shade_Phong;
+ else if( IsElement( "constant"))
+ pEffect.mShadeType = Shade_Constant;
+ else if( IsElement( "lambert"))
+ pEffect.mShadeType = Shade_Lambert;
+ else if( IsElement( "blinn"))
+ pEffect.mShadeType = Shade_Blinn;
+
+ /* Color + texture properties */
+ else if( IsElement( "emission"))
+ ReadEffectColor( pEffect.mEmissive, pEffect.mTexEmissive);
+ else if( IsElement( "ambient"))
+ ReadEffectColor( pEffect.mAmbient, pEffect.mTexAmbient);
+ else if( IsElement( "diffuse"))
+ ReadEffectColor( pEffect.mDiffuse, pEffect.mTexDiffuse);
+ else if( IsElement( "specular"))
+ ReadEffectColor( pEffect.mSpecular, pEffect.mTexSpecular);
+ else if( IsElement( "reflective")) {
+ ReadEffectColor( pEffect.mReflective, pEffect.mTexReflective);
+ }
+ else if( IsElement( "transparent")) {
+ pEffect.mHasTransparency = true;
+
+ const char* opaque = mReader->getAttributeValueSafe("opaque");
+
+ if(::strcmp(opaque, "RGB_ZERO") == 0 || ::strcmp(opaque, "RGB_ONE") == 0) {
+ pEffect.mRGBTransparency = true;
+ }
+
+ // In RGB_ZERO mode, the transparency is interpreted in reverse, go figure...
+ if(::strcmp(opaque, "RGB_ZERO") == 0 || ::strcmp(opaque, "A_ZERO") == 0) {
+ pEffect.mInvertTransparency = true;
+ }
+
+ ReadEffectColor( pEffect.mTransparent,pEffect.mTexTransparent);
+ }
+ else if( IsElement( "shininess"))
+ ReadEffectFloat( pEffect.mShininess);
+ else if( IsElement( "reflectivity"))
+ ReadEffectFloat( pEffect.mReflectivity);
+
+ /* Single scalar properties */
+ else if( IsElement( "transparency"))
+ ReadEffectFloat( pEffect.mTransparency);
+ else if( IsElement( "index_of_refraction"))
+ ReadEffectFloat( pEffect.mRefractIndex);
+
+ // GOOGLEEARTH/OKINO extensions
+ // -------------------------------------------------------
+ else if( IsElement( "double_sided"))
+ pEffect.mDoubleSided = ReadBoolFromTextContent();
+
+ // FCOLLADA extensions
+ // -------------------------------------------------------
+ else if( IsElement( "bump")) {
+ aiColor4D dummy;
+ ReadEffectColor( dummy,pEffect.mTexBump);
+ }
+
+ // MAX3D extensions
+ // -------------------------------------------------------
+ else if( IsElement( "wireframe")) {
+ pEffect.mWireframe = ReadBoolFromTextContent();
+ TestClosing( "wireframe");
+ }
+ else if( IsElement( "faceted")) {
+ pEffect.mFaceted = ReadBoolFromTextContent();
+ TestClosing( "faceted");
+ }
+ else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "profile_COMMON") == 0)
+ {
+ break;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Read texture wrapping + UV transform settings from a profile==Maya chunk
void ColladaParser::ReadSamplerProperties( Sampler& out )
{
- if (mReader->isEmptyElement()) {
- return;
- }
+ if (mReader->isEmptyElement()) {
+ return;
+ }
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+
+ // MAYA extensions
+ // -------------------------------------------------------
+ if( IsElement( "wrapU")) {
+ out.mWrapU = ReadBoolFromTextContent();
+ TestClosing( "wrapU");
+ }
+ else if( IsElement( "wrapV")) {
+ out.mWrapV = ReadBoolFromTextContent();
+ TestClosing( "wrapV");
+ }
+ else if( IsElement( "mirrorU")) {
+ out.mMirrorU = ReadBoolFromTextContent();
+ TestClosing( "mirrorU");
+ }
+ else if( IsElement( "mirrorV")) {
+ out.mMirrorV = ReadBoolFromTextContent();
+ TestClosing( "mirrorV");
+ }
+ else if( IsElement( "repeatU")) {
+ out.mTransform.mScaling.x = ReadFloatFromTextContent();
+ TestClosing( "repeatU");
+ }
+ else if( IsElement( "repeatV")) {
+ out.mTransform.mScaling.y = ReadFloatFromTextContent();
+ TestClosing( "repeatV");
+ }
+ else if( IsElement( "offsetU")) {
+ out.mTransform.mTranslation.x = ReadFloatFromTextContent();
+ TestClosing( "offsetU");
+ }
+ else if( IsElement( "offsetV")) {
+ out.mTransform.mTranslation.y = ReadFloatFromTextContent();
+ TestClosing( "offsetV");
+ }
+ else if( IsElement( "rotateUV")) {
+ out.mTransform.mRotation = ReadFloatFromTextContent();
+ TestClosing( "rotateUV");
+ }
+ else if( IsElement( "blend_mode")) {
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ const char* sz = GetTextContent();
+ // http://www.feelingsoftware.com/content/view/55/72/lang,en/
+ // NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE
+ if (0 == ASSIMP_strincmp(sz,"ADD",3))
+ out.mOp = aiTextureOp_Add;
- // MAYA extensions
- // -------------------------------------------------------
- if( IsElement( "wrapU")) {
- out.mWrapU = ReadBoolFromTextContent();
- TestClosing( "wrapU");
- }
- else if( IsElement( "wrapV")) {
- out.mWrapV = ReadBoolFromTextContent();
- TestClosing( "wrapV");
- }
- else if( IsElement( "mirrorU")) {
- out.mMirrorU = ReadBoolFromTextContent();
- TestClosing( "mirrorU");
- }
- else if( IsElement( "mirrorV")) {
- out.mMirrorV = ReadBoolFromTextContent();
- TestClosing( "mirrorV");
- }
- else if( IsElement( "repeatU")) {
- out.mTransform.mScaling.x = ReadFloatFromTextContent();
- TestClosing( "repeatU");
- }
- else if( IsElement( "repeatV")) {
- out.mTransform.mScaling.y = ReadFloatFromTextContent();
- TestClosing( "repeatV");
- }
- else if( IsElement( "offsetU")) {
- out.mTransform.mTranslation.x = ReadFloatFromTextContent();
- TestClosing( "offsetU");
- }
- else if( IsElement( "offsetV")) {
- out.mTransform.mTranslation.y = ReadFloatFromTextContent();
- TestClosing( "offsetV");
- }
- else if( IsElement( "rotateUV")) {
- out.mTransform.mRotation = ReadFloatFromTextContent();
- TestClosing( "rotateUV");
- }
- else if( IsElement( "blend_mode")) {
-
- const char* sz = GetTextContent();
- // http://www.feelingsoftware.com/content/view/55/72/lang,en/
- // NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE
- if (0 == ASSIMP_strincmp(sz,"ADD",3))
- out.mOp = aiTextureOp_Add;
-
- else if (0 == ASSIMP_strincmp(sz,"SUBTRACT",8))
- out.mOp = aiTextureOp_Subtract;
-
- else if (0 == ASSIMP_strincmp(sz,"MULTIPLY",8))
- out.mOp = aiTextureOp_Multiply;
-
- else {
- DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode");
- }
- TestClosing( "blend_mode");
- }
- // OKINO extensions
- // -------------------------------------------------------
- else if( IsElement( "weighting")) {
- out.mWeighting = ReadFloatFromTextContent();
- TestClosing( "weighting");
- }
- else if( IsElement( "mix_with_previous_layer")) {
- out.mMixWithPrevious = ReadFloatFromTextContent();
- TestClosing( "mix_with_previous_layer");
- }
- // MAX3D extensions
- // -------------------------------------------------------
- else if( IsElement( "amount")) {
- out.mWeighting = ReadFloatFromTextContent();
- TestClosing( "amount");
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "technique") == 0)
- break;
- }
- }
+ else if (0 == ASSIMP_strincmp(sz,"SUBTRACT",8))
+ out.mOp = aiTextureOp_Subtract;
+
+ else if (0 == ASSIMP_strincmp(sz,"MULTIPLY",8))
+ out.mOp = aiTextureOp_Multiply;
+
+ else {
+ DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode");
+ }
+ TestClosing( "blend_mode");
+ }
+ // OKINO extensions
+ // -------------------------------------------------------
+ else if( IsElement( "weighting")) {
+ out.mWeighting = ReadFloatFromTextContent();
+ TestClosing( "weighting");
+ }
+ else if( IsElement( "mix_with_previous_layer")) {
+ out.mMixWithPrevious = ReadFloatFromTextContent();
+ TestClosing( "mix_with_previous_layer");
+ }
+ // MAX3D extensions
+ // -------------------------------------------------------
+ else if( IsElement( "amount")) {
+ out.mWeighting = ReadFloatFromTextContent();
+ TestClosing( "amount");
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "technique") == 0)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a color or a texture defining that color
void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
{
- if (mReader->isEmptyElement())
- return;
+ if (mReader->isEmptyElement())
+ return;
- // Save current element name
- const std::string curElem = mReader->getNodeName();
+ // Save current element name
+ const std::string curElem = mReader->getNodeName();
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "color"))
- {
- // text content contains 4 floats
- const char* content = GetTextContent();
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "color"))
+ {
+ // text content contains 4 floats
+ const char* content = GetTextContent();
- content = fast_atoreal_move<float>( content, (float&)pColor.r);
- SkipSpacesAndLineEnd( &content);
+ content = fast_atoreal_move<float>( content, (float&)pColor.r);
+ SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.g);
- SkipSpacesAndLineEnd( &content);
+ content = fast_atoreal_move<float>( content, (float&)pColor.g);
+ SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.b);
- SkipSpacesAndLineEnd( &content);
+ content = fast_atoreal_move<float>( content, (float&)pColor.b);
+ SkipSpacesAndLineEnd( &content);
- content = fast_atoreal_move<float>( content, (float&)pColor.a);
- SkipSpacesAndLineEnd( &content);
- TestClosing( "color");
- }
- else if( IsElement( "texture"))
- {
- // get name of source textur/sampler
- int attrTex = GetAttribute( "texture");
- pSampler.mName = mReader->getAttributeValue( attrTex);
-
- // get name of UV source channel. Specification demands it to be there, but some exporters
- // don't write it. It will be the default UV channel in case it's missing.
- attrTex = TestAttribute( "texcoord");
- if( attrTex >= 0 )
- pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
- //SkipElement();
- }
- else if( IsElement( "technique"))
- {
- const int _profile = GetAttribute( "profile");
- const char* profile = mReader->getAttributeValue( _profile );
+ content = fast_atoreal_move<float>( content, (float&)pColor.a);
+ SkipSpacesAndLineEnd( &content);
+ TestClosing( "color");
+ }
+ else if( IsElement( "texture"))
+ {
+ // get name of source textur/sampler
+ int attrTex = GetAttribute( "texture");
+ pSampler.mName = mReader->getAttributeValue( attrTex);
+
+ // get name of UV source channel. Specification demands it to be there, but some exporters
+ // don't write it. It will be the default UV channel in case it's missing.
+ attrTex = TestAttribute( "texcoord");
+ if( attrTex >= 0 )
+ pSampler.mUVChannel = mReader->getAttributeValue( attrTex);
+ //SkipElement();
+
+ // as we've read texture, the color needs to be 1,1,1,1
+ pColor = aiColor4D(1.f, 1.f, 1.f, 1.f);
+ }
+ else if( IsElement( "technique"))
+ {
+ const int _profile = GetAttribute( "profile");
+ const char* profile = mReader->getAttributeValue( _profile );
- // Some extensions are quite useful ... ReadSamplerProperties processes
- // several extensions in MAYA, OKINO and MAX3D profiles.
- if (!::strcmp(profile,"MAYA") || !::strcmp(profile,"MAX3D") || !::strcmp(profile,"OKINO"))
- {
- // get more information on this sampler
- ReadSamplerProperties(pSampler);
- }
- else SkipElement();
- }
- else if( !IsElement( "extra"))
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
- if (mReader->getNodeName() == curElem)
- break;
- }
- }
+ // Some extensions are quite useful ... ReadSamplerProperties processes
+ // several extensions in MAYA, OKINO and MAX3D profiles.
+ if (!::strcmp(profile,"MAYA") || !::strcmp(profile,"MAX3D") || !::strcmp(profile,"OKINO"))
+ {
+ // get more information on this sampler
+ ReadSamplerProperties(pSampler);
+ }
+ else SkipElement();
+ }
+ else if( !IsElement( "extra"))
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
+ if (mReader->getNodeName() == curElem)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a float
void ColladaParser::ReadEffectFloat( float& pFloat)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT){
- if( IsElement( "float"))
- {
- // text content contains a single floats
- const char* content = GetTextContent();
- content = fast_atoreal_move<float>( content, pFloat);
- SkipSpacesAndLineEnd( &content);
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT){
+ if( IsElement( "float"))
+ {
+ // text content contains a single floats
+ const char* content = GetTextContent();
+ content = fast_atoreal_move<float>( content, pFloat);
+ SkipSpacesAndLineEnd( &content);
- TestClosing( "float");
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
- break;
- }
- }
+ TestClosing( "float");
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Reads an effect parameter specification of any kind
+// Reads an effect parameter specification of any kind
void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "surface"))
- {
- // image ID given inside <init_from> tags
- TestOpening( "init_from");
- const char* content = GetTextContent();
- pParam.mType = Param_Surface;
- pParam.mReference = content;
- TestClosing( "init_from");
-
- // don't care for remaining stuff
- SkipElement( "surface");
- }
- else if( IsElement( "sampler2D"))
- {
- // surface ID is given inside <source> tags
- TestOpening( "source");
- const char* content = GetTextContent();
- pParam.mType = Param_Sampler;
- pParam.mReference = content;
- TestClosing( "source");
-
- // don't care for remaining stuff
- SkipElement( "sampler2D");
- } else
- {
- // ignore unknown element
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- break;
- }
- }
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "surface"))
+ {
+ // image ID given inside <init_from> tags
+ TestOpening( "init_from");
+ const char* content = GetTextContent();
+ pParam.mType = Param_Surface;
+ pParam.mReference = content;
+ TestClosing( "init_from");
+
+ // don't care for remaining stuff
+ SkipElement( "surface");
+ }
+ else if( IsElement( "sampler2D") && (FV_1_4_n == mFormat || FV_1_3_n == mFormat))
+ {
+ // surface ID is given inside <source> tags
+ TestOpening( "source");
+ const char* content = GetTextContent();
+ pParam.mType = Param_Sampler;
+ pParam.mReference = content;
+ TestClosing( "source");
+
+ // don't care for remaining stuff
+ SkipElement( "sampler2D");
+ }
+ else if( IsElement( "sampler2D"))
+ {
+ // surface ID is given inside <instance_image> tags
+ TestOpening( "instance_image");
+ int attrURL = GetAttribute("url");
+ const char* url = mReader->getAttributeValue( attrURL);
+ if( url[0] != '#')
+ ThrowException( "Unsupported URL format in instance_image");
+ url++;
+ pParam.mType = Param_Sampler;
+ pParam.mReference = url;
+ SkipElement( "sampler2D");
+ } else
+ {
+ // ignore unknown element
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the geometry library contents
void ColladaParser::ReadGeometryLibrary()
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "geometry"))
+ {
+ // read ID. Another entry which is "optional" by design but obligatory in reality
+ int indexID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( indexID);
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "geometry"))
- {
- // read ID. Another entry which is "optional" by design but obligatory in reality
- int indexID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( indexID);
+ // TODO: (thom) support SIDs
+ // ai_assert( TestAttribute( "sid") == -1);
- // TODO: (thom) support SIDs
- // ai_assert( TestAttribute( "sid") == -1);
+ // create a mesh and store it in the library under its ID
+ Mesh* mesh = new Mesh;
+ mMeshLibrary[id] = mesh;
- // create a mesh and store it in the library under its ID
- Mesh* mesh = new Mesh;
- mMeshLibrary[id] = mesh;
-
// read the mesh name if it exists
const int nameIndex = TestAttribute("name");
if(nameIndex != -1)
@@ -1542,167 +1789,167 @@ void ColladaParser::ReadGeometryLibrary()
mesh->mName = mReader->getAttributeValue(nameIndex);
}
- // read on from there
- ReadGeometry( mesh);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "library_geometries") != 0)
- ThrowException( "Expected end of <library_geometries> element.");
-
- break;
- }
- }
+ // read on from there
+ ReadGeometry( mesh);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "library_geometries") != 0)
+ ThrowException( "Expected end of <library_geometries> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a geometry from the geometry library.
void ColladaParser::ReadGeometry( Collada::Mesh* pMesh)
{
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "mesh"))
- {
- // read on from there
- ReadMesh( pMesh);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "geometry") != 0)
- ThrowException( "Expected end of <geometry> element.");
-
- break;
- }
- }
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "mesh"))
+ {
+ // read on from there
+ ReadMesh( pMesh);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "geometry") != 0)
+ ThrowException( "Expected end of <geometry> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a mesh from the geometry library
void ColladaParser::ReadMesh( Mesh* pMesh)
{
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "source"))
- {
- // we have professionals dealing with this
- ReadSource();
- }
- else if( IsElement( "vertices"))
- {
- // read per-vertex mesh data
- ReadVertexData( pMesh);
- }
- else if( IsElement( "triangles") || IsElement( "lines") || IsElement( "linestrips")
- || IsElement( "polygons") || IsElement( "polylist") || IsElement( "trifans") || IsElement( "tristrips"))
- {
- // read per-index mesh data and faces setup
- ReadIndexData( pMesh);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "technique_common") == 0)
- {
- // end of another meaningless element - read over it
- }
- else if( strcmp( mReader->getNodeName(), "mesh") == 0)
- {
- // end of <mesh> element - we're done here
- break;
- } else
- {
- // everything else should be punished
- ThrowException( "Expected end of <mesh> element.");
- }
- }
- }
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "source"))
+ {
+ // we have professionals dealing with this
+ ReadSource();
+ }
+ else if( IsElement( "vertices"))
+ {
+ // read per-vertex mesh data
+ ReadVertexData( pMesh);
+ }
+ else if( IsElement( "triangles") || IsElement( "lines") || IsElement( "linestrips")
+ || IsElement( "polygons") || IsElement( "polylist") || IsElement( "trifans") || IsElement( "tristrips"))
+ {
+ // read per-index mesh data and faces setup
+ ReadIndexData( pMesh);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "technique_common") == 0)
+ {
+ // end of another meaningless element - read over it
+ }
+ else if( strcmp( mReader->getNodeName(), "mesh") == 0)
+ {
+ // end of <mesh> element - we're done here
+ break;
+ } else
+ {
+ // everything else should be punished
+ ThrowException( "Expected end of <mesh> element.");
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Reads a source element
+// Reads a source element
void ColladaParser::ReadSource()
{
- int indexID = GetAttribute( "id");
- std::string sourceID = mReader->getAttributeValue( indexID);
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "float_array") || IsElement( "IDREF_array") || IsElement( "Name_array"))
- {
- ReadDataArray();
- }
- else if( IsElement( "technique_common"))
- {
- // I don't care for your profiles
- }
- else if( IsElement( "accessor"))
- {
- ReadAccessor( sourceID);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "source") == 0)
- {
- // end of <source> - we're done
- break;
- }
- else if( strcmp( mReader->getNodeName(), "technique_common") == 0)
- {
- // end of another meaningless element - read over it
- } else
- {
- // everything else should be punished
- ThrowException( "Expected end of <source> element.");
- }
- }
- }
+ int indexID = GetAttribute( "id");
+ std::string sourceID = mReader->getAttributeValue( indexID);
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "float_array") || IsElement( "IDREF_array") || IsElement( "Name_array"))
+ {
+ ReadDataArray();
+ }
+ else if( IsElement( "technique_common"))
+ {
+ // I don't care for your profiles
+ }
+ else if( IsElement( "accessor"))
+ {
+ ReadAccessor( sourceID);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "source") == 0)
+ {
+ // end of <source> - we're done
+ break;
+ }
+ else if( strcmp( mReader->getNodeName(), "technique_common") == 0)
+ {
+ // end of another meaningless element - read over it
+ } else
+ {
+ // everything else should be punished
+ ThrowException( "Expected end of <source> element.");
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a data array holding a number of floats, and stores it in the global library
void ColladaParser::ReadDataArray()
{
- std::string elmName = mReader->getNodeName();
- bool isStringArray = (elmName == "IDREF_array" || elmName == "Name_array");
+ std::string elmName = mReader->getNodeName();
+ bool isStringArray = (elmName == "IDREF_array" || elmName == "Name_array");
bool isEmptyElement = mReader->isEmptyElement();
- // read attributes
- int indexID = GetAttribute( "id");
- std::string id = mReader->getAttributeValue( indexID);
- int indexCount = GetAttribute( "count");
- unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( indexCount);
- const char* content = TestTextContent();
+ // read attributes
+ int indexID = GetAttribute( "id");
+ std::string id = mReader->getAttributeValue( indexID);
+ int indexCount = GetAttribute( "count");
+ unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( indexCount);
+ const char* content = TestTextContent();
// read values and store inside an array in the data library
mDataLibrary[id] = Data();
@@ -1710,43 +1957,43 @@ void ColladaParser::ReadDataArray()
data.mIsStringArray = isStringArray;
// some exporters write empty data arrays, but we need to conserve them anyways because others might reference them
- if (content)
- {
- if( isStringArray)
- {
- data.mStrings.reserve( count);
- std::string s;
+ if (content)
+ {
+ if( isStringArray)
+ {
+ data.mStrings.reserve( count);
+ std::string s;
- for( unsigned int a = 0; a < count; a++)
- {
- if( *content == 0)
- ThrowException( "Expected more values while reading IDREF_array contents.");
+ for( unsigned int a = 0; a < count; a++)
+ {
+ if( *content == 0)
+ ThrowException( "Expected more values while reading IDREF_array contents.");
- s.clear();
- while( !IsSpaceOrNewLine( *content))
- s += *content++;
- data.mStrings.push_back( s);
+ s.clear();
+ while( !IsSpaceOrNewLine( *content))
+ s += *content++;
+ data.mStrings.push_back( s);
- SkipSpacesAndLineEnd( &content);
- }
- } else
- {
- data.mValues.reserve( count);
+ SkipSpacesAndLineEnd( &content);
+ }
+ } else
+ {
+ data.mValues.reserve( count);
- for( unsigned int a = 0; a < count; a++)
- {
- if( *content == 0)
- ThrowException( "Expected more values while reading float_array contents.");
-
- float value;
- // read a number
- content = fast_atoreal_move<float>( content, value);
- data.mValues.push_back( value);
- // skip whitespace after it
- SkipSpacesAndLineEnd( &content);
- }
- }
- }
+ for( unsigned int a = 0; a < count; a++)
+ {
+ if( *content == 0)
+ ThrowException( "Expected more values while reading float_array contents.");
+
+ float value;
+ // read a number
+ content = fast_atoreal_move<float>( content, value);
+ data.mValues.push_back( value);
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
+ }
+ }
// test for closing tag
if( !isEmptyElement )
@@ -1757,1037 +2004,1102 @@ void ColladaParser::ReadDataArray()
// Reads an accessor and stores it in the global library
void ColladaParser::ReadAccessor( const std::string& pID)
{
- // read accessor attributes
- int attrSource = GetAttribute( "source");
- const char* source = mReader->getAttributeValue( attrSource);
- if( source[0] != '#')
- ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\" in source attribute of <accessor> element.") % source));
- int attrCount = GetAttribute( "count");
- unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount);
- int attrOffset = TestAttribute( "offset");
- unsigned int offset = 0;
- if( attrOffset > -1)
- offset = (unsigned int) mReader->getAttributeValueAsInt( attrOffset);
- int attrStride = TestAttribute( "stride");
- unsigned int stride = 1;
- if( attrStride > -1)
- stride = (unsigned int) mReader->getAttributeValueAsInt( attrStride);
-
- // store in the library under the given ID
- mAccessorLibrary[pID] = Accessor();
- Accessor& acc = mAccessorLibrary[pID];
- acc.mCount = count;
- acc.mOffset = offset;
- acc.mStride = stride;
- acc.mSource = source+1; // ignore the leading '#'
- acc.mSize = 0; // gets incremented with every param
-
- // and read the components
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "param"))
- {
- // read data param
- int attrName = TestAttribute( "name");
- std::string name;
- if( attrName > -1)
- {
- name = mReader->getAttributeValue( attrName);
-
- // analyse for common type components and store it's sub-offset in the corresponding field
-
- /* Cartesian coordinates */
- if( name == "X") acc.mSubOffset[0] = acc.mParams.size();
- else if( name == "Y") acc.mSubOffset[1] = acc.mParams.size();
- else if( name == "Z") acc.mSubOffset[2] = acc.mParams.size();
-
- /* RGBA colors */
- else if( name == "R") acc.mSubOffset[0] = acc.mParams.size();
- else if( name == "G") acc.mSubOffset[1] = acc.mParams.size();
- else if( name == "B") acc.mSubOffset[2] = acc.mParams.size();
- else if( name == "A") acc.mSubOffset[3] = acc.mParams.size();
-
- /* UVWQ (STPQ) texture coordinates */
- else if( name == "S") acc.mSubOffset[0] = acc.mParams.size();
- else if( name == "T") acc.mSubOffset[1] = acc.mParams.size();
- else if( name == "P") acc.mSubOffset[2] = acc.mParams.size();
- // else if( name == "Q") acc.mSubOffset[3] = acc.mParams.size();
- /* 4D uv coordinates are not supported in Assimp */
-
- /* Generic extra data, interpreted as UV data, too*/
- else if( name == "U") acc.mSubOffset[0] = acc.mParams.size();
- else if( name == "V") acc.mSubOffset[1] = acc.mParams.size();
- //else
- // DefaultLogger::get()->warn( boost::str( boost::format( "Unknown accessor parameter \"%s\". Ignoring data channel.") % name));
- }
+ // read accessor attributes
+ int attrSource = GetAttribute( "source");
+ const char* source = mReader->getAttributeValue( attrSource);
+ if( source[0] != '#')
+ ThrowException( format() << "Unknown reference format in url \"" << source << "\" in source attribute of <accessor> element." );
+ int attrCount = GetAttribute( "count");
+ unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount);
+ int attrOffset = TestAttribute( "offset");
+ unsigned int offset = 0;
+ if( attrOffset > -1)
+ offset = (unsigned int) mReader->getAttributeValueAsInt( attrOffset);
+ int attrStride = TestAttribute( "stride");
+ unsigned int stride = 1;
+ if( attrStride > -1)
+ stride = (unsigned int) mReader->getAttributeValueAsInt( attrStride);
+
+ // store in the library under the given ID
+ mAccessorLibrary[pID] = Accessor();
+ Accessor& acc = mAccessorLibrary[pID];
+ acc.mCount = count;
+ acc.mOffset = offset;
+ acc.mStride = stride;
+ acc.mSource = source+1; // ignore the leading '#'
+ acc.mSize = 0; // gets incremented with every param
+
+ // and read the components
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "param"))
+ {
+ // read data param
+ int attrName = TestAttribute( "name");
+ std::string name;
+ if( attrName > -1)
+ {
+ name = mReader->getAttributeValue( attrName);
+
+ // analyse for common type components and store it's sub-offset in the corresponding field
+
+ /* Cartesian coordinates */
+ if( name == "X") acc.mSubOffset[0] = acc.mParams.size();
+ else if( name == "Y") acc.mSubOffset[1] = acc.mParams.size();
+ else if( name == "Z") acc.mSubOffset[2] = acc.mParams.size();
+
+ /* RGBA colors */
+ else if( name == "R") acc.mSubOffset[0] = acc.mParams.size();
+ else if( name == "G") acc.mSubOffset[1] = acc.mParams.size();
+ else if( name == "B") acc.mSubOffset[2] = acc.mParams.size();
+ else if( name == "A") acc.mSubOffset[3] = acc.mParams.size();
+
+ /* UVWQ (STPQ) texture coordinates */
+ else if( name == "S") acc.mSubOffset[0] = acc.mParams.size();
+ else if( name == "T") acc.mSubOffset[1] = acc.mParams.size();
+ else if( name == "P") acc.mSubOffset[2] = acc.mParams.size();
+ // else if( name == "Q") acc.mSubOffset[3] = acc.mParams.size();
+ /* 4D uv coordinates are not supported in Assimp */
+
+ /* Generic extra data, interpreted as UV data, too*/
+ else if( name == "U") acc.mSubOffset[0] = acc.mParams.size();
+ else if( name == "V") acc.mSubOffset[1] = acc.mParams.size();
+ //else
+ // DefaultLogger::get()->warn( format() << "Unknown accessor parameter \"" << name << "\". Ignoring data channel." );
+ }
- // read data type
- int attrType = TestAttribute( "type");
- if( attrType > -1)
- {
- // for the moment we only distinguish between a 4x4 matrix and anything else.
- // TODO: (thom) I don't have a spec here at work. Check if there are other multi-value types
- // which should be tested for here.
- std::string type = mReader->getAttributeValue( attrType);
- if( type == "float4x4")
- acc.mSize += 16;
- else
- acc.mSize += 1;
- }
+ // read data type
+ int attrType = TestAttribute( "type");
+ if( attrType > -1)
+ {
+ // for the moment we only distinguish between a 4x4 matrix and anything else.
+ // TODO: (thom) I don't have a spec here at work. Check if there are other multi-value types
+ // which should be tested for here.
+ std::string type = mReader->getAttributeValue( attrType);
+ if( type == "float4x4")
+ acc.mSize += 16;
+ else
+ acc.mSize += 1;
+ }
- acc.mParams.push_back( name);
+ acc.mParams.push_back( name);
- // skip remaining stuff of this element, if any
- SkipElement();
- } else
- {
- ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <accessor>") % mReader->getNodeName()));
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "accessor") != 0)
- ThrowException( "Expected end of <accessor> element.");
- break;
- }
- }
+ // skip remaining stuff of this element, if any
+ SkipElement();
+ } else
+ {
+ ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <accessor>" );
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "accessor") != 0)
+ ThrowException( "Expected end of <accessor> element.");
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads input declarations of per-vertex mesh data into the given mesh
void ColladaParser::ReadVertexData( Mesh* pMesh)
{
- // extract the ID of the <vertices> element. Not that we care, but to catch strange referencing schemes we should warn about
- int attrID= GetAttribute( "id");
- pMesh->mVertexID = mReader->getAttributeValue( attrID);
-
- // a number of <input> elements
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "input"))
- {
- ReadInputChannel( pMesh->mPerVertexData);
- } else
- {
- ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <vertices>") % mReader->getNodeName()));
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "vertices") != 0)
- ThrowException( "Expected end of <vertices> element.");
-
- break;
- }
- }
+ // extract the ID of the <vertices> element. Not that we care, but to catch strange referencing schemes we should warn about
+ int attrID= GetAttribute( "id");
+ pMesh->mVertexID = mReader->getAttributeValue( attrID);
+
+ // a number of <input> elements
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "input"))
+ {
+ ReadInputChannel( pMesh->mPerVertexData);
+ } else
+ {
+ ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <vertices>" );
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "vertices") != 0)
+ ThrowException( "Expected end of <vertices> element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads input declarations of per-index mesh data into the given mesh
void ColladaParser::ReadIndexData( Mesh* pMesh)
{
- std::vector<size_t> vcount;
- std::vector<InputChannel> perIndexData;
-
- // read primitive count from the attribute
- int attrCount = GetAttribute( "count");
- size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
-
- // material subgroup
- int attrMaterial = TestAttribute( "material");
- SubMesh subgroup;
- if( attrMaterial > -1)
- subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
- subgroup.mNumFaces = numPrimitives;
- pMesh->mSubMeshes.push_back( subgroup);
-
- // distinguish between polys and triangles
- std::string elementName = mReader->getNodeName();
- PrimitiveType primType = Prim_Invalid;
- if( IsElement( "lines"))
- primType = Prim_Lines;
- else if( IsElement( "linestrips"))
- primType = Prim_LineStrip;
- else if( IsElement( "polygons"))
- primType = Prim_Polygon;
- else if( IsElement( "polylist"))
- primType = Prim_Polylist;
- else if( IsElement( "triangles"))
- primType = Prim_Triangles;
- else if( IsElement( "trifans"))
- primType = Prim_TriFans;
- else if( IsElement( "tristrips"))
- primType = Prim_TriStrips;
-
- ai_assert( primType != Prim_Invalid);
-
- // also a number of <input> elements, but in addition a <p> primitive collection and propably index counts for all primitives
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "input"))
- {
- ReadInputChannel( perIndexData);
- }
- else if( IsElement( "vcount"))
- {
- if( !mReader->isEmptyElement())
- {
- if (numPrimitives) // It is possible to define a mesh without any primitives
- {
- // case <polylist> - specifies the number of indices for each polygon
- const char* content = GetTextContent();
- vcount.reserve( numPrimitives);
- for( unsigned int a = 0; a < numPrimitives; a++)
- {
- if( *content == 0)
- ThrowException( "Expected more values while reading <vcount> contents.");
- // read a number
- vcount.push_back( (size_t) strtoul10( content, &content));
- // skip whitespace after it
- SkipSpacesAndLineEnd( &content);
- }
- }
-
- TestClosing( "vcount");
- }
- }
- else if( IsElement( "p"))
- {
- if( !mReader->isEmptyElement())
- {
- // now here the actual fun starts - these are the indices to construct the mesh data from
- ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType);
- }
- } else
- {
- ThrowException( boost::str( boost::format( "Unexpected sub element <%s> in tag <%s>") % mReader->getNodeName() % elementName));
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( mReader->getNodeName() != elementName)
- ThrowException( boost::str( boost::format( "Expected end of <%s> element.") % elementName));
+ std::vector<size_t> vcount;
+ std::vector<InputChannel> perIndexData;
+
+ // read primitive count from the attribute
+ int attrCount = GetAttribute( "count");
+ size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
+ // some mesh types (e.g. tristrips) don't specify primitive count upfront,
+ // so we need to sum up the actual number of primitives while we read the <p>-tags
+ size_t actualPrimitives = 0;
+
+ // material subgroup
+ int attrMaterial = TestAttribute( "material");
+ SubMesh subgroup;
+ if( attrMaterial > -1)
+ subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
+
+ // distinguish between polys and triangles
+ std::string elementName = mReader->getNodeName();
+ PrimitiveType primType = Prim_Invalid;
+ if( IsElement( "lines"))
+ primType = Prim_Lines;
+ else if( IsElement( "linestrips"))
+ primType = Prim_LineStrip;
+ else if( IsElement( "polygons"))
+ primType = Prim_Polygon;
+ else if( IsElement( "polylist"))
+ primType = Prim_Polylist;
+ else if( IsElement( "triangles"))
+ primType = Prim_Triangles;
+ else if( IsElement( "trifans"))
+ primType = Prim_TriFans;
+ else if( IsElement( "tristrips"))
+ primType = Prim_TriStrips;
+
+ ai_assert( primType != Prim_Invalid);
+
+ // also a number of <input> elements, but in addition a <p> primitive collection and probably index counts for all primitives
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "input"))
+ {
+ ReadInputChannel( perIndexData);
+ }
+ else if( IsElement( "vcount"))
+ {
+ if( !mReader->isEmptyElement())
+ {
+ if (numPrimitives) // It is possible to define a mesh without any primitives
+ {
+ // case <polylist> - specifies the number of indices for each polygon
+ const char* content = GetTextContent();
+ vcount.reserve( numPrimitives);
+ for( unsigned int a = 0; a < numPrimitives; a++)
+ {
+ if( *content == 0)
+ ThrowException( "Expected more values while reading <vcount> contents.");
+ // read a number
+ vcount.push_back( (size_t) strtoul10( content, &content));
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
+ }
- break;
- }
- }
+ TestClosing( "vcount");
+ }
+ }
+ else if( IsElement( "p"))
+ {
+ if( !mReader->isEmptyElement())
+ {
+ // now here the actual fun starts - these are the indices to construct the mesh data from
+ actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
+ }
+ }
+ else if (IsElement("extra"))
+ {
+ SkipElement("extra");
+ } else
+ {
+ ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" );
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( mReader->getNodeName() != elementName)
+ ThrowException( format() << "Expected end of <" << elementName << "> element." );
+
+ break;
+ }
+ }
+
+#ifdef ASSIMP_BUILD_DEBUG
+ if (primType != Prim_TriFans && primType != Prim_TriStrips &&
+ primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'.
+ ai_assert(actualPrimitives == numPrimitives);
+ }
+#endif
+
+ // only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
+ subgroup.mNumFaces = actualPrimitives;
+ pMesh->mSubMeshes.push_back(subgroup);
}
// ------------------------------------------------------------------------------------------------
-// Reads a single input channel element and stores it in the given array, if valid
+// Reads a single input channel element and stores it in the given array, if valid
void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
{
- InputChannel channel;
-
- // read semantic
- int attrSemantic = GetAttribute( "semantic");
- std::string semantic = mReader->getAttributeValue( attrSemantic);
- channel.mType = GetTypeForSemantic( semantic);
-
- // read source
- int attrSource = GetAttribute( "source");
- const char* source = mReader->getAttributeValue( attrSource);
- if( source[0] != '#')
- ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\" in source attribute of <input> element.") % source));
- channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only
-
- // read index offset, if per-index <input>
- int attrOffset = TestAttribute( "offset");
- if( attrOffset > -1)
- channel.mOffset = mReader->getAttributeValueAsInt( attrOffset);
-
- // read set if texture coordinates
- if(channel.mType == IT_Texcoord || channel.mType == IT_Color){
- int attrSet = TestAttribute("set");
- if(attrSet > -1){
- attrSet = mReader->getAttributeValueAsInt( attrSet);
- if(attrSet < 0)
- ThrowException( boost::str( boost::format( "Invalid index \"%i\" in set attribute of <input> element") % (attrSet)));
-
- channel.mIndex = attrSet;
- }
- }
-
- // store, if valid type
- if( channel.mType != IT_Invalid)
- poChannels.push_back( channel);
-
- // skip remaining stuff of this element, if any
- SkipElement();
+ InputChannel channel;
+
+ // read semantic
+ int attrSemantic = GetAttribute( "semantic");
+ std::string semantic = mReader->getAttributeValue( attrSemantic);
+ channel.mType = GetTypeForSemantic( semantic);
+
+ // read source
+ int attrSource = GetAttribute( "source");
+ const char* source = mReader->getAttributeValue( attrSource);
+ if( source[0] != '#')
+ ThrowException( format() << "Unknown reference format in url \"" << source << "\" in source attribute of <input> element." );
+ channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only
+
+ // read index offset, if per-index <input>
+ int attrOffset = TestAttribute( "offset");
+ if( attrOffset > -1)
+ channel.mOffset = mReader->getAttributeValueAsInt( attrOffset);
+
+ // read set if texture coordinates
+ if(channel.mType == IT_Texcoord || channel.mType == IT_Color){
+ int attrSet = TestAttribute("set");
+ if(attrSet > -1){
+ attrSet = mReader->getAttributeValueAsInt( attrSet);
+ if(attrSet < 0)
+ ThrowException( format() << "Invalid index \"" << (attrSet) << "\" in set attribute of <input> element" );
+
+ channel.mIndex = attrSet;
+ }
+ }
+
+ // store, if valid type
+ if( channel.mType != IT_Invalid)
+ poChannels.push_back( channel);
+
+ // skip remaining stuff of this element, if any
+ SkipElement();
}
// ------------------------------------------------------------------------------------------------
// Reads a <p> primitive index list and assembles the mesh data into the given mesh
-void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
- size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
+size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
+ size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
{
- // determine number of indices coming per vertex
- // find the offset index for all per-vertex channels
- size_t numOffsets = 1;
- size_t perVertexOffset = SIZE_MAX; // invalid value
- BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels)
- {
- numOffsets = std::max( numOffsets, channel.mOffset+1);
- if( channel.mType == IT_Vertex)
- perVertexOffset = channel.mOffset;
- }
-
- // determine the expected number of indices
- size_t expectedPointCount = 0;
- switch( pPrimType)
- {
- case Prim_Polylist:
- {
- BOOST_FOREACH( size_t i, pVCount)
- expectedPointCount += i;
- break;
- }
- case Prim_Lines:
- expectedPointCount = 2 * pNumPrimitives;
- break;
- case Prim_Triangles:
- expectedPointCount = 3 * pNumPrimitives;
- break;
- default:
- // other primitive types don't state the index count upfront... we need to guess
- break;
- }
-
- // and read all indices into a temporary array
- std::vector<size_t> indices;
- if( expectedPointCount > 0)
- indices.reserve( expectedPointCount * numOffsets);
-
- if (pNumPrimitives > 0) // It is possible to not contain any indicies
- {
- const char* content = GetTextContent();
- while( *content != 0)
- {
- // read a value.
- // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways.
- int value = std::max( 0, strtol10( content, &content));
- indices.push_back( size_t( value));
- // skip whitespace after it
- SkipSpacesAndLineEnd( &content);
- }
- }
-
- // complain if the index count doesn't fit
- if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets)
- ThrowException( "Expected different index count in <p> element.");
- else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
+ // determine number of indices coming per vertex
+ // find the offset index for all per-vertex channels
+ size_t numOffsets = 1;
+ size_t perVertexOffset = SIZE_MAX; // invalid value
+ for( const InputChannel& channel : pPerIndexChannels)
+ {
+ numOffsets = std::max( numOffsets, channel.mOffset+1);
+ if( channel.mType == IT_Vertex)
+ perVertexOffset = channel.mOffset;
+ }
+
+ // determine the expected number of indices
+ size_t expectedPointCount = 0;
+ switch( pPrimType)
+ {
+ case Prim_Polylist:
+ {
+ for( size_t i : pVCount)
+ expectedPointCount += i;
+ break;
+ }
+ case Prim_Lines:
+ expectedPointCount = 2 * pNumPrimitives;
+ break;
+ case Prim_Triangles:
+ expectedPointCount = 3 * pNumPrimitives;
+ break;
+ default:
+ // other primitive types don't state the index count upfront... we need to guess
+ break;
+ }
+
+ // and read all indices into a temporary array
+ std::vector<size_t> indices;
+ if( expectedPointCount > 0)
+ indices.reserve( expectedPointCount * numOffsets);
+
+ if (pNumPrimitives > 0) // It is possible to not contain any indices
+ {
+ const char* content = GetTextContent();
+ while( *content != 0)
+ {
+ // read a value.
+ // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways.
+ int value = std::max( 0, strtol10( content, &content));
+ indices.push_back( size_t( value));
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
+ }
+
+ // complain if the index count doesn't fit
+ if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) {
+ if (pPrimType == Prim_Lines) {
+ // HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines'
+ ReportWarning( "Expected different index count in <p> element, %d instead of %d.", indices.size(), expectedPointCount * numOffsets);
+ pNumPrimitives = (indices.size() / numOffsets) / 2;
+ } else
+ ThrowException( "Expected different index count in <p> element.");
+
+ } else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
ThrowException( "Expected different index count in <p> element.");
- // find the data for all sources
+ // find the data for all sources
for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
- {
+ {
InputChannel& input = *it;
- if( input.mResolved)
- continue;
-
- // find accessor
- input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
- // resolve accessor's data pointer as well, if neccessary
- const Accessor* acc = input.mResolved;
- if( !acc->mData)
- acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
- }
- // and the same for the per-index channels
+ if( input.mResolved)
+ continue;
+
+ // find accessor
+ input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
+ // resolve accessor's data pointer as well, if necessary
+ const Accessor* acc = input.mResolved;
+ if( !acc->mData)
+ acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
+ }
+ // and the same for the per-index channels
for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
{
InputChannel& input = *it;
- if( input.mResolved)
- continue;
-
- // ignore vertex pointer, it doesn't refer to an accessor
- if( input.mType == IT_Vertex)
- {
- // warn if the vertex channel does not refer to the <vertices> element in the same mesh
- if( input.mAccessor != pMesh->mVertexID)
- ThrowException( "Unsupported vertex referencing scheme.");
- continue;
- }
-
- // find accessor
- input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
- // resolve accessor's data pointer as well, if neccessary
- const Accessor* acc = input.mResolved;
- if( !acc->mData)
- acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
- }
-
-
- // now assemble vertex data according to those indices
- std::vector<size_t>::const_iterator idx = indices.begin();
-
- // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
- size_t numPrimitives = pNumPrimitives;
- if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
- numPrimitives = 1;
+ if( input.mResolved)
+ continue;
+
+ // ignore vertex pointer, it doesn't refer to an accessor
+ if( input.mType == IT_Vertex)
+ {
+ // warn if the vertex channel does not refer to the <vertices> element in the same mesh
+ if( input.mAccessor != pMesh->mVertexID)
+ ThrowException( "Unsupported vertex referencing scheme.");
+ continue;
+ }
+
+ // find accessor
+ input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
+ // resolve accessor's data pointer as well, if necessary
+ const Accessor* acc = input.mResolved;
+ if( !acc->mData)
+ acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
+ }
+
+ // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
+ size_t numPrimitives = pNumPrimitives;
+ if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
+ numPrimitives = 1;
+ // For continued primitives, the given count is actually the number of <p>'s inside the parent tag
+ if ( pPrimType == Prim_TriStrips){
+ size_t numberOfVertices = indices.size() / numOffsets;
+ numPrimitives = numberOfVertices - 2;
+ }
+
+ pMesh->mFaceSize.reserve( numPrimitives);
+ pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
+
+ size_t polylistStartVertex = 0;
+ for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++)
+ {
+ // determine number of points for this primitive
+ size_t numPoints = 0;
+ switch( pPrimType)
+ {
+ case Prim_Lines:
+ numPoints = 2;
+ for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+ CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ break;
+ case Prim_Triangles:
+ numPoints = 3;
+ for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+ CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ break;
+ case Prim_TriStrips:
+ numPoints = 3;
+ ReadPrimTriStrips(numOffsets, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ break;
+ case Prim_Polylist:
+ numPoints = pVCount[currentPrimitive];
+ for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+ CopyVertex(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices);
+ polylistStartVertex += numPoints;
+ break;
+ case Prim_TriFans:
+ case Prim_Polygon:
+ numPoints = indices.size() / numOffsets;
+ for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+ CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ break;
+ default:
+ // LineStrip is not supported due to expected index unmangling
+ ThrowException( "Unsupported primitive type.");
+ break;
+ }
+
+ // store the face size to later reconstruct the face from
+ pMesh->mFaceSize.push_back( numPoints);
+ }
+
+ // if I ever get my hands on that guy who invented this steaming pile of indirection...
+ TestClosing( "p");
+ return numPrimitives;
+}
- pMesh->mFaceSize.reserve( numPrimitives);
- pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
+void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
+ // calculate the base offset of the vertex whose attributes we ant to copy
+ size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
- for( size_t a = 0; a < numPrimitives; a++)
- {
- // determine number of points for this primitive
- size_t numPoints = 0;
- switch( pPrimType)
- {
- case Prim_Lines:
- numPoints = 2;
- break;
- case Prim_Triangles:
- numPoints = 3;
- break;
- case Prim_Polylist:
- numPoints = pVCount[a];
- break;
- case Prim_TriFans:
- case Prim_Polygon:
- numPoints = indices.size() / numOffsets;
- break;
- default:
- // LineStrip and TriStrip not supported due to expected index unmangling
- ThrowException( "Unsupported primitive type.");
- break;
- }
+ // don't overrun the boundaries of the index list
+ size_t maxIndexRequested = baseOffset + numOffsets - 1;
+ ai_assert(maxIndexRequested < indices.size());
- // store the face size to later reconstruct the face from
- pMesh->mFaceSize.push_back( numPoints);
-
- // gather that number of vertices
- for( size_t b = 0; b < numPoints; b++)
- {
- // read all indices for this vertex. Yes, in a hacky local array
- ai_assert( numOffsets < 20 && perVertexOffset < 20);
- size_t vindex[20];
- for( size_t offsets = 0; offsets < numOffsets; ++offsets)
- vindex[offsets] = *idx++;
-
- // extract per-vertex channels using the global per-vertex offset
- for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
- ExtractDataObjectFromChannel( *it, vindex[perVertexOffset], pMesh);
- // and extract per-index channels using there specified offset
- for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
- ExtractDataObjectFromChannel( *it, vindex[it->mOffset], pMesh);
-
- // store the vertex-data index for later assignment of bone vertex weights
- pMesh->mFacePosIndices.push_back( vindex[perVertexOffset]);
- }
- }
+ // extract per-vertex channels using the global per-vertex offset
+ for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
+ ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
+ // and extract per-index channels using there specified offset
+ for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
+ ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
+ // store the vertex-data index for later assignment of bone vertex weights
+ pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
+}
- // if I ever get my hands on that guy who invented this steaming pile of indirection...
- TestClosing( "p");
+void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
+ if (currentPrimitive % 2 != 0){
+ //odd tristrip triangles need their indices mangled, to preserve winding direction
+ CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ }
+ else {//for non tristrips or even tristrip triangles
+ CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Extracts a single object from an input channel and stores it in the appropriate mesh data array
+// Extracts a single object from an input channel and stores it in the appropriate mesh data array
void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh)
{
- // ignore vertex referrer - we handle them that separate
- if( pInput.mType == IT_Vertex)
- return;
-
- const Accessor& acc = *pInput.mResolved;
- if( pLocalIndex >= acc.mCount)
- ThrowException( boost::str( boost::format( "Invalid data index (%d/%d) in primitive specification") % pLocalIndex % acc.mCount));
-
- // get a pointer to the start of the data object referred to by the accessor and the local index
- const float* dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex* acc.mStride;
-
- // assemble according to the accessors component sub-offset list. We don't care, yet,
- // what kind of object exactly we're extracting here
- float obj[4];
- for( size_t c = 0; c < 4; ++c)
- obj[c] = dataObject[acc.mSubOffset[c]];
-
- // now we reinterpret it according to the type we're reading here
- switch( pInput.mType)
- {
- case IT_Position: // ignore all position streams except 0 - there can be only one position
- if( pInput.mIndex == 0)
- pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
- else
- DefaultLogger::get()->error("Collada: just one vertex position stream supported");
- break;
- case IT_Normal:
- // pad to current vertex count if necessary
- if( pMesh->mNormals.size() < pMesh->mPositions.size()-1)
- pMesh->mNormals.insert( pMesh->mNormals.end(), pMesh->mPositions.size() - pMesh->mNormals.size() - 1, aiVector3D( 0, 1, 0));
-
- // ignore all normal streams except 0 - there can be only one normal
- if( pInput.mIndex == 0)
- pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
- else
- DefaultLogger::get()->error("Collada: just one vertex normal stream supported");
- break;
- case IT_Tangent:
- // pad to current vertex count if necessary
- if( pMesh->mTangents.size() < pMesh->mPositions.size()-1)
- pMesh->mTangents.insert( pMesh->mTangents.end(), pMesh->mPositions.size() - pMesh->mTangents.size() - 1, aiVector3D( 1, 0, 0));
-
- // ignore all tangent streams except 0 - there can be only one tangent
- if( pInput.mIndex == 0)
- pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
- else
- DefaultLogger::get()->error("Collada: just one vertex tangent stream supported");
- break;
- case IT_Bitangent:
- // pad to current vertex count if necessary
- if( pMesh->mBitangents.size() < pMesh->mPositions.size()-1)
- pMesh->mBitangents.insert( pMesh->mBitangents.end(), pMesh->mPositions.size() - pMesh->mBitangents.size() - 1, aiVector3D( 0, 0, 1));
-
- // ignore all bitangent streams except 0 - there can be only one bitangent
- if( pInput.mIndex == 0)
- pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
- else
- DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported");
- break;
- case IT_Texcoord:
- // up to 4 texture coord sets are fine, ignore the others
- if( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS)
- {
- // pad to current vertex count if necessary
- if( pMesh->mTexCoords[pInput.mIndex].size() < pMesh->mPositions.size()-1)
- pMesh->mTexCoords[pInput.mIndex].insert( pMesh->mTexCoords[pInput.mIndex].end(),
- pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D( 0, 0, 0));
-
- pMesh->mTexCoords[pInput.mIndex].push_back( aiVector3D( obj[0], obj[1], obj[2]));
- if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
- pMesh->mNumUVComponents[pInput.mIndex]=3;
- } else
- {
- DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping.");
- }
- break;
- case IT_Color:
- // up to 4 color sets are fine, ignore the others
- if( pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS)
- {
- // pad to current vertex count if necessary
- if( pMesh->mColors[pInput.mIndex].size() < pMesh->mPositions.size()-1)
- pMesh->mColors[pInput.mIndex].insert( pMesh->mColors[pInput.mIndex].end(),
- pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D( 0, 0, 0, 1));
+ // ignore vertex referrer - we handle them that separate
+ if( pInput.mType == IT_Vertex)
+ return;
+
+ const Accessor& acc = *pInput.mResolved;
+ if( pLocalIndex >= acc.mCount)
+ ThrowException( format() << "Invalid data index (" << pLocalIndex << "/" << acc.mCount << ") in primitive specification" );
+
+ // get a pointer to the start of the data object referred to by the accessor and the local index
+ const float* dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex* acc.mStride;
+
+ // assemble according to the accessors component sub-offset list. We don't care, yet,
+ // what kind of object exactly we're extracting here
+ float obj[4];
+ for( size_t c = 0; c < 4; ++c)
+ obj[c] = dataObject[acc.mSubOffset[c]];
+
+ // now we reinterpret it according to the type we're reading here
+ switch( pInput.mType)
+ {
+ case IT_Position: // ignore all position streams except 0 - there can be only one position
+ if( pInput.mIndex == 0)
+ pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
+ else
+ DefaultLogger::get()->error("Collada: just one vertex position stream supported");
+ break;
+ case IT_Normal:
+ // pad to current vertex count if necessary
+ if( pMesh->mNormals.size() < pMesh->mPositions.size()-1)
+ pMesh->mNormals.insert( pMesh->mNormals.end(), pMesh->mPositions.size() - pMesh->mNormals.size() - 1, aiVector3D( 0, 1, 0));
+
+ // ignore all normal streams except 0 - there can be only one normal
+ if( pInput.mIndex == 0)
+ pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
+ else
+ DefaultLogger::get()->error("Collada: just one vertex normal stream supported");
+ break;
+ case IT_Tangent:
+ // pad to current vertex count if necessary
+ if( pMesh->mTangents.size() < pMesh->mPositions.size()-1)
+ pMesh->mTangents.insert( pMesh->mTangents.end(), pMesh->mPositions.size() - pMesh->mTangents.size() - 1, aiVector3D( 1, 0, 0));
+
+ // ignore all tangent streams except 0 - there can be only one tangent
+ if( pInput.mIndex == 0)
+ pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
+ else
+ DefaultLogger::get()->error("Collada: just one vertex tangent stream supported");
+ break;
+ case IT_Bitangent:
+ // pad to current vertex count if necessary
+ if( pMesh->mBitangents.size() < pMesh->mPositions.size()-1)
+ pMesh->mBitangents.insert( pMesh->mBitangents.end(), pMesh->mPositions.size() - pMesh->mBitangents.size() - 1, aiVector3D( 0, 0, 1));
+
+ // ignore all bitangent streams except 0 - there can be only one bitangent
+ if( pInput.mIndex == 0)
+ pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
+ else
+ DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported");
+ break;
+ case IT_Texcoord:
+ // up to 4 texture coord sets are fine, ignore the others
+ if( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS)
+ {
+ // pad to current vertex count if necessary
+ if( pMesh->mTexCoords[pInput.mIndex].size() < pMesh->mPositions.size()-1)
+ pMesh->mTexCoords[pInput.mIndex].insert( pMesh->mTexCoords[pInput.mIndex].end(),
+ pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D( 0, 0, 0));
+
+ pMesh->mTexCoords[pInput.mIndex].push_back( aiVector3D( obj[0], obj[1], obj[2]));
+ if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
+ pMesh->mNumUVComponents[pInput.mIndex]=3;
+ } else
+ {
+ DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping.");
+ }
+ break;
+ case IT_Color:
+ // up to 4 color sets are fine, ignore the others
+ if( pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS)
+ {
+ // pad to current vertex count if necessary
+ if( pMesh->mColors[pInput.mIndex].size() < pMesh->mPositions.size()-1)
+ pMesh->mColors[pInput.mIndex].insert( pMesh->mColors[pInput.mIndex].end(),
+ pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D( 0, 0, 0, 1));
- aiColor4D result(0, 0, 0, 1);
- for (size_t i = 0; i < pInput.mResolved->mSize; ++i)
- {
- result[i] = obj[pInput.mResolved->mSubOffset[i]];
- }
- pMesh->mColors[pInput.mIndex].push_back(result);
- } else
- {
- DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping.");
- }
+ aiColor4D result(0, 0, 0, 1);
+ for (size_t i = 0; i < pInput.mResolved->mSize; ++i)
+ {
+ result[i] = obj[pInput.mResolved->mSubOffset[i]];
+ }
+ pMesh->mColors[pInput.mIndex].push_back(result);
+ } else
+ {
+ DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping.");
+ }
- break;
- default:
- // IT_Invalid and IT_Vertex
- ai_assert(false && "shouldn't ever get here");
- }
+ break;
+ default:
+ // IT_Invalid and IT_Vertex
+ ai_assert(false && "shouldn't ever get here");
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads the library of node hierarchies and scene parts
void ColladaParser::ReadSceneLibrary()
{
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- // a visual scene - generate root node under its ID and let ReadNode() do the recursive work
- if( IsElement( "visual_scene"))
- {
- // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then?
- int indexID = GetAttribute( "id");
- const char* attrID = mReader->getAttributeValue( indexID);
-
- // read name if given.
- int indexName = TestAttribute( "name");
- const char* attrName = "unnamed";
- if( indexName > -1)
- attrName = mReader->getAttributeValue( indexName);
-
- // create a node and store it in the library under its ID
- Node* node = new Node;
- node->mID = attrID;
- node->mName = attrName;
- mNodeLibrary[node->mID] = node;
-
- ReadSceneNode( node);
- } else
- {
- // ignore the rest
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "library_visual_scenes") == 0)
- //ThrowException( "Expected end of \"library_visual_scenes\" element.");
-
- break;
- }
- }
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ // a visual scene - generate root node under its ID and let ReadNode() do the recursive work
+ if( IsElement( "visual_scene"))
+ {
+ // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then?
+ int indexID = GetAttribute( "id");
+ const char* attrID = mReader->getAttributeValue( indexID);
+
+ // read name if given.
+ int indexName = TestAttribute( "name");
+ const char* attrName = "unnamed";
+ if( indexName > -1)
+ attrName = mReader->getAttributeValue( indexName);
+
+ // create a node and store it in the library under its ID
+ Node* node = new Node;
+ node->mID = attrID;
+ node->mName = attrName;
+ mNodeLibrary[node->mID] = node;
+
+ ReadSceneNode( node);
+ } else
+ {
+ // ignore the rest
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "library_visual_scenes") == 0)
+ //ThrowException( "Expected end of \"library_visual_scenes\" element.");
+
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a scene node's contents including children and stores it in the given node
void ColladaParser::ReadSceneNode( Node* pNode)
{
- // quit immediately on <bla/> elements
- if( mReader->isEmptyElement())
- return;
-
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "node"))
- {
- Node* child = new Node;
- int attrID = TestAttribute( "id");
- if( attrID > -1)
- child->mID = mReader->getAttributeValue( attrID);
- int attrSID = TestAttribute( "sid");
- if( attrSID > -1)
- child->mSID = mReader->getAttributeValue( attrSID);
-
- int attrName = TestAttribute( "name");
- if( attrName > -1)
- child->mName = mReader->getAttributeValue( attrName);
-
- // TODO: (thom) support SIDs
- // ai_assert( TestAttribute( "sid") == -1);
-
- if (pNode)
- {
- pNode->mChildren.push_back( child);
- child->mParent = pNode;
- }
- else
- {
- // no parent node given, probably called from <library_nodes> element.
- // create new node in node library
- mNodeLibrary[child->mID] = child;
- }
+ // quit immediately on <bla/> elements
+ if( mReader->isEmptyElement())
+ return;
+
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "node"))
+ {
+ Node* child = new Node;
+ int attrID = TestAttribute( "id");
+ if( attrID > -1)
+ child->mID = mReader->getAttributeValue( attrID);
+ int attrSID = TestAttribute( "sid");
+ if( attrSID > -1)
+ child->mSID = mReader->getAttributeValue( attrSID);
+
+ int attrName = TestAttribute( "name");
+ if( attrName > -1)
+ child->mName = mReader->getAttributeValue( attrName);
+
+ // TODO: (thom) support SIDs
+ // ai_assert( TestAttribute( "sid") == -1);
+
+ if (pNode)
+ {
+ pNode->mChildren.push_back( child);
+ child->mParent = pNode;
+ }
+ else
+ {
+ // no parent node given, probably called from <library_nodes> element.
+ // create new node in node library
+ mNodeLibrary[child->mID] = child;
+ }
- // read on recursively from there
- ReadSceneNode( child);
- continue;
- }
- // For any further stuff we need a valid node to work on
- else if (!pNode)
- continue;
-
- if( IsElement( "lookat"))
- ReadNodeTransformation( pNode, TF_LOOKAT);
- else if( IsElement( "matrix"))
- ReadNodeTransformation( pNode, TF_MATRIX);
- else if( IsElement( "rotate"))
- ReadNodeTransformation( pNode, TF_ROTATE);
- else if( IsElement( "scale"))
- ReadNodeTransformation( pNode, TF_SCALE);
- else if( IsElement( "skew"))
- ReadNodeTransformation( pNode, TF_SKEW);
- else if( IsElement( "translate"))
- ReadNodeTransformation( pNode, TF_TRANSLATE);
- else if( IsElement( "render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length())
- {
- // ... scene evaluation or, in other words, postprocessing pipeline,
- // or, again in other words, a turing-complete description how to
- // render a Collada scene. The only thing that is interesting for
- // us is the primary camera.
- int attrId = TestAttribute("camera_node");
- if (-1 != attrId)
- {
- const char* s = mReader->getAttributeValue(attrId);
- if (s[0] != '#')
- DefaultLogger::get()->error("Collada: Unresolved reference format of camera");
- else
- pNode->mPrimaryCamera = s+1;
- }
- }
- else if( IsElement( "instance_node"))
- {
- // find the node in the library
- int attrID = TestAttribute( "url");
- if( attrID != -1)
- {
- const char* s = mReader->getAttributeValue(attrID);
- if (s[0] != '#')
- DefaultLogger::get()->error("Collada: Unresolved reference format of node");
- else
- {
- pNode->mNodeInstances.push_back(NodeInstance());
- pNode->mNodeInstances.back().mNode = s+1;
- }
- }
- }
- else if( IsElement( "instance_geometry") || IsElement( "instance_controller"))
- {
- // Reference to a mesh or controller, with possible material associations
- ReadNodeGeometry( pNode);
- }
- else if( IsElement( "instance_light"))
- {
- // Reference to a light, name given in 'url' attribute
- int attrID = TestAttribute("url");
- if (-1 == attrID)
- DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_light> element");
- else
- {
- const char* url = mReader->getAttributeValue( attrID);
- if( url[0] != '#')
- ThrowException( "Unknown reference format in <instance_light> element");
+ // read on recursively from there
+ ReadSceneNode( child);
+ continue;
+ }
+ // For any further stuff we need a valid node to work on
+ else if (!pNode)
+ continue;
+
+ if( IsElement( "lookat"))
+ ReadNodeTransformation( pNode, TF_LOOKAT);
+ else if( IsElement( "matrix"))
+ ReadNodeTransformation( pNode, TF_MATRIX);
+ else if( IsElement( "rotate"))
+ ReadNodeTransformation( pNode, TF_ROTATE);
+ else if( IsElement( "scale"))
+ ReadNodeTransformation( pNode, TF_SCALE);
+ else if( IsElement( "skew"))
+ ReadNodeTransformation( pNode, TF_SKEW);
+ else if( IsElement( "translate"))
+ ReadNodeTransformation( pNode, TF_TRANSLATE);
+ else if( IsElement( "render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length())
+ {
+ // ... scene evaluation or, in other words, postprocessing pipeline,
+ // or, again in other words, a turing-complete description how to
+ // render a Collada scene. The only thing that is interesting for
+ // us is the primary camera.
+ int attrId = TestAttribute("camera_node");
+ if (-1 != attrId)
+ {
+ const char* s = mReader->getAttributeValue(attrId);
+ if (s[0] != '#')
+ DefaultLogger::get()->error("Collada: Unresolved reference format of camera");
+ else
+ pNode->mPrimaryCamera = s+1;
+ }
+ }
+ else if( IsElement( "instance_node"))
+ {
+ // find the node in the library
+ int attrID = TestAttribute( "url");
+ if( attrID != -1)
+ {
+ const char* s = mReader->getAttributeValue(attrID);
+ if (s[0] != '#')
+ DefaultLogger::get()->error("Collada: Unresolved reference format of node");
+ else
+ {
+ pNode->mNodeInstances.push_back(NodeInstance());
+ pNode->mNodeInstances.back().mNode = s+1;
+ }
+ }
+ }
+ else if( IsElement( "instance_geometry") || IsElement( "instance_controller"))
+ {
+ // Reference to a mesh or controller, with possible material associations
+ ReadNodeGeometry( pNode);
+ }
+ else if( IsElement( "instance_light"))
+ {
+ // Reference to a light, name given in 'url' attribute
+ int attrID = TestAttribute("url");
+ if (-1 == attrID)
+ DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_light> element");
+ else
+ {
+ const char* url = mReader->getAttributeValue( attrID);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format in <instance_light> element");
- pNode->mLights.push_back(LightInstance());
- pNode->mLights.back().mLight = url+1;
- }
- }
- else if( IsElement( "instance_camera"))
- {
- // Reference to a camera, name given in 'url' attribute
- int attrID = TestAttribute("url");
- if (-1 == attrID)
- DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_camera> element");
- else
- {
- const char* url = mReader->getAttributeValue( attrID);
- if( url[0] != '#')
- ThrowException( "Unknown reference format in <instance_camera> element");
+ pNode->mLights.push_back(LightInstance());
+ pNode->mLights.back().mLight = url+1;
+ }
+ }
+ else if( IsElement( "instance_camera"))
+ {
+ // Reference to a camera, name given in 'url' attribute
+ int attrID = TestAttribute("url");
+ if (-1 == attrID)
+ DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_camera> element");
+ else
+ {
+ const char* url = mReader->getAttributeValue( attrID);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format in <instance_camera> element");
- pNode->mCameras.push_back(CameraInstance());
- pNode->mCameras.back().mCamera = url+1;
- }
- }
- else
- {
- // skip everything else for the moment
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- break;
- }
- }
+ pNode->mCameras.push_back(CameraInstance());
+ pNode->mCameras.back().mCamera = url+1;
+ }
+ }
+ else
+ {
+ // skip everything else for the moment
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a node transformation entry of the given type and adds it to the given node's transformation list.
void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType)
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
- std::string tagName = mReader->getNodeName();
+ std::string tagName = mReader->getNodeName();
- Transform tf;
- tf.mType = pType;
-
- // read SID
- int indexSID = TestAttribute( "sid");
- if( indexSID >= 0)
- tf.mID = mReader->getAttributeValue( indexSID);
+ Transform tf;
+ tf.mType = pType;
- // how many parameters to read per transformation type
- static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
- const char* content = GetTextContent();
+ // read SID
+ int indexSID = TestAttribute( "sid");
+ if( indexSID >= 0)
+ tf.mID = mReader->getAttributeValue( indexSID);
- // read as many parameters and store in the transformation
- for( unsigned int a = 0; a < sNumParameters[pType]; a++)
- {
- // read a number
- content = fast_atoreal_move<float>( content, tf.f[a]);
- // skip whitespace after it
- SkipSpacesAndLineEnd( &content);
- }
+ // how many parameters to read per transformation type
+ static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
+ const char* content = GetTextContent();
+
+ // read as many parameters and store in the transformation
+ for( unsigned int a = 0; a < sNumParameters[pType]; a++)
+ {
+ // read a number
+ content = fast_atoreal_move<float>( content, tf.f[a]);
+ // skip whitespace after it
+ SkipSpacesAndLineEnd( &content);
+ }
- // place the transformation at the queue of the node
- pNode->mTransforms.push_back( tf);
+ // place the transformation at the queue of the node
+ pNode->mTransforms.push_back( tf);
- // and consume the closing tag
- TestClosing( tagName.c_str());
+ // and consume the closing tag
+ TestClosing( tagName.c_str());
}
// ------------------------------------------------------------------------------------------------
// Processes bind_vertex_input and bind elements
void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl)
{
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "bind_vertex_input"))
- {
- Collada::InputSemanticMapEntry vn;
-
- // effect semantic
- int n = GetAttribute("semantic");
- std::string s = mReader->getAttributeValue(n);
-
- // input semantic
- n = GetAttribute("input_semantic");
- vn.mType = GetTypeForSemantic( mReader->getAttributeValue(n) );
-
- // index of input set
- n = TestAttribute("input_set");
- if (-1 != n)
- vn.mSet = mReader->getAttributeValueAsInt(n);
-
- tbl.mMap[s] = vn;
- }
- else if( IsElement( "bind")) {
- DefaultLogger::get()->warn("Collada: Found unsupported <bind> element");
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
- if( strcmp( mReader->getNodeName(), "instance_material") == 0)
- break;
- }
- }
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "bind_vertex_input"))
+ {
+ Collada::InputSemanticMapEntry vn;
+
+ // effect semantic
+ int n = GetAttribute("semantic");
+ std::string s = mReader->getAttributeValue(n);
+
+ // input semantic
+ n = GetAttribute("input_semantic");
+ vn.mType = GetTypeForSemantic( mReader->getAttributeValue(n) );
+
+ // index of input set
+ n = TestAttribute("input_set");
+ if (-1 != n)
+ vn.mSet = mReader->getAttributeValueAsInt(n);
+
+ tbl.mMap[s] = vn;
+ }
+ else if( IsElement( "bind")) {
+ DefaultLogger::get()->warn("Collada: Found unsupported <bind> element");
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+ if( strcmp( mReader->getNodeName(), "instance_material") == 0)
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Reads a mesh reference in a node and adds it to the node's mesh list
void ColladaParser::ReadNodeGeometry( Node* pNode)
{
- // referred mesh is given as an attribute of the <instance_geometry> element
- int attrUrl = GetAttribute( "url");
- const char* url = mReader->getAttributeValue( attrUrl);
- if( url[0] != '#')
- ThrowException( "Unknown reference format");
-
- Collada::MeshInstance instance;
- instance.mMeshOrController = url+1; // skipping the leading #
-
- if( !mReader->isEmptyElement())
- {
- // read material associations. Ignore additional elements inbetween
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
- {
- if( IsElement( "instance_material"))
- {
- // read ID of the geometry subgroup and the target material
- int attrGroup = GetAttribute( "symbol");
- std::string group = mReader->getAttributeValue( attrGroup);
- int attrMaterial = GetAttribute( "target");
- const char* urlMat = mReader->getAttributeValue( attrMaterial);
- Collada::SemanticMappingTable s;
- if( urlMat[0] == '#')
- urlMat++;
-
- s.mMatName = urlMat;
-
- // resolve further material details + THIS UGLY AND NASTY semantic mapping stuff
- if( !mReader->isEmptyElement())
- ReadMaterialVertexInputBinding(s);
-
- // store the association
- instance.mMaterials[group] = s;
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- {
- if( strcmp( mReader->getNodeName(), "instance_geometry") == 0
- || strcmp( mReader->getNodeName(), "instance_controller") == 0)
- break;
- }
- }
- }
+ // referred mesh is given as an attribute of the <instance_geometry> element
+ int attrUrl = GetAttribute( "url");
+ const char* url = mReader->getAttributeValue( attrUrl);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format");
+
+ Collada::MeshInstance instance;
+ instance.mMeshOrController = url+1; // skipping the leading #
+
+ if( !mReader->isEmptyElement())
+ {
+ // read material associations. Ignore additional elements inbetween
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ if( IsElement( "instance_material"))
+ {
+ // read ID of the geometry subgroup and the target material
+ int attrGroup = GetAttribute( "symbol");
+ std::string group = mReader->getAttributeValue( attrGroup);
+ int attrMaterial = GetAttribute( "target");
+ const char* urlMat = mReader->getAttributeValue( attrMaterial);
+ Collada::SemanticMappingTable s;
+ if( urlMat[0] == '#')
+ urlMat++;
+
+ s.mMatName = urlMat;
+
+ // resolve further material details + THIS UGLY AND NASTY semantic mapping stuff
+ if( !mReader->isEmptyElement())
+ ReadMaterialVertexInputBinding(s);
+
+ // store the association
+ instance.mMaterials[group] = s;
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if( strcmp( mReader->getNodeName(), "instance_geometry") == 0
+ || strcmp( mReader->getNodeName(), "instance_controller") == 0)
+ break;
+ }
+ }
+ }
- // store it
- pNode->mMeshes.push_back( instance);
+ // store it
+ pNode->mMeshes.push_back( instance);
}
// ------------------------------------------------------------------------------------------------
// Reads the collada scene
void ColladaParser::ReadScene()
{
- if( mReader->isEmptyElement())
- return;
+ if( mReader->isEmptyElement())
+ return;
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
- if( IsElement( "instance_visual_scene"))
- {
- // should be the first and only occurence
- if( mRootNode)
- ThrowException( "Invalid scene containing multiple root nodes in <instance_visual_scene> element");
-
- // read the url of the scene to instance. Should be of format "#some_name"
- int urlIndex = GetAttribute( "url");
- const char* url = mReader->getAttributeValue( urlIndex);
- if( url[0] != '#')
- ThrowException( "Unknown reference format in <instance_visual_scene> element");
-
- // find the referred scene, skip the leading #
- NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1);
- if( sit == mNodeLibrary.end())
- ThrowException( "Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
- mRootNode = sit->second;
- } else {
- SkipElement();
- }
- }
- else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
- break;
- }
- }
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ if( IsElement( "instance_visual_scene"))
+ {
+ // should be the first and only occurrence
+ if( mRootNode)
+ ThrowException( "Invalid scene containing multiple root nodes in <instance_visual_scene> element");
+
+ // read the url of the scene to instance. Should be of format "#some_name"
+ int urlIndex = GetAttribute( "url");
+ const char* url = mReader->getAttributeValue( urlIndex);
+ if( url[0] != '#')
+ ThrowException( "Unknown reference format in <instance_visual_scene> element");
+
+ // find the referred scene, skip the leading #
+ NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1);
+ if( sit == mNodeLibrary.end())
+ ThrowException( "Unable to resolve visual_scene reference \"" + std::string(url) + "\" in <instance_visual_scene> element.");
+ mRootNode = sit->second;
+ } else {
+ SkipElement();
+ }
+ }
+ else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception
-void ColladaParser::ThrowException( const std::string& pError) const
+AI_WONT_RETURN void ColladaParser::ThrowException( const std::string& pError) const
{
- throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError));
+ throw DeadlyImportError( format() << "Collada: " << mFileName << " - " << pError );
}
+void ColladaParser::ReportWarning(const char* msg,...)
+{
+ ai_assert(NULL != msg);
+
+ va_list args;
+ va_start(args,msg);
+
+ char szBuffer[3000];
+ const int iLen = vsprintf(szBuffer,msg,args);
+ ai_assert(iLen > 0);
+
+ va_end(args);
+ DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
+}
+
// ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the current element
void ColladaParser::SkipElement()
{
- // nothing to skip if it's an <element />
- if( mReader->isEmptyElement())
- return;
+ // nothing to skip if it's an <element />
+ if( mReader->isEmptyElement())
+ return;
- // reroute
- SkipElement( mReader->getNodeName());
+ // reroute
+ SkipElement( mReader->getNodeName());
}
// ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the given element
void ColladaParser::SkipElement( const char* pElement)
{
- // copy the current node's name because it'a pointer to the reader's internal buffer,
- // which is going to change with the upcoming parsing
- std::string element = pElement;
- while( mReader->read())
- {
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
- if( mReader->getNodeName() == element)
- break;
- }
+ // copy the current node's name because it'a pointer to the reader's internal buffer,
+ // which is going to change with the upcoming parsing
+ std::string element = pElement;
+ while( mReader->read())
+ {
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ if( mReader->getNodeName() == element)
+ break;
+ }
}
// ------------------------------------------------------------------------------------------------
// Tests for an opening element of the given name, throws an exception if not found
void ColladaParser::TestOpening( const char* pName)
{
- // read element start
- if( !mReader->read())
- ThrowException( boost::str( boost::format( "Unexpected end of file while beginning of <%s> element.") % pName));
- // whitespace in front is ok, just read again if found
- if( mReader->getNodeType() == irr::io::EXN_TEXT)
- if( !mReader->read())
- ThrowException( boost::str( boost::format( "Unexpected end of file while reading beginning of <%s> element.") % pName));
-
- if( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0)
- ThrowException( boost::str( boost::format( "Expected start of <%s> element.") % pName));
+ // read element start
+ if( !mReader->read())
+ ThrowException( format() << "Unexpected end of file while beginning of <" << pName << "> element." );
+ // whitespace in front is ok, just read again if found
+ if( mReader->getNodeType() == irr::io::EXN_TEXT)
+ if( !mReader->read())
+ ThrowException( format() << "Unexpected end of file while reading beginning of <" << pName << "> element." );
+
+ if( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0)
+ ThrowException( format() << "Expected start of <" << pName << "> element." );
}
// ------------------------------------------------------------------------------------------------
// Tests for the closing tag of the given element, throws an exception if not found
void ColladaParser::TestClosing( const char* pName)
{
- // check if we're already on the closing tag and return right away
- if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp( mReader->getNodeName(), pName) == 0)
- return;
-
- // if not, read some more
- if( !mReader->read())
- ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of <%s> element.") % pName));
- // whitespace in front is ok, just read again if found
- if( mReader->getNodeType() == irr::io::EXN_TEXT)
- if( !mReader->read())
- ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of <%s> element.") % pName));
-
- // but this has the be the closing tag, or we're lost
- if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
- ThrowException( boost::str( boost::format( "Expected end of <%s> element.") % pName));
+ // check if we're already on the closing tag and return right away
+ if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp( mReader->getNodeName(), pName) == 0)
+ return;
+
+ // if not, read some more
+ if( !mReader->read())
+ ThrowException( format() << "Unexpected end of file while reading end of <" << pName << "> element." );
+ // whitespace in front is ok, just read again if found
+ if( mReader->getNodeType() == irr::io::EXN_TEXT)
+ if( !mReader->read())
+ ThrowException( format() << "Unexpected end of file while reading end of <" << pName << "> element." );
+
+ // but this has the be the closing tag, or we're lost
+ if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
+ ThrowException( format() << "Expected end of <" << pName << "> element." );
}
// ------------------------------------------------------------------------------------------------
// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes
int ColladaParser::GetAttribute( const char* pAttr) const
{
- int index = TestAttribute( pAttr);
- if( index != -1)
- return index;
+ int index = TestAttribute( pAttr);
+ if( index != -1)
+ return index;
- // attribute not found -> throw an exception
- ThrowException( boost::str( boost::format( "Expected attribute \"%s\" for element <%s>.") % pAttr % mReader->getNodeName()));
- return -1;
+ // attribute not found -> throw an exception
+ ThrowException( format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">." );
+ return -1;
}
// ------------------------------------------------------------------------------------------------
// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found
int ColladaParser::TestAttribute( const char* pAttr) const
{
- for( int a = 0; a < mReader->getAttributeCount(); a++)
- if( strcmp( mReader->getAttributeName( a), pAttr) == 0)
- return a;
+ for( int a = 0; a < mReader->getAttributeCount(); a++)
+ if( strcmp( mReader->getAttributeName( a), pAttr) == 0)
+ return a;
- return -1;
+ return -1;
}
// ------------------------------------------------------------------------------------------------
// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace.
const char* ColladaParser::GetTextContent()
{
- const char* sz = TestTextContent();
- if(!sz) {
- ThrowException( "Invalid contents in element \"n\".");
- }
- return sz;
+ const char* sz = TestTextContent();
+ if(!sz) {
+ ThrowException( "Invalid contents in element \"n\".");
+ }
+ return sz;
}
// ------------------------------------------------------------------------------------------------
// Reads the text contents of an element, returns NULL if not given. Skips leading whitespace.
const char* ColladaParser::TestTextContent()
{
- // present node should be the beginning of an element
- if( mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
- return NULL;
+ // present node should be the beginning of an element
+ if( mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement())
+ return NULL;
- // read contents of the element
- if( !mReader->read() )
- return NULL;
- if( mReader->getNodeType() != irr::io::EXN_TEXT)
- return NULL;
+ // read contents of the element
+ if( !mReader->read() )
+ return NULL;
+ if( mReader->getNodeType() != irr::io::EXN_TEXT)
+ return NULL;
- // skip leading whitespace
- const char* text = mReader->getNodeData();
- SkipSpacesAndLineEnd( &text);
+ // skip leading whitespace
+ const char* text = mReader->getNodeData();
+ SkipSpacesAndLineEnd( &text);
- return text;
+ return text;
}
// ------------------------------------------------------------------------------------------------
// Calculates the resulting transformation fromm all the given transform steps
aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform>& pTransforms) const
{
- aiMatrix4x4 res;
-
- for( std::vector<Transform>::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it)
- {
- const Transform& tf = *it;
- switch( tf.mType)
- {
- case TF_LOOKAT:
+ aiMatrix4x4 res;
+
+ for( std::vector<Transform>::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it)
+ {
+ const Transform& tf = *it;
+ switch( tf.mType)
+ {
+ case TF_LOOKAT:
{
aiVector3D pos( tf.f[0], tf.f[1], tf.f[2]);
aiVector3D dstPos( tf.f[3], tf.f[4], tf.f[5]);
@@ -2795,77 +3107,82 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
aiVector3D dir = aiVector3D( dstPos - pos).Normalize();
aiVector3D right = (dir ^ up).Normalize();
- res *= aiMatrix4x4(
- right.x, up.x, -dir.x, pos.x,
+ res *= aiMatrix4x4(
+ right.x, up.x, -dir.x, pos.x,
right.y, up.y, -dir.y, pos.y,
right.z, up.z, -dir.z, pos.z,
0, 0, 0, 1);
- break;
+ break;
}
- case TF_ROTATE:
- {
- aiMatrix4x4 rot;
- float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f;
- aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]);
- aiMatrix4x4::Rotation( angle, axis, rot);
- res *= rot;
- break;
- }
- case TF_TRANSLATE:
- {
- aiMatrix4x4 trans;
- aiMatrix4x4::Translation( aiVector3D( tf.f[0], tf.f[1], tf.f[2]), trans);
- res *= trans;
- break;
- }
- case TF_SCALE:
- {
- aiMatrix4x4 scale( tf.f[0], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[1], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[2], 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f);
- res *= scale;
- break;
- }
- case TF_SKEW:
- // TODO: (thom)
- ai_assert( false);
- break;
- case TF_MATRIX:
- {
- aiMatrix4x4 mat( tf.f[0], tf.f[1], tf.f[2], tf.f[3], tf.f[4], tf.f[5], tf.f[6], tf.f[7],
- tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]);
- res *= mat;
- break;
- }
- default:
- ai_assert( false);
- break;
- }
- }
+ case TF_ROTATE:
+ {
+ aiMatrix4x4 rot;
+ float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f;
+ aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]);
+ aiMatrix4x4::Rotation( angle, axis, rot);
+ res *= rot;
+ break;
+ }
+ case TF_TRANSLATE:
+ {
+ aiMatrix4x4 trans;
+ aiMatrix4x4::Translation( aiVector3D( tf.f[0], tf.f[1], tf.f[2]), trans);
+ res *= trans;
+ break;
+ }
+ case TF_SCALE:
+ {
+ aiMatrix4x4 scale( tf.f[0], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[1], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[2], 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ res *= scale;
+ break;
+ }
+ case TF_SKEW:
+ // TODO: (thom)
+ ai_assert( false);
+ break;
+ case TF_MATRIX:
+ {
+ aiMatrix4x4 mat( tf.f[0], tf.f[1], tf.f[2], tf.f[3], tf.f[4], tf.f[5], tf.f[6], tf.f[7],
+ tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]);
+ res *= mat;
+ break;
+ }
+ default:
+ ai_assert( false);
+ break;
+ }
+ }
- return res;
+ return res;
}
// ------------------------------------------------------------------------------------------------
// Determines the input data type for the given semantic string
-Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
+Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semantic)
{
- if( pSemantic == "POSITION")
- return IT_Position;
- else if( pSemantic == "TEXCOORD")
- return IT_Texcoord;
- else if( pSemantic == "NORMAL")
- return IT_Normal;
- else if( pSemantic == "COLOR")
- return IT_Color;
- else if( pSemantic == "VERTEX")
- return IT_Vertex;
- else if( pSemantic == "BINORMAL" || pSemantic == "TEXBINORMAL")
- return IT_Bitangent;
- else if( pSemantic == "TANGENT" || pSemantic == "TEXTANGENT")
- return IT_Tangent;
-
- DefaultLogger::get()->warn( boost::str( boost::format( "Unknown vertex input type \"%s\". Ignoring.") % pSemantic));
- return IT_Invalid;
+ if ( semantic.empty() ) {
+ DefaultLogger::get()->warn( format() << "Vertex input type is empty." );
+ return IT_Invalid;
+ }
+
+ if( semantic == "POSITION")
+ return IT_Position;
+ else if( semantic == "TEXCOORD")
+ return IT_Texcoord;
+ else if( semantic == "NORMAL")
+ return IT_Normal;
+ else if( semantic == "COLOR")
+ return IT_Color;
+ else if( semantic == "VERTEX")
+ return IT_Vertex;
+ else if( semantic == "BINORMAL" || semantic == "TEXBINORMAL")
+ return IT_Bitangent;
+ else if( semantic == "TANGENT" || semantic == "TEXTANGENT")
+ return IT_Tangent;
+
+ DefaultLogger::get()->warn( format() << "Unknown vertex input type \"" << semantic << "\". Ignoring." );
+ return IT_Invalid;
}
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
diff --git a/src/3rdparty/assimp/code/ColladaParser.h b/src/3rdparty/assimp/code/ColladaParser.h
index ee764a23b..9193e2027 100644
--- a/src/3rdparty/assimp/code/ColladaParser.h
+++ b/src/3rdparty/assimp/code/ColladaParser.h
@@ -1,45 +1,45 @@
/*
-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.
-
-----------------------------------------------------------------------
-*/
+ 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.
+
+ ----------------------------------------------------------------------
+ */
/** @file ColladaParser.h
- * @brief Defines the parser helper class for the collada loader
+ * @brief Defines the parser helper class for the collada loader
*/
#ifndef AI_COLLADAPARSER_H_INC
@@ -47,294 +47,321 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "irrXMLWrapper.h"
#include "ColladaHelper.h"
+#include <assimp/ai_assert.h>
+#include "TinyFormatter.h"
+#include <memory>
namespace Assimp
{
-// ------------------------------------------------------------------------------------------
-/** Parser helper class for the Collada loader.
- *
- * Does all the XML reading and builds internal data structures from it,
- * but leaves the resolving of all the references to the loader.
-*/
-class ColladaParser
-{
- friend class ColladaLoader;
+ // ------------------------------------------------------------------------------------------
+ /** Parser helper class for the Collada loader.
+ *
+ * Does all the XML reading and builds internal data structures from it,
+ * but leaves the resolving of all the references to the loader.
+ */
+ class ColladaParser
+ {
+ friend class ColladaLoader;
-protected:
- /** Constructor from XML file */
- ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
+ protected:
+ /** Constructor from XML file */
+ ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
- /** Destructor */
- ~ColladaParser();
+ /** Destructor */
+ ~ColladaParser();
- /** Reads the contents of the file */
- void ReadContents();
+ /** Reads the contents of the file */
+ void ReadContents();
- /** Reads the structure of the file */
- void ReadStructure();
+ /** Reads the structure of the file */
+ void ReadStructure();
- /** Reads asset informations such as coordinate system informations and legal blah */
- void ReadAssetInfo();
+ /** Reads asset informations such as coordinate system informations and legal blah */
+ void ReadAssetInfo();
- /** Reads the animation library */
- void ReadAnimationLibrary();
+ /** Reads the animation library */
+ void ReadAnimationLibrary();
- /** Reads an animation into the given parent structure */
- void ReadAnimation( Collada::Animation* pParent);
+ /** Reads the animation clip library */
+ void ReadAnimationClipLibrary();
- /** Reads an animation sampler into the given anim channel */
- void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
+ /** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
+ void PostProcessRootAnimations();
- /** Reads the skeleton controller library */
- void ReadControllerLibrary();
+ /** Reads an animation into the given parent structure */
+ void ReadAnimation( Collada::Animation* pParent);
- /** Reads a controller into the given mesh structure */
- void ReadController( Collada::Controller& pController);
+ /** Reads an animation sampler into the given anim channel */
+ void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
- /** Reads the joint definitions for the given controller */
- void ReadControllerJoints( Collada::Controller& pController);
+ /** Reads the skeleton controller library */
+ void ReadControllerLibrary();
- /** Reads the joint weights for the given controller */
- void ReadControllerWeights( Collada::Controller& pController);
+ /** Reads a controller into the given mesh structure */
+ void ReadController( Collada::Controller& pController);
- /** Reads the image library contents */
- void ReadImageLibrary();
+ /** Reads the joint definitions for the given controller */
+ void ReadControllerJoints( Collada::Controller& pController);
- /** Reads an image entry into the given image */
- void ReadImage( Collada::Image& pImage);
+ /** Reads the joint weights for the given controller */
+ void ReadControllerWeights( Collada::Controller& pController);
- /** Reads the material library */
- void ReadMaterialLibrary();
+ /** Reads the image library contents */
+ void ReadImageLibrary();
- /** Reads a material entry into the given material */
- void ReadMaterial( Collada::Material& pMaterial);
+ /** Reads an image entry into the given image */
+ void ReadImage( Collada::Image& pImage);
- /** Reads the camera library */
- void ReadCameraLibrary();
+ /** Reads the material library */
+ void ReadMaterialLibrary();
- /** Reads a camera entry into the given camera */
- void ReadCamera( Collada::Camera& pCamera);
+ /** Reads a material entry into the given material */
+ void ReadMaterial( Collada::Material& pMaterial);
- /** Reads the light library */
- void ReadLightLibrary();
+ /** Reads the camera library */
+ void ReadCameraLibrary();
- /** Reads a light entry into the given light */
- void ReadLight( Collada::Light& pLight);
+ /** Reads a camera entry into the given camera */
+ void ReadCamera( Collada::Camera& pCamera);
- /** Reads the effect library */
- void ReadEffectLibrary();
+ /** Reads the light library */
+ void ReadLightLibrary();
- /** Reads an effect entry into the given effect*/
- void ReadEffect( Collada::Effect& pEffect);
+ /** Reads a light entry into the given light */
+ void ReadLight( Collada::Light& pLight);
- /** Reads an COMMON effect profile */
- void ReadEffectProfileCommon( Collada::Effect& pEffect);
+ /** Reads the effect library */
+ void ReadEffectLibrary();
- /** Read sampler properties */
- void ReadSamplerProperties( Collada::Sampler& pSampler);
+ /** Reads an effect entry into the given effect*/
+ void ReadEffect( Collada::Effect& pEffect);
- /** Reads an effect entry containing a color or a texture defining that color */
- void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
+ /** Reads an COMMON effect profile */
+ void ReadEffectProfileCommon( Collada::Effect& pEffect);
- /** Reads an effect entry containing a float */
- void ReadEffectFloat( float& pFloat);
+ /** Read sampler properties */
+ void ReadSamplerProperties( Collada::Sampler& pSampler);
- /** Reads an effect parameter specification of any kind */
- void ReadEffectParam( Collada::EffectParam& pParam);
+ /** Reads an effect entry containing a color or a texture defining that color */
+ void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
- /** Reads the geometry library contents */
- void ReadGeometryLibrary();
+ /** Reads an effect entry containing a float */
+ void ReadEffectFloat( float& pFloat);
- /** Reads a geometry from the geometry library. */
- void ReadGeometry( Collada::Mesh* pMesh);
+ /** Reads an effect parameter specification of any kind */
+ void ReadEffectParam( Collada::EffectParam& pParam);
- /** Reads a mesh from the geometry library */
- void ReadMesh( Collada::Mesh* pMesh);
+ /** Reads the geometry library contents */
+ void ReadGeometryLibrary();
- /** Reads a source element - a combination of raw data and an accessor defining
- * things that should not be redefinable. Yes, that's another rant.
- */
- void ReadSource();
+ /** Reads a geometry from the geometry library. */
+ void ReadGeometry( Collada::Mesh* pMesh);
- /** Reads a data array holding a number of elements, and stores it in the global library.
- * Currently supported are array of floats and arrays of strings.
- */
- void ReadDataArray();
+ /** Reads a mesh from the geometry library */
+ void ReadMesh( Collada::Mesh* pMesh);
- /** Reads an accessor and stores it in the global library under the given ID -
- * accessors use the ID of the parent <source> element
- */
- void ReadAccessor( const std::string& pID);
+ /** Reads a source element - a combination of raw data and an accessor defining
+ * things that should not be redefinable. Yes, that's another rant.
+ */
+ void ReadSource();
- /** Reads input declarations of per-vertex mesh data into the given mesh */
- void ReadVertexData( Collada::Mesh* pMesh);
+ /** Reads a data array holding a number of elements, and stores it in the global library.
+ * Currently supported are array of floats and arrays of strings.
+ */
+ void ReadDataArray();
- /** Reads input declarations of per-index mesh data into the given mesh */
- void ReadIndexData( Collada::Mesh* pMesh);
+ /** Reads an accessor and stores it in the global library under the given ID -
+ * accessors use the ID of the parent <source> element
+ */
+ void ReadAccessor( const std::string& pID);
- /** Reads a single input channel element and stores it in the given array, if valid */
- void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
+ /** Reads input declarations of per-vertex mesh data into the given mesh */
+ void ReadVertexData( Collada::Mesh* pMesh);
- /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
- void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
- size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
+ /** Reads input declarations of per-index mesh data into the given mesh */
+ void ReadIndexData( Collada::Mesh* pMesh);
- /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
- void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
+ /** Reads a single input channel element and stores it in the given array, if valid */
+ void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
- /** Reads the library of node hierarchies and scene parts */
- void ReadSceneLibrary();
+ /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
+ size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
+ size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
- /** Reads a scene node's contents including children and stores it in the given node */
- void ReadSceneNode( Collada::Node* pNode);
+ /** Copies the data for a single primitive into the mesh, based on the InputChannels */
+ void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
+ Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
+ size_t currentPrimitive, const std::vector<size_t>& indices);
- /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
- void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
+ /** Reads one triangle of a tristrip into the mesh */
+ void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
+ std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
- /** Reads a mesh reference in a node and adds it to the node's mesh list */
- void ReadNodeGeometry( Collada::Node* pNode);
+ /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
+ void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
- /** Reads the collada scene */
- void ReadScene();
+ /** Reads the library of node hierarchies and scene parts */
+ void ReadSceneLibrary();
- // Processes bind_vertex_input and bind elements
- void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
+ /** Reads a scene node's contents including children and stores it in the given node */
+ void ReadSceneNode( Collada::Node* pNode);
-protected:
- /** Aborts the file reading with an exception */
- void ThrowException( const std::string& pError) const;
+ /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
+ void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
- /** Skips all data until the end node of the current element */
- void SkipElement();
+ /** Reads a mesh reference in a node and adds it to the node's mesh list */
+ void ReadNodeGeometry( Collada::Node* pNode);
- /** Skips all data until the end node of the given element */
- void SkipElement( const char* pElement);
+ /** Reads the collada scene */
+ void ReadScene();
- /** Compares the current xml element name to the given string and returns true if equal */
- bool IsElement( const char* pName) const;
+ // Processes bind_vertex_input and bind elements
+ void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
- /** Tests for the opening tag of the given element, throws an exception if not found */
- void TestOpening( const char* pName);
+ protected:
+ /** Aborts the file reading with an exception */
+ AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
+ void ReportWarning(const char* msg,...);
- /** Tests for the closing tag of the given element, throws an exception if not found */
- void TestClosing( const char* pName);
+ /** Skips all data until the end node of the current element */
+ void SkipElement();
- /** Checks the present element for the presence of the attribute, returns its index
- or throws an exception if not found */
- int GetAttribute( const char* pAttr) const;
+ /** Skips all data until the end node of the given element */
+ void SkipElement( const char* pElement);
- /** Returns the index of the named attribute or -1 if not found. Does not throw,
- therefore useful for optional attributes */
- int TestAttribute( const char* pAttr) const;
+ /** Compares the current xml element name to the given string and returns true if equal */
+ bool IsElement( const char* pName) const;
- /** Reads the text contents of an element, throws an exception if not given.
- Skips leading whitespace. */
- const char* GetTextContent();
+ /** Tests for the opening tag of the given element, throws an exception if not found */
+ void TestOpening( const char* pName);
- /** Reads the text contents of an element, returns NULL if not given.
- Skips leading whitespace. */
- const char* TestTextContent();
+ /** Tests for the closing tag of the given element, throws an exception if not found */
+ void TestClosing( const char* pName);
- /** Reads a single bool from current text content */
- bool ReadBoolFromTextContent();
+ /** Checks the present element for the presence of the attribute, returns its index
+ or throws an exception if not found */
+ int GetAttribute( const char* pAttr) const;
- /** Reads a single float from current text content */
- float ReadFloatFromTextContent();
+ /** Returns the index of the named attribute or -1 if not found. Does not throw,
+ therefore useful for optional attributes */
+ int TestAttribute( const char* pAttr) const;
- /** Calculates the resulting transformation from all the given transform steps */
- aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
+ /** Reads the text contents of an element, throws an exception if not given.
+ Skips leading whitespace. */
+ const char* GetTextContent();
- /** Determines the input data type for the given semantic string */
- Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
+ /** Reads the text contents of an element, returns NULL if not given.
+ Skips leading whitespace. */
+ const char* TestTextContent();
- /** Finds the item in the given library by its reference, throws if not found */
- template <typename Type> const Type& ResolveLibraryReference(
- const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
+ /** Reads a single bool from current text content */
+ bool ReadBoolFromTextContent();
-protected:
- /** Filename, for a verbose error message */
- std::string mFileName;
+ /** Reads a single float from current text content */
+ float ReadFloatFromTextContent();
- /** XML reader, member for everyday use */
- irr::io::IrrXMLReader* mReader;
+ /** Calculates the resulting transformation from all the given transform steps */
+ aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
- /** All data arrays found in the file by ID. Might be referred to by actually
- everyone. Collada, you are a steaming pile of indirection. */
- typedef std::map<std::string, Collada::Data> DataLibrary;
- DataLibrary mDataLibrary;
+ /** Determines the input data type for the given semantic string */
+ Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
- /** Same for accessors which define how the data in a data array is accessed. */
- typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
- AccessorLibrary mAccessorLibrary;
+ /** Finds the item in the given library by its reference, throws if not found */
+ template <typename Type> const Type& ResolveLibraryReference(
+ const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
- /** Mesh library: mesh by ID */
- typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
- MeshLibrary mMeshLibrary;
+ protected:
+ /** Filename, for a verbose error message */
+ std::string mFileName;
- /** node library: root node of the hierarchy part by ID */
- typedef std::map<std::string, Collada::Node*> NodeLibrary;
- NodeLibrary mNodeLibrary;
+ /** XML reader, member for everyday use */
+ irr::io::IrrXMLReader* mReader;
- /** Image library: stores texture properties by ID */
- typedef std::map<std::string, Collada::Image> ImageLibrary;
- ImageLibrary mImageLibrary;
+ /** All data arrays found in the file by ID. Might be referred to by actually
+ everyone. Collada, you are a steaming pile of indirection. */
+ typedef std::map<std::string, Collada::Data> DataLibrary;
+ DataLibrary mDataLibrary;
- /** Effect library: surface attributes by ID */
- typedef std::map<std::string, Collada::Effect> EffectLibrary;
- EffectLibrary mEffectLibrary;
+ /** Same for accessors which define how the data in a data array is accessed. */
+ typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
+ AccessorLibrary mAccessorLibrary;
- /** Material library: surface material by ID */
- typedef std::map<std::string, Collada::Material> MaterialLibrary;
- MaterialLibrary mMaterialLibrary;
+ /** Mesh library: mesh by ID */
+ typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
+ MeshLibrary mMeshLibrary;
- /** Light library: surface light by ID */
- typedef std::map<std::string, Collada::Light> LightLibrary;
- LightLibrary mLightLibrary;
+ /** node library: root node of the hierarchy part by ID */
+ typedef std::map<std::string, Collada::Node*> NodeLibrary;
+ NodeLibrary mNodeLibrary;
- /** Camera library: surface material by ID */
- typedef std::map<std::string, Collada::Camera> CameraLibrary;
- CameraLibrary mCameraLibrary;
+ /** Image library: stores texture properties by ID */
+ typedef std::map<std::string, Collada::Image> ImageLibrary;
+ ImageLibrary mImageLibrary;
- /** Controller library: joint controllers by ID */
- typedef std::map<std::string, Collada::Controller> ControllerLibrary;
- ControllerLibrary mControllerLibrary;
+ /** Effect library: surface attributes by ID */
+ typedef std::map<std::string, Collada::Effect> EffectLibrary;
+ EffectLibrary mEffectLibrary;
- /** Pointer to the root node. Don't delete, it just points to one of
- the nodes in the node library. */
- Collada::Node* mRootNode;
+ /** Material library: surface material by ID */
+ typedef std::map<std::string, Collada::Material> MaterialLibrary;
+ MaterialLibrary mMaterialLibrary;
- /** Root animation container */
- Collada::Animation mAnims;
+ /** Light library: surface light by ID */
+ typedef std::map<std::string, Collada::Light> LightLibrary;
+ LightLibrary mLightLibrary;
- /** Size unit: how large compared to a meter */
- float mUnitSize;
+ /** Camera library: surface material by ID */
+ typedef std::map<std::string, Collada::Camera> CameraLibrary;
+ CameraLibrary mCameraLibrary;
- /** Which is the up vector */
- enum { UP_X, UP_Y, UP_Z } mUpDirection;
+ /** Controller library: joint controllers by ID */
+ typedef std::map<std::string, Collada::Controller> ControllerLibrary;
+ ControllerLibrary mControllerLibrary;
- /** Collada file format version */
- Collada::FormatVersion mFormat;
-};
+ /** Animation library: animation references by ID */
+ typedef std::map<std::string, Collada::Animation*> AnimationLibrary;
+ AnimationLibrary mAnimationLibrary;
-// ------------------------------------------------------------------------------------------------
-// Check for element match
-inline bool ColladaParser::IsElement( const char* pName) const
-{
- ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
- return ::strcmp( mReader->getNodeName(), pName) == 0;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Finds the item in the given library by its reference, throws if not found
-template <typename Type>
-const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
-{
- typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
- if( it == pLibrary.end())
- ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL));
- return it->second;
-}
+ /** Animation clip library: clip animation references by ID */
+ typedef std::vector<std::pair<std::string, std::vector<std::string> > > AnimationClipLibrary;
+ AnimationClipLibrary mAnimationClipLibrary;
+
+ /** Pointer to the root node. Don't delete, it just points to one of
+ the nodes in the node library. */
+ Collada::Node* mRootNode;
+
+ /** Root animation container */
+ Collada::Animation mAnims;
+
+ /** Size unit: how large compared to a meter */
+ float mUnitSize;
+
+ /** Which is the up vector */
+ enum { UP_X, UP_Y, UP_Z } mUpDirection;
+
+ /** Collada file format version */
+ Collada::FormatVersion mFormat;
+ };
+
+ // ------------------------------------------------------------------------------------------------
+ // Check for element match
+ inline bool ColladaParser::IsElement( const char* pName) const
+ {
+ ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
+ return ::strcmp( mReader->getNodeName(), pName) == 0;
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ // Finds the item in the given library by its reference, throws if not found
+ template <typename Type>
+ const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
+ {
+ typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
+ if( it == pLibrary.end())
+ ThrowException( Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"." );
+ return it->second;
+ }
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
index c25a17c20..2bbb30be8 100644
--- a/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
+++ b/src/3rdparty/assimp/code/ComputeUVMappingProcess.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,50 +41,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file GenUVCoords step */
-#include "AssimpPCH.h"
#include "ComputeUVMappingProcess.h"
#include "ProcessHelper.h"
+#include "Exceptional.h"
using namespace Assimp;
namespace {
- const static aiVector3D base_axis_y(0.f,1.f,0.f);
- const static aiVector3D base_axis_x(1.f,0.f,0.f);
- const static aiVector3D base_axis_z(0.f,0.f,1.f);
- const static float angle_epsilon = 0.95f;
+ const static aiVector3D base_axis_y(0.f,1.f,0.f);
+ const static aiVector3D base_axis_x(1.f,0.f,0.f);
+ const static aiVector3D base_axis_z(0.f,0.f,1.f);
+ const static float angle_epsilon = 0.95f;
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ComputeUVMappingProcess::ComputeUVMappingProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ComputeUVMappingProcess::~ComputeUVMappingProcess()
{
- // nothing to do here
+ // 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;
+ 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 aiVector3D& planeNormal, aiVector3D& pos)
{
- const float b = planeNormal * (planePos - ray.pos);
- float h = ray.dir * planeNormal;
+ const float b = planeNormal * (planePos - ray.pos);
+ float h = ray.dir * planeNormal;
if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0)
- return false;
+ return false;
pos = ray.pos + (ray.dir * h);
return true;
@@ -94,411 +94,411 @@ inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
// 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;
-
- DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
- return UINT_MAX;
+ for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
+ if (!mesh->mTextureCoords[m])return m;
+
+ DefaultLogger::get()->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 float LOWER_LIMIT = 0.1f;
- const static float UPPER_LIMIT = 0.9f;
-
- const static float LOWER_EPSILON = 10e-3f;
- const static float UPPER_EPSILON = 1.f-10e-3f;
-
- 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.f;
-
- // 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.f;
-
- // 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.f;
- else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
- out[face.mIndices[n]].x = 1.f;
- }
- }
- }
- }
+ // 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 float LOWER_LIMIT = 0.1f;
+ const static float UPPER_LIMIT = 0.9f;
+
+ const static float LOWER_EPSILON = 10e-3f;
+ const static float UPPER_EPSILON = 1.f-10e-3f;
+
+ 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.f;
+
+ // 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.f;
+
+ // 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.f;
+ else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
+ out[face.mIndices[n]].x = 1.f;
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
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 = std::cos(lon)*std::cos(lat)
- // y = std::sin(lon)*std::cos(lat)
- // z = std::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((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.f);
- }
- }
- 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((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.f);
- }
- }
- 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((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.f);
- }
- }
- // 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((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.f);
- }
- }
-
-
- // 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);
+ 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((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.f);
+ }
+ }
+ 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((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.f);
+ }
+ }
+ 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((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.f);
+ }
+ }
+ // 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((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+ (asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
+ }
+ }
+
+
+ // 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 float 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 = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
- }
- }
- else if (axis * base_axis_y >= angle_epsilon) {
- FindMeshCenter(mesh, center, min, max);
- const float 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 = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
- }
- }
- else if (axis * base_axis_z >= angle_epsilon) {
- FindMeshCenter(mesh, center, min, max);
- const float 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 = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)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 float 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 = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)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);
+ 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 float 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 = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+ }
+ }
+ else if (axis * base_axis_y >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ const float 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 = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+ }
+ }
+ else if (axis * base_axis_z >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ const float 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 = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)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 float 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 = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)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)
{
- float 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.f);
- }
- }
- 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.f);
- }
- }
- else if (axis * base_axis_z >= angle_epsilon) {
- FindMeshCenter(mesh, center, min, max);
- diffu = max.y - min.y;
- diffv = max.z - min.z;
-
- for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
- const aiVector3D& pos = mesh->mVertices[pnt];
- out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
- }
- }
- // 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.f);
- }
- }
-
- // shouldn't be necessary to remove UV seams ...
+ float 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.f);
+ }
+ }
+ 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.f);
+ }
+ }
+ else if (axis * base_axis_z >= angle_epsilon) {
+ FindMeshCenter(mesh, center, min, max);
+ diffu = max.y - min.y;
+ diffv = max.z - min.z;
+
+ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
+ const aiVector3D& pos = mesh->mVertices[pnt];
+ out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
+ }
+ }
+ // 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.f);
+ }
+ }
+
+ // shouldn't be necessary to remove UV seams ...
}
// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
{
- DefaultLogger::get()->error("Mapping type currently not implemented");
+ DefaultLogger::get()->error("Mapping type currently not implemented");
}
// ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::Execute( aiScene* pScene)
+void ComputeUVMappingProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->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())
- {
- sprintf(buffer, "Found non-UV mapped texture (%s,%i). Mapping type: %s",
- TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
- MappingTypeToString(mapping));
-
- DefaultLogger::get()->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;
-
- // 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;
- 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)
- {
- DefaultLogger::get()->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));
- }
- }
- }
- }
- DefaultLogger::get()->debug("GenUVCoordsProcess finished");
+ DefaultLogger::get()->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));
+
+ DefaultLogger::get()->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;
+
+ // 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)
+ {
+ DefaultLogger::get()->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));
+ }
+ }
+ }
+ }
+ DefaultLogger::get()->debug("GenUVCoordsProcess finished");
}
diff --git a/src/3rdparty/assimp/code/ComputeUVMappingProcess.h b/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
index 065622c27..db4287863 100644
--- a/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
+++ b/src/3rdparty/assimp/code/ComputeUVMappingProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,11 +44,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_COMPUTEUVMAPPING_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/types.h>
class ComputeUVMappingTest;
-namespace Assimp
- {
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** ComputeUVMappingProcess - converts special mappings, such as spherical,
@@ -57,86 +59,86 @@ namespace Assimp
class ComputeUVMappingProcess : public BaseProcess
{
public:
- ComputeUVMappingProcess();
- ~ComputeUVMappingProcess();
+ 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);
+ // -------------------------------------------------------------------
+ /** 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);
+ // -------------------------------------------------------------------
+ /** 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
- {
- 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;
- }
- };
+ // 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
diff --git a/src/3rdparty/assimp/code/ConvertToLHProcess.cpp b/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
index 8af4ff831..017282796 100644
--- a/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
+++ b/src/3rdparty/assimp/code/ConvertToLHProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -47,8 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* better location.
*/
-#include "AssimpPCH.h"
+
#include "ConvertToLHProcess.h"
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
@@ -57,151 +60,155 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MakeLeftHandedProcess::MakeLeftHandedProcess()
-{}
+: BaseProcess() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-MakeLeftHandedProcess::~MakeLeftHandedProcess()
-{}
+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);
+ 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);
- DefaultLogger::get()->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);
- }
- }
- DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
+ // Check for an existent root node to proceed
+ ai_assert(pScene->mRootNode != NULL);
+ DefaultLogger::get()->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);
+ }
+ }
+ DefaultLogger::get()->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);
+ // 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.
+// Converts a single mesh to left handed coordinates.
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
{
- // 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 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;
- }
+ // 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 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.
+// Converts a single material to left handed coordinates.
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
{
- 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;
- }
- }
+ 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;
- }
-}
+// 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
@@ -221,54 +228,60 @@ 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);
+ return 0 != (pFlags & aiProcess_FlipUVs);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipUVsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FlipUVsProcess begin");
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- ProcessMesh(pScene->mMeshes[i]);
+ DefaultLogger::get()->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]);
- DefaultLogger::get()->debug("FlipUVsProcess finished");
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ ProcessMaterial(pScene->mMaterials[i]);
+ DefaultLogger::get()->debug("FlipUVsProcess finished");
}
// ------------------------------------------------------------------------------------------------
-// Converts a single material
+// 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];
-
- // 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;
- }
- }
+ aiMaterial* mat = (aiMaterial*)_mat;
+ for (unsigned int a = 0; a < mat->mNumProperties;++a) {
+ aiMaterialProperty* prop = mat->mProperties[a];
+ if( !prop ) {
+ DefaultLogger::get()->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
+// Converts a single mesh
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{
- // mirror texture y coordinate
- for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
- if( !pMesh->HasTextureCoords( a))
- break;
-
- for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
- pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
- }
+ // mirror texture y coordinate
+ for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
+ if( !pMesh->HasTextureCoords( a ) ) {
+ break;
+ }
+
+ for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
+ pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
+ }
+ }
}
#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
@@ -289,30 +302,30 @@ 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);
+ return 0 != (pFlags & aiProcess_FlipWindingOrder);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FlipWindingOrderProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- ProcessMesh(pScene->mMeshes[i]);
- DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
+ DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ ProcessMesh(pScene->mMeshes[i]);
+ DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
}
// ------------------------------------------------------------------------------------------------
-// Converts a single mesh
+// 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 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]);
+ }
}
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS
diff --git a/src/3rdparty/assimp/code/ConvertToLHProcess.h b/src/3rdparty/assimp/code/ConvertToLHProcess.h
index 5fea19c10..0c5f91c96 100644
--- a/src/3rdparty/assimp/code/ConvertToLHProcess.h
+++ b/src/3rdparty/assimp/code/ConvertToLHProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,24 +44,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - LH to RH
* - UV origin upper-left to lower-left
- * - face order cw to ccw
+ * - face order cw to ccw
*/
#ifndef AI_CONVERTTOLHPROCESS_H_INC
#define AI_CONVERTTOLHPROCESS_H_INC
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include "BaseProcess.h"
struct aiMesh;
struct aiNodeAnim;
+struct aiNode;
+struct aiMaterial;
-namespace Assimp {
+namespace Assimp {
// -----------------------------------------------------------------------------------
/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
- * coordinate system.
+ * coordinate system.
*
- * This implies a mirroring of the Z axis of the coordinate system. But to keep
+ * 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.
*
@@ -69,46 +71,46 @@ namespace Assimp {
*/
class MakeLeftHandedProcess : public BaseProcess
{
-
+
public:
- MakeLeftHandedProcess();
- ~MakeLeftHandedProcess();
+ MakeLeftHandedProcess();
+ ~MakeLeftHandedProcess();
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ 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);
+ // -------------------------------------------------------------------
+ /** 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);
};
@@ -117,23 +119,23 @@ protected:
*/
class FlipWindingOrderProcess : public BaseProcess
{
- friend class Importer;
+ friend class Importer;
public:
- /** Constructor to be privately used by Importer */
- FlipWindingOrderProcess();
+ /** Constructor to be privately used by Importer */
+ FlipWindingOrderProcess();
- /** Destructor, private as well */
- ~FlipWindingOrderProcess();
+ /** Destructor, private as well */
+ ~FlipWindingOrderProcess();
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
protected:
- void ProcessMesh( aiMesh* pMesh);
+ void ProcessMesh( aiMesh* pMesh);
};
// ---------------------------------------------------------------------------
@@ -141,24 +143,24 @@ protected:
*/
class FlipUVsProcess : public BaseProcess
{
- friend class Importer;
+ friend class Importer;
public:
- /** Constructor to be privately used by Importer */
- FlipUVsProcess();
+ /** Constructor to be privately used by Importer */
+ FlipUVsProcess();
- /** Destructor, private as well */
- ~FlipUVsProcess();
+ /** Destructor, private as well */
+ ~FlipUVsProcess();
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
protected:
- void ProcessMesh( aiMesh* pMesh);
- void ProcessMaterial( aiMaterial* mat);
+ void ProcessMesh( aiMesh* pMesh);
+ void ProcessMaterial( aiMaterial* mat);
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/D3MFImporter.cpp b/src/3rdparty/assimp/code/D3MFImporter.cpp
new file mode 100644
index 000000000..52ebba40e
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFImporter.cpp
@@ -0,0 +1,388 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+
+#include "D3MFImporter.h"
+
+#include <assimp/scene.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <contrib/unzip/unzip.h>
+#include "irrXMLWrapper.h"
+#include "StringComparison.h"
+#include "StringUtils.h"
+
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <memory>
+
+#include <assimp/ai_assert.h>
+
+#include "D3MFOpcPackage.h"
+
+namespace Assimp {
+
+namespace D3MF {
+
+
+namespace XmlTag {
+
+ const std::string model = "model";
+ const std::string metadata = "metadata";
+ const std::string resources = "resources";
+ const std::string object = "object";
+ const std::string mesh = "mesh";
+ const std::string vertices = "vertices";
+ const std::string vertex = "vertex";
+ const std::string triangles = "triangles";
+ const std::string triangle = "triangle";
+ const std::string x = "x";
+ const std::string y = "y";
+ const std::string z = "z";
+ const std::string v1 = "v1";
+ const std::string v2 = "v2";
+ const std::string v3 = "v3";
+ const std::string id = "id";
+ const std::string name = "name";
+ const std::string type = "type";
+ const std::string build = "build";
+ const std::string item = "item";
+ const std::string objectid = "objectid";
+ const std::string transform = "transform";
+
+}
+
+
+class XmlSerializer
+{
+public:
+ XmlSerializer(XmlReader* xmlReader)
+ : xmlReader(xmlReader)
+ {
+
+ }
+
+ void ImportXml(aiScene* scene)
+ {
+
+ scene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+
+ scene->mRootNode = new aiNode();
+ std::vector<aiNode*> children;
+
+ while(ReadToEndElement(D3MF::XmlTag::model))
+ {
+
+ if(xmlReader->getNodeName() == D3MF::XmlTag::object)
+ {
+ children.push_back(ReadObject(scene));
+ }
+ else if(xmlReader->getNodeName() == D3MF::XmlTag::build)
+ {
+
+ }
+ }
+
+ if(scene->mRootNode->mName.length == 0)
+ scene->mRootNode->mName.Set("3MF");
+
+
+ scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
+
+ std::copy(meshes.begin(), meshes.end(), scene->mMeshes);
+
+ scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
+ scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
+
+ std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
+
+ }
+
+private:
+ aiNode* ReadObject(aiScene* scene)
+ {
+ ScopeGuard<aiNode> node(new aiNode());
+
+ std::vector<unsigned long> meshIds;
+
+ int id = std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::id.c_str()));
+ std::string name(xmlReader->getAttributeValue(D3MF::XmlTag::name.c_str()));
+ std::string type(xmlReader->getAttributeValue(D3MF::XmlTag::type.c_str()));
+
+ node->mParent = scene->mRootNode;
+ node->mName.Set(name);
+
+ unsigned long meshIdx = meshes.size();
+
+ while(ReadToEndElement(D3MF::XmlTag::object))
+ {
+ if(xmlReader->getNodeName() == D3MF::XmlTag::mesh)
+ {
+ auto mesh = ReadMesh();
+
+ mesh->mName.Set(name);
+ meshes.push_back(mesh);
+ meshIds.push_back(meshIdx);
+ meshIdx++;
+
+ }
+ }
+
+ node->mNumMeshes = static_cast<unsigned int>(meshIds.size());
+
+ node->mMeshes = new unsigned int[node->mNumMeshes];
+
+ std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
+
+ return node.dismiss();
+
+ }
+
+ aiMesh* ReadMesh()
+ {
+ aiMesh* mesh = new aiMesh();
+
+ while(ReadToEndElement(D3MF::XmlTag::mesh))
+ {
+ if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
+ {
+ ImportVertices(mesh);
+ }
+ else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles)
+ {
+ ImportTriangles(mesh);
+ }
+
+ }
+
+
+ return mesh;
+ }
+
+ void ImportVertices(aiMesh* mesh)
+ {
+ std::vector<aiVector3D> vertices;
+
+ while(ReadToEndElement(D3MF::XmlTag::vertices))
+ {
+ if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
+ {
+ vertices.push_back(ReadVertex());
+ }
+ }
+ mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+
+ std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
+
+ }
+ aiVector3D ReadVertex()
+ {
+ aiVector3D vertex;
+ vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
+ vertex.y = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::y.c_str()), nullptr);
+ vertex.z = ai_strtof>(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
+
+ return vertex;
+ }
+
+ void ImportTriangles(aiMesh* mesh)
+ {
+ std::vector<aiFace> faces;
+
+
+ while(ReadToEndElement(D3MF::XmlTag::triangles))
+ {
+ if(xmlReader->getNodeName() == D3MF::XmlTag::triangle)
+ {
+ faces.push_back(ReadTriangle());
+ }
+ }
+
+ mesh->mNumFaces = static_cast<unsigned int>(faces.size());
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+
+ std::copy(faces.begin(), faces.end(), mesh->mFaces);
+
+ }
+
+ aiFace ReadTriangle()
+ {
+ aiFace face;
+
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[face.mNumIndices];
+ face.mIndices[0] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v1.c_str())));
+ face.mIndices[1] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v2.c_str())));
+ face.mIndices[2] = static_cast<unsigned int>(std::atoi(xmlReader->getAttributeValue(D3MF::XmlTag::v3.c_str())));
+
+ return face;
+ }
+
+private:
+
+ bool ReadToStartElement(const std::string& startTag)
+ {
+ while(xmlReader->read())
+ {
+ if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag)
+ {
+ return true;
+ }
+ else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END &&
+ xmlReader->getNodeName() == startTag)
+ {
+ return false;
+ }
+ }
+ //DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
+ return false;
+ }
+
+ bool ReadToEndElement(const std::string& closeTag)
+ {
+ while(xmlReader->read())
+ {
+ if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
+ return true;
+ }
+ else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END
+ && xmlReader->getNodeName() == closeTag)
+ {
+ return false;
+ }
+ }
+ DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
+ return false;
+ }
+
+
+private:
+ std::vector<aiMesh*> meshes;
+ XmlReader* xmlReader;
+
+
+};
+
+} //namespace D3MF
+
+
+static const aiImporterDesc desc = {
+ "3mf Importer",
+ "",
+ "",
+ "http://3mf.io/",
+ aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "3mf"
+};
+
+
+D3MFImporter::D3MFImporter()
+{
+
+}
+
+D3MFImporter::~D3MFImporter()
+{
+
+}
+
+bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const
+{
+ const std::string extension = GetExtension(pFile);
+
+ if(extension == "3mf")
+ {
+ return true;
+ }
+ else if(!extension.length() || checkSig)
+ {
+ if(!pIOHandler)
+ return true;
+ }
+
+ return false;
+}
+
+void D3MFImporter::SetupProperties(const Importer *pImp)
+{
+
+}
+
+const aiImporterDesc *D3MFImporter::GetInfo() const
+{
+ return &desc;
+}
+
+void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler)
+{
+
+
+ D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile);
+
+ std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
+ std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
+
+ D3MF::XmlSerializer xmlSerializer(xmlReader.get());
+
+
+ xmlSerializer.ImportXml(pScene);
+
+
+}
+
+}
+
+#endif // ASSIMP_BUILD_NO_3MF_IMPORTER
diff --git a/src/3rdparty/assimp/code/D3MFImporter.h b/src/3rdparty/assimp/code/D3MFImporter.h
new file mode 100644
index 000000000..36c6d53e4
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFImporter.h
@@ -0,0 +1,68 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef AI_D3MFLOADER_H_INCLUDED
+#define AI_D3MFLOADER_H_INCLUDED
+
+#include <vector>
+#include <cstdint>
+
+#include "BaseImporter.h"
+
+namespace Assimp {
+
+class D3MFImporter : public BaseImporter
+{
+public:
+ D3MFImporter();
+ ~D3MFImporter();
+
+ // BaseImporter interface
+public:
+ bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
+ void SetupProperties(const Importer *pImp);
+ const aiImporterDesc *GetInfo() const;
+
+protected:
+ void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
+
+};
+}
+#endif // AI_D3MFLOADER_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/D3MFOpcPackage.cpp b/src/3rdparty/assimp/code/D3MFOpcPackage.cpp
new file mode 100644
index 000000000..9f4bdc468
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFOpcPackage.cpp
@@ -0,0 +1,591 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+
+#include "D3MFOpcPackage.h"
+#include "Exceptional.h"
+
+#include <contrib/unzip/unzip.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/ai_assert.h>
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+
+namespace Assimp {
+
+namespace D3MF {
+
+
+
+namespace XmlTag {
+
+const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
+const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
+const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
+const std::string RELS_RELATIONSHIP_NODE = "Relationship";
+const std::string RELS_ATTRIB_TARGET = "Target";
+const std::string RELS_ATTRIB_TYPE = "Type";
+const std::string RELS_ATTRIB_ID = "Id";
+const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
+const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+
+
+}
+
+class IOSystem2Unzip {
+
+ public:
+
+ static voidpf open(voidpf opaque, const char* filename, int mode);
+
+ static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
+
+ static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
+
+ static long tell(voidpf opaque, voidpf stream);
+
+ static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
+
+ static int close(voidpf opaque, voidpf stream);
+
+ static int testerror(voidpf opaque, voidpf stream);
+
+ static zlib_filefunc_def get(IOSystem* pIOHandler);
+};
+
+voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
+ IOSystem* io_system = reinterpret_cast<IOSystem*>(opaque);
+
+ const char* mode_fopen = NULL;
+ if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) {
+ mode_fopen = "rb";
+ } else {
+ if(mode & ZLIB_FILEFUNC_MODE_EXISTING) {
+ mode_fopen = "r+b";
+ } else {
+ if(mode & ZLIB_FILEFUNC_MODE_CREATE) {
+ mode_fopen = "wb";
+ }
+ }
+ }
+
+
+ return (voidpf) io_system->Open(filename, mode_fopen);
+}
+
+uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
+ IOStream* io_stream = (IOStream*) stream;
+
+ return io_stream->Read(buf, 1, size);
+}
+
+uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
+ IOStream* io_stream = (IOStream*) stream;
+
+ return io_stream->Write(buf, 1, size);
+}
+
+long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
+ IOStream* io_stream = (IOStream*) stream;
+
+ return io_stream->Tell();
+}
+
+long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
+ IOStream* io_stream = (IOStream*) stream;
+
+ aiOrigin assimp_origin;
+ switch (origin) {
+ default:
+ case ZLIB_FILEFUNC_SEEK_CUR:
+ assimp_origin = aiOrigin_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END:
+ assimp_origin = aiOrigin_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET:
+ assimp_origin = aiOrigin_SET;
+ break;
+ }
+
+ return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
+}
+
+int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
+ IOSystem* io_system = (IOSystem*) opaque;
+ IOStream* io_stream = (IOStream*) stream;
+
+ io_system->Close(io_stream);
+
+ return 0;
+}
+
+int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
+ return 0;
+}
+
+zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
+ zlib_filefunc_def mapping;
+
+ mapping.zopen_file = open;
+ mapping.zread_file = read;
+ mapping.zwrite_file = write;
+ mapping.ztell_file = tell;
+ mapping.zseek_file = seek;
+ mapping.zclose_file = close;
+ mapping.zerror_file = testerror;
+ mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
+
+ return mapping;
+}
+
+
+class ZipFile : public IOStream
+{
+ friend class D3MFZipArchive;
+
+public:
+ explicit ZipFile(size_t size);
+
+ ~ZipFile();
+
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
+
+ size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
+
+ size_t FileSize() const;
+
+ aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
+
+ size_t Tell() const;
+
+ void Flush();
+
+private:
+
+ void* m_Buffer;
+
+ size_t m_Size;
+
+};
+
+ZipFile::ZipFile(size_t size) : m_Size(size) {
+ ai_assert(m_Size != 0);
+
+ m_Buffer = malloc(m_Size);
+}
+
+ZipFile::~ZipFile() {
+ free(m_Buffer);
+ m_Buffer = NULL;
+}
+
+size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
+ const size_t size = pSize * pCount;
+ assert(size <= m_Size);
+
+ std::memcpy(pvBuffer, m_Buffer, size);
+
+ return size;
+}
+
+size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
+ return 0;
+}
+
+size_t ZipFile::FileSize() const {
+ return m_Size;
+}
+
+aiReturn ZipFile::Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
+ return aiReturn_FAILURE;
+}
+
+size_t ZipFile::Tell() const {
+ return 0;
+}
+
+void ZipFile::Flush() {
+ // empty
+}
+
+
+class D3MFZipArchive : public IOSystem
+{
+public:
+
+ static const unsigned int FileNameSize = 256;
+
+public:
+
+ D3MFZipArchive(IOSystem* pIOHandler, const std::string & rFile);
+
+ ~D3MFZipArchive();
+
+ bool Exists(const char* pFile) const;
+
+ char getOsSeparator() const;
+
+ IOStream* Open(const char* pFile, const char* pMode = "rb");
+
+ void Close(IOStream* pFile);
+
+ bool isOpen() const;
+
+ void getFileList(std::vector<std::string> &rFileList);
+
+private:
+
+ bool mapArchive();
+
+private:
+
+ unzFile m_ZipFileHandle;
+
+ std::map<std::string, ZipFile*> m_ArchiveMap;
+
+};
+
+
+// ------------------------------------------------------------------------------------------------
+// Constructor.
+D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
+ : m_ZipFileHandle(NULL), m_ArchiveMap()
+{
+ if (! rFile.empty())
+ {
+ zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
+
+ m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
+
+ if(m_ZipFileHandle != NULL) {
+ mapArchive();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor.
+D3MFZipArchive::~D3MFZipArchive() {
+ for(auto &file : m_ArchiveMap) {
+ delete file.second;
+ }
+ m_ArchiveMap.clear();
+
+ if(m_ZipFileHandle != NULL) {
+ unzClose(m_ZipFileHandle);
+ m_ZipFileHandle = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns true, if the archive is already open.
+bool D3MFZipArchive::isOpen() const {
+ return (m_ZipFileHandle != NULL);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns true, if the filename is part of the archive.
+bool D3MFZipArchive::Exists(const char* pFile) const {
+ ai_assert(pFile != NULL);
+
+ bool exist = false;
+
+ if (pFile != NULL) {
+ std::string rFile(pFile);
+ std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
+
+ if(it != m_ArchiveMap.end()) {
+ exist = true;
+ }
+ }
+
+ return exist;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns the separator delimiter.
+char D3MFZipArchive::getOsSeparator() const {
+#ifndef _WIN32
+ return '/';
+#else
+ return '\\';
+#endif
+}
+
+// ------------------------------------------------------------------------------------------------
+// Opens a file, which is part of the archive.
+IOStream *D3MFZipArchive::Open(const char* pFile, const char* /*pMode*/) {
+ ai_assert(pFile != NULL);
+
+ IOStream* result = NULL;
+
+ std::map<std::string, ZipFile*>::iterator it = m_ArchiveMap.find(pFile);
+
+ if(it != m_ArchiveMap.end()) {
+ result = static_cast<IOStream*>(it->second);
+ }
+
+ return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Close a filestream.
+void D3MFZipArchive::Close(IOStream *pFile) {
+ ai_assert(pFile != NULL);
+
+ // We don't do anything in case the file would be opened again in the future
+}
+// ------------------------------------------------------------------------------------------------
+// Returns the file-list of the archive.
+void D3MFZipArchive::getFileList(std::vector<std::string> &rFileList) {
+ rFileList.clear();
+
+ for(const auto &file : m_ArchiveMap) {
+ rFileList.push_back(file.first);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Maps the archive content.
+bool D3MFZipArchive::mapArchive() {
+ bool success = false;
+
+ if(m_ZipFileHandle != NULL) {
+ if(m_ArchiveMap.empty()) {
+ // At first ensure file is already open
+ if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) {
+ // Loop over all files
+ do {
+ char filename[FileNameSize];
+ unz_file_info fileInfo;
+
+ if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) {
+ // The file has EXACTLY the size of uncompressed_size. In C
+ // you need to mark the last character with '\0', so add
+ // another character
+ if(fileInfo.uncompressed_size != 0 && unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) {
+ std::pair<std::map<std::string, ZipFile*>::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size)));
+
+ if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) {
+ if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) {
+ // Nothing to do anymore...
+ }
+ }
+ }
+ }
+ } while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
+ }
+ }
+
+ success = true;
+ }
+
+ return success;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+struct OpcPackageRelationship
+{
+ std::string id;
+ std::string type;
+ std::string target;
+};
+
+typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
+
+class OpcPackageRelationshipReader
+{
+public:
+
+ OpcPackageRelationshipReader(XmlReader* xmlReader)
+ {
+
+ while(xmlReader->read())
+ {
+ if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
+ xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER)
+ {
+ ParseRootNode(xmlReader);
+ }
+ }
+
+
+ }
+ void ParseRootNode(XmlReader* xmlReader)
+ {
+ ParseAttributes(xmlReader);
+
+ while(xmlReader->read())
+ {
+ if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
+ xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE)
+ {
+ ParseChildNode(xmlReader);
+ }
+ }
+
+ }
+
+ void ParseAttributes(XmlReader*)
+ {
+
+ }
+ void ParseChildNode(XmlReader* xmlReader)
+ {
+ OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
+
+ relPtr->id = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_ID.c_str());
+ relPtr->type = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TYPE.c_str());
+ relPtr->target = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TARGET.c_str());
+
+ m_relationShips.push_back(relPtr);
+ }
+ std::vector<OpcPackageRelationshipPtr> m_relationShips;
+
+};
+// ------------------------------------------------------------------------------------------------
+
+D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
+ : m_RootStream(nullptr)
+{
+
+ zipArchive.reset(new D3MF::D3MFZipArchive( pIOHandler, rFile ));
+ if(!zipArchive->isOpen())
+ throw DeadlyImportError("Failed to open file " + rFile+ ".");
+
+ std::vector<std::string> fileList;
+ zipArchive->getFileList(fileList);
+
+ for(auto& file: fileList){
+
+ if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE)
+ {
+
+ //PkgRelationshipReader pkgRelReader(file, archive);
+ ai_assert(zipArchive->Exists(file.c_str()));
+
+ IOStream *fileStream = zipArchive->Open(file.c_str());
+
+ ai_assert(fileStream != nullptr);
+
+ std::string rootFile = ReadPackageRootRelationship(fileStream);
+ if(rootFile.size() > 0 && rootFile[0] == '/')
+ rootFile = rootFile.substr(1);
+
+ DefaultLogger::get()->debug(rootFile);
+
+ m_RootStream = zipArchive->Open(rootFile.c_str());
+
+ ai_assert(m_RootStream != nullptr);
+
+
+
+
+ // const size_t size = zipArchive->FileSize();
+ // m_Data.resize( size );
+
+ // const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
+ // if ( readSize != size )
+ // {
+ // m_Data.clear();
+ // return false;
+ // }
+ zipArchive->Close( fileStream );
+
+ }
+ else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE)
+ {
+
+ }
+ }
+}
+
+D3MFOpcPackage::~D3MFOpcPackage()
+{
+
+}
+
+IOStream* D3MFOpcPackage::RootStream() const
+{
+ return m_RootStream;
+}
+
+
+std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream)
+{
+
+ std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
+ std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
+
+ OpcPackageRelationshipReader reader(xml.get());
+
+
+ auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){
+ return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
+ });
+
+
+
+ if(itr == reader.m_relationShips.end())
+ throw DeadlyImportError("Cannot find" + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
+
+ return (*itr)->target;
+}
+
+} //namespace D3MF
+
+}
+
+#endif //ASSIMP_BUILD_NO_3MF_IMPORTER
diff --git a/src/3rdparty/assimp/code/D3MFOpcPackage.h b/src/3rdparty/assimp/code/D3MFOpcPackage.h
new file mode 100644
index 000000000..dd8a40aab
--- /dev/null
+++ b/src/3rdparty/assimp/code/D3MFOpcPackage.h
@@ -0,0 +1,76 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef D3MFOPCPACKAGE_H
+#define D3MFOPCPACKAGE_H
+
+#include <string>
+#include <memory>
+
+#include <assimp/IOSystem.hpp>
+#include "irrXMLWrapper.h"
+
+namespace Assimp {
+
+namespace D3MF {
+
+typedef irr::io::IrrXMLReader XmlReader;
+typedef std::shared_ptr<XmlReader> XmlReaderPtr;
+
+class D3MFZipArchive;
+
+class D3MFOpcPackage
+{
+public:
+ D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile);
+ ~D3MFOpcPackage();
+
+ IOStream* RootStream() const;
+private:
+ std::string ReadPackageRootRelationship(IOStream* stream);
+private:
+ IOStream* m_RootStream;
+ std::unique_ptr<D3MFZipArchive> zipArchive;
+};
+
+}
+}
+
+#endif // D3MFOPCPACKAGE_H
diff --git a/src/3rdparty/assimp/code/DXFHelper.h b/src/3rdparty/assimp/code/DXFHelper.h
index 0c76c3f2d..1947469a8 100644
--- a/src/3rdparty/assimp/code/DXFHelper.h
+++ b/src/3rdparty/assimp/code/DXFHelper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,22 +23,22 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file DXFHelper.h
+/** @file DXFHelper.h
* @brief Internal utilities for the DXF loader.
*/
@@ -48,9 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LineSplitter.h"
#include "TinyFormatter.h"
#include "StreamReader.h"
+#include "fast_atof.h"
+#include <vector>
+#include <assimp/DefaultLogger.hpp>
namespace Assimp {
- namespace DXF {
+ namespace DXF {
// read pairs of lines, parse group code and value and provide utilities
@@ -60,113 +63,115 @@ class LineReader
public:
- LineReader(StreamReaderLE& reader)
- // do NOT skip empty lines. In DXF files, they count as valid data.
- : splitter(reader,false,true)
- , end()
- {
- }
+ LineReader(StreamReaderLE& reader)
+ // do NOT skip empty lines. In DXF files, they count as valid data.
+ : splitter(reader,false,true)
+ , groupcode( 0 )
+ , value()
+ , end()
+ {
+ }
public:
- // -----------------------------------------
- bool Is(int gc, const char* what) const {
- return groupcode == gc && !strcmp(what,value.c_str());
- }
+ // -----------------------------------------
+ bool Is(int gc, const char* what) const {
+ return groupcode == gc && !strcmp(what,value.c_str());
+ }
- // -----------------------------------------
- bool Is(int gc) const {
- return groupcode == gc;
- }
+ // -----------------------------------------
+ bool Is(int gc) const {
+ return groupcode == gc;
+ }
- // -----------------------------------------
- int GroupCode() const {
- return groupcode;
- }
+ // -----------------------------------------
+ int GroupCode() const {
+ return groupcode;
+ }
- // -----------------------------------------
- const std::string& Value() const {
- return value;
- }
+ // -----------------------------------------
+ const std::string& Value() const {
+ return value;
+ }
- // -----------------------------------------
- bool End() const {
- return !((bool)*this);
- }
+ // -----------------------------------------
+ bool End() const {
+ return !((bool)*this);
+ }
public:
- // -----------------------------------------
- unsigned int ValueAsUnsignedInt() const {
- return strtoul10(value.c_str());
- }
+ // -----------------------------------------
+ unsigned int ValueAsUnsignedInt() const {
+ return strtoul10(value.c_str());
+ }
- // -----------------------------------------
- int ValueAsSignedInt() const {
- return strtol10(value.c_str());
- }
+ // -----------------------------------------
+ int ValueAsSignedInt() const {
+ return strtol10(value.c_str());
+ }
- // -----------------------------------------
- float ValueAsFloat() const {
- return fast_atof(value.c_str());
- }
+ // -----------------------------------------
+ float ValueAsFloat() const {
+ return fast_atof(value.c_str());
+ }
public:
- // -----------------------------------------
- /** pseudo-iterator increment to advance to the next (groupcode/value) pair */
- LineReader& operator++() {
- if (end) {
- if (end == 1) {
- ++end;
- }
- return *this;
- }
-
- try {
- groupcode = strtol10(splitter->c_str());
- splitter++;
-
- value = *splitter;
- splitter++;
-
- // automatically skip over {} meta blocks (these are for application use
- // and currently not relevant for Assimp).
- if (value.length() && value[0] == '{') {
-
- size_t cnt = 0;
- for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
-
- splitter++;
- DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
- }
- } catch(std::logic_error&) {
- ai_assert(!splitter);
- }
- if (!splitter) {
- end = 1;
- }
- return *this;
- }
-
- // -----------------------------------------
- LineReader& operator++(int) {
- return ++(*this);
- }
-
-
- // -----------------------------------------
- operator bool() const {
- return end <= 1;
- }
+ // -----------------------------------------
+ /** pseudo-iterator increment to advance to the next (groupcode/value) pair */
+ LineReader& operator++() {
+ if (end) {
+ if (end == 1) {
+ ++end;
+ }
+ return *this;
+ }
+
+ try {
+ groupcode = strtol10(splitter->c_str());
+ splitter++;
+
+ value = *splitter;
+ splitter++;
+
+ // automatically skip over {} meta blocks (these are for application use
+ // and currently not relevant for Assimp).
+ if (value.length() && value[0] == '{') {
+
+ size_t cnt = 0;
+ for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
+
+ splitter++;
+ DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
+ }
+ } catch(std::logic_error&) {
+ ai_assert(!splitter);
+ }
+ if (!splitter) {
+ end = 1;
+ }
+ return *this;
+ }
+
+ // -----------------------------------------
+ LineReader& operator++(int) {
+ return ++(*this);
+ }
+
+
+ // -----------------------------------------
+ operator bool() const {
+ return end <= 1;
+ }
private:
- LineSplitter splitter;
- int groupcode;
- std::string value;
- int end;
+ LineSplitter splitter;
+ int groupcode;
+ std::string value;
+ int end;
};
@@ -174,52 +179,52 @@ private:
// represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
struct PolyLine
{
- PolyLine()
- : flags()
- {}
-
- std::vector<aiVector3D> positions;
- std::vector<aiColor4D> colors;
- std::vector<unsigned int> indices;
- std::vector<unsigned int> counts;
- unsigned int flags;
-
- std::string layer;
- std::string desc;
+ PolyLine()
+ : flags()
+ {}
+
+ std::vector<aiVector3D> positions;
+ std::vector<aiColor4D> colors;
+ std::vector<unsigned int> indices;
+ std::vector<unsigned int> counts;
+ unsigned int flags;
+
+ std::string layer;
+ std::string desc;
};
// reference to a BLOCK. Specifies its own coordinate system.
struct InsertBlock
{
- InsertBlock()
- : scale(1.f,1.f,1.f)
- , angle()
- {}
+ InsertBlock()
+ : scale(1.f,1.f,1.f)
+ , angle()
+ {}
- aiVector3D pos;
- aiVector3D scale;
- float angle;
+ aiVector3D pos;
+ aiVector3D scale;
+ float angle;
- std::string name;
+ std::string name;
};
// keeps track of all geometry in a single BLOCK.
struct Block
{
- std::vector< boost::shared_ptr<PolyLine> > lines;
- std::vector<InsertBlock> insertions;
+ std::vector< std::shared_ptr<PolyLine> > lines;
+ std::vector<InsertBlock> insertions;
- std::string name;
- aiVector3D base;
+ std::string name;
+ aiVector3D base;
};
struct FileData
{
- // note: the LAST block always contains the stuff from ENTITIES.
- std::vector<Block> blocks;
+ // note: the LAST block always contains the stuff from ENTITIES.
+ std::vector<Block> blocks;
};
diff --git a/src/3rdparty/assimp/code/DXFLoader.cpp b/src/3rdparty/assimp/code/DXFLoader.cpp
index acbfc8de6..3e69eff1e 100644
--- a/src/3rdparty/assimp/code/DXFLoader.cpp
+++ b/src/3rdparty/assimp/code/DXFLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the DXF importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
#include "DXFLoader.h"
@@ -52,52 +52,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "fast_atof.h"
#include "DXFHelper.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <numeric>
using namespace Assimp;
-// AutoCAD Binary DXF<CR><LF><SUB><NULL>
+// AutoCAD Binary DXF<CR><LF><SUB><NULL>
#define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0")
#define AI_DXF_BINARY_IDENT_LEN (24)
// default vertex color that all uncolored vertices will receive
#define AI_DXF_DEFAULT_COLOR aiColor4D(0.6f,0.6f,0.6f,0.6f)
-// color indices for DXF - 16 are supported, the table is
+// color indices for DXF - 16 are supported, the table is
// taken directly from the DXF spec.
static aiColor4D g_aclrDxfIndexColors[] =
{
- aiColor4D (0.6f, 0.6f, 0.6f, 1.0f),
- aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
- aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
- aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue
- aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green
- aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue
- aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red
- aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink
- aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange
- aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange
- aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow
- aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray
- aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray
- aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black
- aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white
- aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet
+ aiColor4D (0.6f, 0.6f, 0.6f, 1.0f),
+ aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
+ aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
+ aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue
+ aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green
+ aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue
+ aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red
+ aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink
+ aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange
+ aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange
+ aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow
+ aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray
+ aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray
+ aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black
+ aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white
+ aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet
};
#define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0]))
#define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC"
static const aiImporterDesc desc = {
- "Drawing Interchange Format (DXF) Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport,
- 0,
- 0,
- 0,
- 0,
- "dxf"
+ "Drawing Interchange Format (DXF) Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport,
+ 0,
+ 0,
+ 0,
+ 0,
+ "dxf"
};
// ------------------------------------------------------------------------------------------------
@@ -106,607 +109,607 @@ DXFImporter::DXFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
DXFImporter::~DXFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool DXFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
{
- return SimpleExtensionCheck(pFile,"dxf");
+ return SimpleExtensionCheck(pFile,"dxf");
}
// ------------------------------------------------------------------------------------------------
// Get a list of all supported file extensions
const aiImporterDesc* DXFImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void DXFImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void DXFImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler)
{
- boost::shared_ptr<IOStream> file = boost::shared_ptr<IOStream>( pIOHandler->Open( pFile) );
-
- // Check whether we can read the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open DXF file " + pFile + "");
- }
-
- // check whether this is a binaray DXF file - we can't read binary DXF files :-(
- char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0};
- file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
-
- if (!strncmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
- throw DeadlyImportError("DXF: Binary files are not supported at the moment");
- }
-
- // DXF files can grow very large, so read them via the StreamReader,
- // which will choose a suitable strategy.
- file->Seek(0,aiOrigin_SET);
- StreamReaderLE stream( file );
-
- DXF::LineReader reader (stream);
- DXF::FileData output;
-
- // now get all lines of the file and process top-level sections
- bool eof = false;
- while(!reader.End()) {
-
- // blocks table - these 'build blocks' are later (in ENTITIES)
- // referenced an included via INSERT statements.
- if (reader.Is(2,"BLOCKS")) {
- ParseBlocks(reader,output);
- continue;
- }
-
- // primary entity table
- if (reader.Is(2,"ENTITIES")) {
- ParseEntities(reader,output);
- continue;
- }
-
- // skip unneeded sections entirely to avoid any problems with them
- // alltogether.
- else if (reader.Is(2,"CLASSES") || reader.Is(2,"TABLES")) {
- SkipSection(reader);
- continue;
- }
-
- else if (reader.Is(2,"HEADER")) {
- ParseHeader(reader,output);
- continue;
- }
-
- // comments
- else if (reader.Is(999)) {
- DefaultLogger::get()->info("DXF Comment: " + reader.Value());
- }
-
- // don't read past the official EOF sign
- else if (reader.Is(0,"EOF")) {
- eof = true;
- break;
- }
-
- ++reader;
- }
- if (!eof) {
- DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker");
- }
-
- ConvertMeshes(pScene,output);
-
- // Now rotate the whole scene by 90 degrees around the x axis to convert from AutoCAD's to Assimp's coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(
- 1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,
- 0.f,-1.f,0.f,0.f,
- 0.f,0.f,0.f,1.f) * pScene->mRootNode->mTransformation;
+ std::shared_ptr<IOStream> file = std::shared_ptr<IOStream>( pIOHandler->Open( pFile) );
+
+ // Check whether we can read the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open DXF file " + pFile + "");
+ }
+
+ // check whether this is a binaray DXF file - we can't read binary DXF files :-(
+ char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0};
+ file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
+
+ if (!strncmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
+ throw DeadlyImportError("DXF: Binary files are not supported at the moment");
+ }
+
+ // DXF files can grow very large, so read them via the StreamReader,
+ // which will choose a suitable strategy.
+ file->Seek(0,aiOrigin_SET);
+ StreamReaderLE stream( file );
+
+ DXF::LineReader reader (stream);
+ DXF::FileData output;
+
+ // now get all lines of the file and process top-level sections
+ bool eof = false;
+ while(!reader.End()) {
+
+ // blocks table - these 'build blocks' are later (in ENTITIES)
+ // referenced an included via INSERT statements.
+ if (reader.Is(2,"BLOCKS")) {
+ ParseBlocks(reader,output);
+ continue;
+ }
+
+ // primary entity table
+ if (reader.Is(2,"ENTITIES")) {
+ ParseEntities(reader,output);
+ continue;
+ }
+
+ // skip unneeded sections entirely to avoid any problems with them
+ // altogether.
+ else if (reader.Is(2,"CLASSES") || reader.Is(2,"TABLES")) {
+ SkipSection(reader);
+ continue;
+ }
+
+ else if (reader.Is(2,"HEADER")) {
+ ParseHeader(reader,output);
+ continue;
+ }
+
+ // comments
+ else if (reader.Is(999)) {
+ DefaultLogger::get()->info("DXF Comment: " + reader.Value());
+ }
+
+ // don't read past the official EOF sign
+ else if (reader.Is(0,"EOF")) {
+ eof = true;
+ break;
+ }
+
+ ++reader;
+ }
+ if (!eof) {
+ DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker");
+ }
+
+ ConvertMeshes(pScene,output);
+
+ // Now rotate the whole scene by 90 degrees around the x axis to convert from AutoCAD's to Assimp's coordinate system
+ pScene->mRootNode->mTransformation = aiMatrix4x4(
+ 1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,
+ 0.f,-1.f,0.f,0.f,
+ 0.f,0.f,0.f,1.f) * pScene->mRootNode->mTransformation;
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
{
- // the process of resolving all the INSERT statements can grow the
- // polycount excessively, so log the original number.
- // XXX Option to import blocks as separate nodes?
- if (!DefaultLogger::isNullLogger()) {
-
- unsigned int vcount = 0, icount = 0;
- BOOST_FOREACH (const DXF::Block& bl, output.blocks) {
- BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl, bl.lines) {
- vcount += pl->positions.size();
- icount += pl->counts.size();
- }
- }
-
- DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "),
- icount,", vertex count is ",vcount
- ));
- }
-
- if (! output.blocks.size() ) {
- throw DeadlyImportError("DXF: no data blocks loaded");
- }
-
- DXF::Block* entities = 0;
-
- // index blocks by name
- DXF::BlockMap blocks_by_name;
- BOOST_FOREACH (DXF::Block& bl, output.blocks) {
- blocks_by_name[bl.name] = &bl;
- if ( !entities && bl.name == AI_DXF_ENTITIES_MAGIC_BLOCK ) {
- entities = &bl;
- }
- }
-
- if (!entities) {
- throw DeadlyImportError("DXF: no ENTITIES data block loaded");
- }
-
- typedef std::map<std::string, unsigned int> LayerMap;
-
- LayerMap layers;
- std::vector< std::vector< const DXF::PolyLine*> > corr;
-
- // now expand all block references in the primary ENTITIES block
- // XXX this involves heavy memory copying, consider a faster solution for future versions.
- ExpandBlockReferences(*entities,blocks_by_name);
-
- unsigned int cur = 0;
- BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl, entities->lines) {
- if (pl->positions.size()) {
-
- std::map<std::string, unsigned int>::iterator it = layers.find(pl->layer);
- if (it == layers.end()) {
- ++pScene->mNumMeshes;
-
- layers[pl->layer] = cur++;
-
- std::vector< const DXF::PolyLine* > pv;
- pv.push_back(&*pl);
-
- corr.push_back(pv);
- }
- else {
- corr[(*it).second].push_back(&*pl);
- }
- }
- }
-
- if (!pScene->mNumMeshes) {
- throw DeadlyImportError("DXF: this file contains no 3d data");
- }
-
- pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ] ();
-
- BOOST_FOREACH(const LayerMap::value_type& elem, layers){
- aiMesh* const mesh = pScene->mMeshes[elem.second] = new aiMesh();
- mesh->mName.Set(elem.first);
-
- unsigned int cvert = 0,cface = 0;
- BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){
- // sum over all faces since we need to 'verbosify' them.
- cvert += std::accumulate(pl->counts.begin(),pl->counts.end(),0);
- cface += pl->counts.size();
- }
-
- aiVector3D* verts = mesh->mVertices = new aiVector3D[cvert];
- aiColor4D* colors = mesh->mColors[0] = new aiColor4D[cvert];
- aiFace* faces = mesh->mFaces = new aiFace[cface];
-
- mesh->mNumVertices = cvert;
- mesh->mNumFaces = cface;
-
- unsigned int prims = 0;
- unsigned int overall_indices = 0;
- BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){
-
- std::vector<unsigned int>::const_iterator it = pl->indices.begin();
- BOOST_FOREACH(unsigned int facenumv,pl->counts) {
- aiFace& face = *faces++;
- face.mIndices = new unsigned int[face.mNumIndices = facenumv];
-
- for (unsigned int i = 0; i < facenumv; ++i) {
- face.mIndices[i] = overall_indices++;
-
- ai_assert(pl->positions.size() == pl->colors.size());
- if (*it >= pl->positions.size()) {
- throw DeadlyImportError("DXF: vertex index out of bounds");
- }
-
- *verts++ = pl->positions[*it];
- *colors++ = pl->colors[*it++];
- }
-
- // set primitive flags now, this saves the extra pass in ScenePreprocessor.
- switch(face.mNumIndices) {
- case 1:
- prims |= aiPrimitiveType_POINT;
- break;
- case 2:
- prims |= aiPrimitiveType_LINE;
- break;
- case 3:
- prims |= aiPrimitiveType_TRIANGLE;
- break;
- default:
- prims |= aiPrimitiveType_POLYGON;
- break;
- }
- }
- }
-
- mesh->mPrimitiveTypes = prims;
- mesh->mMaterialIndex = 0;
- }
-
- GenerateHierarchy(pScene,output);
- GenerateMaterials(pScene,output);
+ // the process of resolving all the INSERT statements can grow the
+ // polycount excessively, so log the original number.
+ // XXX Option to import blocks as separate nodes?
+ if (!DefaultLogger::isNullLogger()) {
+
+ unsigned int vcount = 0, icount = 0;
+ for (const DXF::Block& bl : output.blocks) {
+ for (std::shared_ptr<const DXF::PolyLine> pl : bl.lines) {
+ vcount += pl->positions.size();
+ icount += pl->counts.size();
+ }
+ }
+
+ DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "),
+ icount,", vertex count is ",vcount
+ ));
+ }
+
+ if (! output.blocks.size() ) {
+ throw DeadlyImportError("DXF: no data blocks loaded");
+ }
+
+ DXF::Block* entities = 0;
+
+ // index blocks by name
+ DXF::BlockMap blocks_by_name;
+ for (DXF::Block& bl : output.blocks) {
+ blocks_by_name[bl.name] = &bl;
+ if ( !entities && bl.name == AI_DXF_ENTITIES_MAGIC_BLOCK ) {
+ entities = &bl;
+ }
+ }
+
+ if (!entities) {
+ throw DeadlyImportError("DXF: no ENTITIES data block loaded");
+ }
+
+ typedef std::map<std::string, unsigned int> LayerMap;
+
+ LayerMap layers;
+ std::vector< std::vector< const DXF::PolyLine*> > corr;
+
+ // now expand all block references in the primary ENTITIES block
+ // XXX this involves heavy memory copying, consider a faster solution for future versions.
+ ExpandBlockReferences(*entities,blocks_by_name);
+
+ unsigned int cur = 0;
+ for (std::shared_ptr<const DXF::PolyLine> pl : entities->lines) {
+ if (pl->positions.size()) {
+
+ std::map<std::string, unsigned int>::iterator it = layers.find(pl->layer);
+ if (it == layers.end()) {
+ ++pScene->mNumMeshes;
+
+ layers[pl->layer] = cur++;
+
+ std::vector< const DXF::PolyLine* > pv;
+ pv.push_back(&*pl);
+
+ corr.push_back(pv);
+ }
+ else {
+ corr[(*it).second].push_back(&*pl);
+ }
+ }
+ }
+
+ if (!pScene->mNumMeshes) {
+ throw DeadlyImportError("DXF: this file contains no 3d data");
+ }
+
+ pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ] ();
+
+ for(const LayerMap::value_type& elem : layers){
+ aiMesh* const mesh = pScene->mMeshes[elem.second] = new aiMesh();
+ mesh->mName.Set(elem.first);
+
+ unsigned int cvert = 0,cface = 0;
+ for(const DXF::PolyLine* pl : corr[elem.second]){
+ // sum over all faces since we need to 'verbosify' them.
+ cvert += std::accumulate(pl->counts.begin(),pl->counts.end(),0);
+ cface += pl->counts.size();
+ }
+
+ aiVector3D* verts = mesh->mVertices = new aiVector3D[cvert];
+ aiColor4D* colors = mesh->mColors[0] = new aiColor4D[cvert];
+ aiFace* faces = mesh->mFaces = new aiFace[cface];
+
+ mesh->mNumVertices = cvert;
+ mesh->mNumFaces = cface;
+
+ unsigned int prims = 0;
+ unsigned int overall_indices = 0;
+ for(const DXF::PolyLine* pl : corr[elem.second]){
+
+ std::vector<unsigned int>::const_iterator it = pl->indices.begin();
+ for(unsigned int facenumv : pl->counts) {
+ aiFace& face = *faces++;
+ face.mIndices = new unsigned int[face.mNumIndices = facenumv];
+
+ for (unsigned int i = 0; i < facenumv; ++i) {
+ face.mIndices[i] = overall_indices++;
+
+ ai_assert(pl->positions.size() == pl->colors.size());
+ if (*it >= pl->positions.size()) {
+ throw DeadlyImportError("DXF: vertex index out of bounds");
+ }
+
+ *verts++ = pl->positions[*it];
+ *colors++ = pl->colors[*it++];
+ }
+
+ // set primitive flags now, this saves the extra pass in ScenePreprocessor.
+ switch(face.mNumIndices) {
+ case 1:
+ prims |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ prims |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ prims |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ prims |= aiPrimitiveType_POLYGON;
+ break;
+ }
+ }
+ }
+
+ mesh->mPrimitiveTypes = prims;
+ mesh->mMaterialIndex = 0;
+ }
+
+ GenerateHierarchy(pScene,output);
+ GenerateMaterials(pScene,output);
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name)
{
- BOOST_FOREACH (const DXF::InsertBlock& insert, bl.insertions) {
-
- // first check if the referenced blocks exists ...
- const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
- if (it == blocks_by_name.end()) {
- DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "),
- insert.name,"; skipping"
- ));
- continue;
- }
-
- // XXX this would be the place to implement recursive expansion if needed.
- const DXF::Block& bl_src = *(*it).second;
-
- BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl_in, bl_src.lines) {
- boost::shared_ptr<DXF::PolyLine> pl_out = boost::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
-
- if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
- // manual coordinate system transformation
- // XXX order
- aiMatrix4x4 trafo, tmp;
- aiMatrix4x4::Translation(-bl_src.base,trafo);
- trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
- trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
-
- // XXX rotation currently ignored - I didn't find an appropriate sample model.
- if (insert.angle != 0.f) {
- DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented");
- }
-
- BOOST_FOREACH (aiVector3D& v, pl_out->positions) {
- v *= trafo;
- }
- }
-
- bl.lines.push_back(pl_out);
- }
- }
+ for (const DXF::InsertBlock& insert : bl.insertions) {
+
+ // first check if the referenced blocks exists ...
+ const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
+ if (it == blocks_by_name.end()) {
+ DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "),
+ insert.name,"; skipping"
+ ));
+ continue;
+ }
+
+ // XXX this would be the place to implement recursive expansion if needed.
+ const DXF::Block& bl_src = *(*it).second;
+
+ for (std::shared_ptr<const DXF::PolyLine> pl_in : bl_src.lines) {
+ std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
+
+ if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
+ // manual coordinate system transformation
+ // XXX order
+ aiMatrix4x4 trafo, tmp;
+ aiMatrix4x4::Translation(-bl_src.base,trafo);
+ trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
+ trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
+
+ // XXX rotation currently ignored - I didn't find an appropriate sample model.
+ if (insert.angle != 0.f) {
+ DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented");
+ }
+
+ for (aiVector3D& v : pl_out->positions) {
+ v *= trafo;
+ }
+ }
+
+ bl.lines.push_back(pl_out);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
{
- // generate an almost-white default material. Reason:
- // the default vertex color is GREY, so we are
- // already at Assimp's usual default color.
- // generate a default material
- aiMaterial* pcMat = new aiMaterial();
- aiString s;
- s.Set(AI_DEFAULT_MATERIAL_NAME);
- pcMat->AddProperty(&s, AI_MATKEY_NAME);
-
- aiColor4D clrDiffuse(0.9f,0.9f,0.9f,1.0f);
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
-
- clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f);
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
-
- clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
-
- pScene->mNumMaterials = 1;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = pcMat;
+ // generate an almost-white default material. Reason:
+ // the default vertex color is GREY, so we are
+ // already at Assimp's usual default color.
+ // generate a default material
+ aiMaterial* pcMat = new aiMaterial();
+ aiString s;
+ s.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcMat->AddProperty(&s, AI_MATKEY_NAME);
+
+ aiColor4D clrDiffuse(0.9f,0.9f,0.9f,1.0f);
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f);
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
+
+ clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
+
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = pcMat;
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
{
- // generate the output scene graph, which is just the root node with a single child for each layer.
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<DXF_ROOT>");
-
- if (1 == pScene->mNumMeshes) {
- pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
- pScene->mRootNode->mMeshes[0] = 0;
- }
- else
- {
- pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
- for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) {
- aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
- p->mName = pScene->mMeshes[m]->mName;
-
- p->mMeshes = new unsigned int[p->mNumMeshes = 1];
- p->mMeshes[0] = m;
- p->mParent = pScene->mRootNode;
- }
- }
+ // generate the output scene graph, which is just the root node with a single child for each layer.
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<DXF_ROOT>");
+
+ if (1 == pScene->mNumMeshes) {
+ pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
+ pScene->mRootNode->mMeshes[0] = 0;
+ }
+ else
+ {
+ pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
+ for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) {
+ aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
+ p->mName = pScene->mMeshes[m]->mName;
+
+ p->mMeshes = new unsigned int[p->mNumMeshes = 1];
+ p->mMeshes[0] = m;
+ p->mParent = pScene->mRootNode;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::SkipSection(DXF::LineReader& reader)
-{
- for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
+{
+ for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& /*output*/)
-{
- for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
+{
+ for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
-{
- while( !reader.End() && !reader.Is(0,"ENDSEC")) {
- if (reader.Is(0,"BLOCK")) {
- ParseBlock(++reader,output);
- continue;
- }
- ++reader;
- }
-
- DefaultLogger::get()->debug((Formatter::format("DXF: got "),
- output.blocks.size()," entries in BLOCKS"
- ));
+{
+ while( !reader.End() && !reader.Is(0,"ENDSEC")) {
+ if (reader.Is(0,"BLOCK")) {
+ ParseBlock(++reader,output);
+ continue;
+ }
+ ++reader;
+ }
+
+ DefaultLogger::get()->debug((Formatter::format("DXF: got "),
+ output.blocks.size()," entries in BLOCKS"
+ ));
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
-{
- // push a new block onto the stack.
- output.blocks.push_back( DXF::Block() );
- DXF::Block& block = output.blocks.back();
-
- while( !reader.End() && !reader.Is(0,"ENDBLK")) {
-
- switch(reader.GroupCode()) {
- case 2:
- block.name = reader.Value();
- break;
-
- case 10:
- block.base.x = reader.ValueAsFloat();
- break;
- case 20:
- block.base.y = reader.ValueAsFloat();
- break;
- case 30:
- block.base.z = reader.ValueAsFloat();
- break;
- }
-
- if (reader.Is(0,"POLYLINE")) {
- ParsePolyLine(++reader,output);
- continue;
- }
-
- // XXX is this a valid case?
- if (reader.Is(0,"INSERT")) {
- DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping");
- for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
- break;
- }
-
- else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
- //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
- Parse3DFace(++reader, output);
- continue;
- }
- ++reader;
- }
+{
+ // push a new block onto the stack.
+ output.blocks.push_back( DXF::Block() );
+ DXF::Block& block = output.blocks.back();
+
+ while( !reader.End() && !reader.Is(0,"ENDBLK")) {
+
+ switch(reader.GroupCode()) {
+ case 2:
+ block.name = reader.Value();
+ break;
+
+ case 10:
+ block.base.x = reader.ValueAsFloat();
+ break;
+ case 20:
+ block.base.y = reader.ValueAsFloat();
+ break;
+ case 30:
+ block.base.z = reader.ValueAsFloat();
+ break;
+ }
+
+ if (reader.Is(0,"POLYLINE")) {
+ ParsePolyLine(++reader,output);
+ continue;
+ }
+
+ // XXX is this a valid case?
+ if (reader.Is(0,"INSERT")) {
+ DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping");
+ for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
+ break;
+ }
+
+ else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
+ //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
+ Parse3DFace(++reader, output);
+ continue;
+ }
+ ++reader;
+ }
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
-{
- // push a new block onto the stack.
- output.blocks.push_back( DXF::Block() );
- DXF::Block& block = output.blocks.back();
-
- block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
-
- while( !reader.End() && !reader.Is(0,"ENDSEC")) {
- if (reader.Is(0,"POLYLINE")) {
- ParsePolyLine(++reader,output);
- continue;
- }
-
- else if (reader.Is(0,"INSERT")) {
- ParseInsertion(++reader,output);
- continue;
- }
-
- else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
- //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
- Parse3DFace(++reader, output);
- continue;
- }
-
- ++reader;
- }
-
- DefaultLogger::get()->debug((Formatter::format("DXF: got "),
- block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES"
- ));
+{
+ // push a new block onto the stack.
+ output.blocks.push_back( DXF::Block() );
+ DXF::Block& block = output.blocks.back();
+
+ block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
+
+ while( !reader.End() && !reader.Is(0,"ENDSEC")) {
+ if (reader.Is(0,"POLYLINE")) {
+ ParsePolyLine(++reader,output);
+ continue;
+ }
+
+ else if (reader.Is(0,"INSERT")) {
+ ParseInsertion(++reader,output);
+ continue;
+ }
+
+ else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
+ //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
+ Parse3DFace(++reader, output);
+ continue;
+ }
+
+ ++reader;
+ }
+
+ DefaultLogger::get()->debug((Formatter::format("DXF: got "),
+ block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES"
+ ));
}
void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
-{
- output.blocks.back().insertions.push_back( DXF::InsertBlock() );
- DXF::InsertBlock& bl = output.blocks.back().insertions.back();
-
- while( !reader.End() && !reader.Is(0)) {
-
- switch(reader.GroupCode())
- {
- // name of referenced block
- case 2:
- bl.name = reader.Value();
- break;
-
- // translation
- case 10:
- bl.pos.x = reader.ValueAsFloat();
- break;
- case 20:
- bl.pos.y = reader.ValueAsFloat();
- break;
- case 30:
- bl.pos.z = reader.ValueAsFloat();
- break;
-
- // scaling
- case 41:
- bl.scale.x = reader.ValueAsFloat();
- break;
- case 42:
- bl.scale.y = reader.ValueAsFloat();
- break;
- case 43:
- bl.scale.z = reader.ValueAsFloat();
- break;
-
- // rotation angle
- case 50:
- bl.angle = reader.ValueAsFloat();
- break;
- }
- reader++;
- }
+{
+ output.blocks.back().insertions.push_back( DXF::InsertBlock() );
+ DXF::InsertBlock& bl = output.blocks.back().insertions.back();
+
+ while( !reader.End() && !reader.Is(0)) {
+
+ switch(reader.GroupCode())
+ {
+ // name of referenced block
+ case 2:
+ bl.name = reader.Value();
+ break;
+
+ // translation
+ case 10:
+ bl.pos.x = reader.ValueAsFloat();
+ break;
+ case 20:
+ bl.pos.y = reader.ValueAsFloat();
+ break;
+ case 30:
+ bl.pos.z = reader.ValueAsFloat();
+ break;
+
+ // scaling
+ case 41:
+ bl.scale.x = reader.ValueAsFloat();
+ break;
+ case 42:
+ bl.scale.y = reader.ValueAsFloat();
+ break;
+ case 43:
+ bl.scale.z = reader.ValueAsFloat();
+ break;
+
+ // rotation angle
+ case 50:
+ bl.angle = reader.ValueAsFloat();
+ break;
+ }
+ reader++;
+ }
}
-#define DXF_POLYLINE_FLAG_CLOSED 0x1
-#define DXF_POLYLINE_FLAG_3D_POLYLINE 0x8
-#define DXF_POLYLINE_FLAG_3D_POLYMESH 0x10
-#define DXF_POLYLINE_FLAG_POLYFACEMESH 0x40
+#define DXF_POLYLINE_FLAG_CLOSED 0x1
+#define DXF_POLYLINE_FLAG_3D_POLYLINE 0x8
+#define DXF_POLYLINE_FLAG_3D_POLYMESH 0x10
+#define DXF_POLYLINE_FLAG_POLYFACEMESH 0x40
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
{
- output.blocks.back().lines.push_back( boost::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
- DXF::PolyLine& line = *output.blocks.back().lines.back();
-
- unsigned int iguess = 0, vguess = 0;
- while( !reader.End() && !reader.Is(0,"ENDSEC")) {
-
- if (reader.Is(0,"VERTEX")) {
- ParsePolyLineVertex(++reader,line);
- if (reader.Is(0,"SEQEND")) {
- break;
- }
- continue;
- }
-
- switch(reader.GroupCode())
- {
- // flags --- important that we know whether it is a
- // polyface mesh or 'just' a line.
- case 70:
- if (!line.flags) {
- line.flags = reader.ValueAsSignedInt();
- }
- break;
-
- // optional number of vertices
- case 71:
- vguess = reader.ValueAsSignedInt();
- line.positions.reserve(vguess);
- break;
-
- // optional number of faces
- case 72:
- iguess = reader.ValueAsSignedInt();
- line.indices.reserve(iguess);
- break;
-
- // 8 specifies the layer on which this line is placed on
- case 8:
- line.layer = reader.Value();
- break;
- }
-
- reader++;
- }
-
- //if (!(line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH)) {
- // DefaultLogger::get()->warn((Formatter::format("DXF: polyline not currently supported: "),line.flags));
- // output.blocks.back().lines.pop_back();
- // return;
- //}
-
- if (vguess && line.positions.size() != vguess) {
- DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "),
- line.positions.size(),", expected ", vguess
- ));
- }
-
- if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
- if (line.positions.size() < 3 || line.indices.size() < 3) {
- DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring");
- output.blocks.back().lines.pop_back();
- return;
- }
-
- // if these numbers are wrong, parsing might have gone wild.
- // however, the docs state that applications are not required
- // to set the 71 and 72 fields, respectively, to valid values.
- // So just fire a warning.
- if (iguess && line.counts.size() != iguess) {
- DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "),
- line.counts.size(),", expected ", iguess
- ));
- }
- }
- else if (!line.indices.size() && !line.counts.size()) {
- // a polyline - so there are no indices yet.
- size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
- line.indices.reserve(guess);
-
- line.counts.reserve(guess/2);
- for (unsigned int i = 0; i < line.positions.size()/2; ++i) {
- line.indices.push_back(i*2);
- line.indices.push_back(i*2+1);
- line.counts.push_back(2);
- }
-
- // closed polyline?
- if (line.flags & DXF_POLYLINE_FLAG_CLOSED) {
- line.indices.push_back(line.positions.size()-1);
- line.indices.push_back(0);
- line.counts.push_back(2);
- }
- }
+ output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
+ DXF::PolyLine& line = *output.blocks.back().lines.back();
+
+ unsigned int iguess = 0, vguess = 0;
+ while( !reader.End() && !reader.Is(0,"ENDSEC")) {
+
+ if (reader.Is(0,"VERTEX")) {
+ ParsePolyLineVertex(++reader,line);
+ if (reader.Is(0,"SEQEND")) {
+ break;
+ }
+ continue;
+ }
+
+ switch(reader.GroupCode())
+ {
+ // flags --- important that we know whether it is a
+ // polyface mesh or 'just' a line.
+ case 70:
+ if (!line.flags) {
+ line.flags = reader.ValueAsSignedInt();
+ }
+ break;
+
+ // optional number of vertices
+ case 71:
+ vguess = reader.ValueAsSignedInt();
+ line.positions.reserve(vguess);
+ break;
+
+ // optional number of faces
+ case 72:
+ iguess = reader.ValueAsSignedInt();
+ line.indices.reserve(iguess);
+ break;
+
+ // 8 specifies the layer on which this line is placed on
+ case 8:
+ line.layer = reader.Value();
+ break;
+ }
+
+ reader++;
+ }
+
+ //if (!(line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH)) {
+ // DefaultLogger::get()->warn((Formatter::format("DXF: polyline not currently supported: "),line.flags));
+ // output.blocks.back().lines.pop_back();
+ // return;
+ //}
+
+ if (vguess && line.positions.size() != vguess) {
+ DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "),
+ line.positions.size(),", expected ", vguess
+ ));
+ }
+
+ if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
+ if (line.positions.size() < 3 || line.indices.size() < 3) {
+ DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring");
+ output.blocks.back().lines.pop_back();
+ return;
+ }
+
+ // if these numbers are wrong, parsing might have gone wild.
+ // however, the docs state that applications are not required
+ // to set the 71 and 72 fields, respectively, to valid values.
+ // So just fire a warning.
+ if (iguess && line.counts.size() != iguess) {
+ DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "),
+ line.counts.size(),", expected ", iguess
+ ));
+ }
+ }
+ else if (!line.indices.size() && !line.counts.size()) {
+ // a polyline - so there are no indices yet.
+ size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
+ line.indices.reserve(guess);
+
+ line.counts.reserve(guess/2);
+ for (unsigned int i = 0; i < line.positions.size()/2; ++i) {
+ line.indices.push_back(i*2);
+ line.indices.push_back(i*2+1);
+ line.counts.push_back(2);
+ }
+
+ // closed polyline?
+ if (line.flags & DXF_POLYLINE_FLAG_CLOSED) {
+ line.indices.push_back(line.positions.size()-1);
+ line.indices.push_back(0);
+ line.counts.push_back(2);
+ }
+ }
}
#define DXF_VERTEX_FLAG_PART_OF_POLYFACE 0x80
@@ -715,198 +718,198 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
// ------------------------------------------------------------------------------------------------
void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line)
{
- unsigned int cnti = 0, flags = 0;
- unsigned int indices[4];
-
- aiVector3D out;
- aiColor4D clr = AI_DXF_DEFAULT_COLOR;
-
- while( !reader.End() ) {
-
- if (reader.Is(0)) { // SEQEND or another VERTEX
- break;
- }
-
- switch (reader.GroupCode())
- {
- case 8:
- // layer to which the vertex belongs to - assume that
- // this is always the layer the top-level polyline
- // entity resides on as well.
- if(reader.Value() != line.layer) {
- DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
- }
- break;
-
- case 70:
- flags = reader.ValueAsUnsignedInt();
- break;
-
- // VERTEX COORDINATES
- case 10: out.x = reader.ValueAsFloat();break;
- case 20: out.y = reader.ValueAsFloat();break;
- case 30: out.z = reader.ValueAsFloat();break;
-
- // POLYFACE vertex indices
- case 71:
- case 72:
- case 73:
- case 74:
- if (cnti == 4) {
- DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring");
- break;
- }
- indices[cnti++] = reader.ValueAsUnsignedInt();
- break;
-
- // color
- case 62:
- clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
- break;
- };
-
- reader++;
- }
-
- if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
- DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
- }
-
- if (cnti) {
- line.counts.push_back(cnti);
- for (unsigned int i = 0; i < cnti; ++i) {
- // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
- if (indices[i] == 0) {
- DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based.");
- --line.counts.back();
- continue;
- }
- line.indices.push_back(indices[i]-1);
- }
- }
- else {
- line.positions.push_back(out);
- line.colors.push_back(clr);
- }
+ unsigned int cnti = 0, flags = 0;
+ unsigned int indices[4];
+
+ aiVector3D out;
+ aiColor4D clr = AI_DXF_DEFAULT_COLOR;
+
+ while( !reader.End() ) {
+
+ if (reader.Is(0)) { // SEQEND or another VERTEX
+ break;
+ }
+
+ switch (reader.GroupCode())
+ {
+ case 8:
+ // layer to which the vertex belongs to - assume that
+ // this is always the layer the top-level polyline
+ // entity resides on as well.
+ if(reader.Value() != line.layer) {
+ DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
+ }
+ break;
+
+ case 70:
+ flags = reader.ValueAsUnsignedInt();
+ break;
+
+ // VERTEX COORDINATES
+ case 10: out.x = reader.ValueAsFloat();break;
+ case 20: out.y = reader.ValueAsFloat();break;
+ case 30: out.z = reader.ValueAsFloat();break;
+
+ // POLYFACE vertex indices
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ if (cnti == 4) {
+ DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring");
+ break;
+ }
+ indices[cnti++] = reader.ValueAsUnsignedInt();
+ break;
+
+ // color
+ case 62:
+ clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
+ break;
+ };
+
+ reader++;
+ }
+
+ if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
+ DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
+ }
+
+ if (cnti) {
+ line.counts.push_back(cnti);
+ for (unsigned int i = 0; i < cnti; ++i) {
+ // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
+ if (indices[i] == 0) {
+ DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based.");
+ --line.counts.back();
+ continue;
+ }
+ line.indices.push_back(indices[i]-1);
+ }
+ }
+ else {
+ line.positions.push_back(out);
+ line.colors.push_back(clr);
+ }
}
// ------------------------------------------------------------------------------------------------
void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
{
- // (note) this is also used for for parsing line entities, so we
- // must handle the vertex_count == 2 case as well.
-
- output.blocks.back().lines.push_back( boost::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
- DXF::PolyLine& line = *output.blocks.back().lines.back();
-
- aiVector3D vip[4];
- aiColor4D clr = AI_DXF_DEFAULT_COLOR;
-
- bool b[4] = {false,false,false,false};
- while( !reader.End() ) {
-
- // next entity with a groupcode == 0 is probably already the next vertex or polymesh entity
- if (reader.GroupCode() == 0) {
- break;
- }
- switch (reader.GroupCode())
- {
-
- // 8 specifies the layer
- case 8:
- line.layer = reader.Value();
- break;
-
- // x position of the first corner
- case 10: vip[0].x = reader.ValueAsFloat();
- b[2] = true;
- break;
-
- // y position of the first corner
- case 20: vip[0].y = reader.ValueAsFloat();
- b[2] = true;
- break;
-
- // z position of the first corner
- case 30: vip[0].z = reader.ValueAsFloat();
- b[2] = true;
- break;
-
- // x position of the second corner
- case 11: vip[1].x = reader.ValueAsFloat();
- b[3] = true;
- break;
-
- // y position of the second corner
- case 21: vip[1].y = reader.ValueAsFloat();
- b[3] = true;
- break;
-
- // z position of the second corner
- case 31: vip[1].z = reader.ValueAsFloat();
- b[3] = true;
- break;
-
- // x position of the third corner
- case 12: vip[2].x = reader.ValueAsFloat();
- b[0] = true;
- break;
-
- // y position of the third corner
- case 22: vip[2].y = reader.ValueAsFloat();
- b[0] = true;
- break;
-
- // z position of the third corner
- case 32: vip[2].z = reader.ValueAsFloat();
- b[0] = true;
- break;
-
- // x position of the fourth corner
- case 13: vip[3].x = reader.ValueAsFloat();
- b[1] = true;
- break;
-
- // y position of the fourth corner
- case 23: vip[3].y = reader.ValueAsFloat();
- b[1] = true;
- break;
-
- // z position of the fourth corner
- case 33: vip[3].z = reader.ValueAsFloat();
- b[1] = true;
- break;
-
- // color
- case 62:
- clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
- break;
- };
-
- ++reader;
- }
-
- // the fourth corner may even be identical to the third,
- // in this case we treat it as if it didn't exist.
- if (vip[3] == vip[2]) {
- b[1] = false;
- }
-
- // sanity checks to see if we got something meaningful
- if ((b[1] && !b[0]) || !b[2] || !b[3]) {
- DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
- output.blocks.back().lines.pop_back();
- return;
- }
-
- const unsigned int cnt = (2+(b[0]?1:0)+(b[1]?1:0));
- line.counts.push_back(cnt);
-
- for (unsigned int i = 0; i < cnt; ++i) {
- line.indices.push_back(line.positions.size());
- line.positions.push_back(vip[i]);
- line.colors.push_back(clr);
- }
+ // (note) this is also used for for parsing line entities, so we
+ // must handle the vertex_count == 2 case as well.
+
+ output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
+ DXF::PolyLine& line = *output.blocks.back().lines.back();
+
+ aiVector3D vip[4];
+ aiColor4D clr = AI_DXF_DEFAULT_COLOR;
+
+ bool b[4] = {false,false,false,false};
+ while( !reader.End() ) {
+
+ // next entity with a groupcode == 0 is probably already the next vertex or polymesh entity
+ if (reader.GroupCode() == 0) {
+ break;
+ }
+ switch (reader.GroupCode())
+ {
+
+ // 8 specifies the layer
+ case 8:
+ line.layer = reader.Value();
+ break;
+
+ // x position of the first corner
+ case 10: vip[0].x = reader.ValueAsFloat();
+ b[2] = true;
+ break;
+
+ // y position of the first corner
+ case 20: vip[0].y = reader.ValueAsFloat();
+ b[2] = true;
+ break;
+
+ // z position of the first corner
+ case 30: vip[0].z = reader.ValueAsFloat();
+ b[2] = true;
+ break;
+
+ // x position of the second corner
+ case 11: vip[1].x = reader.ValueAsFloat();
+ b[3] = true;
+ break;
+
+ // y position of the second corner
+ case 21: vip[1].y = reader.ValueAsFloat();
+ b[3] = true;
+ break;
+
+ // z position of the second corner
+ case 31: vip[1].z = reader.ValueAsFloat();
+ b[3] = true;
+ break;
+
+ // x position of the third corner
+ case 12: vip[2].x = reader.ValueAsFloat();
+ b[0] = true;
+ break;
+
+ // y position of the third corner
+ case 22: vip[2].y = reader.ValueAsFloat();
+ b[0] = true;
+ break;
+
+ // z position of the third corner
+ case 32: vip[2].z = reader.ValueAsFloat();
+ b[0] = true;
+ break;
+
+ // x position of the fourth corner
+ case 13: vip[3].x = reader.ValueAsFloat();
+ b[1] = true;
+ break;
+
+ // y position of the fourth corner
+ case 23: vip[3].y = reader.ValueAsFloat();
+ b[1] = true;
+ break;
+
+ // z position of the fourth corner
+ case 33: vip[3].z = reader.ValueAsFloat();
+ b[1] = true;
+ break;
+
+ // color
+ case 62:
+ clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
+ break;
+ };
+
+ ++reader;
+ }
+
+ // the fourth corner may even be identical to the third,
+ // in this case we treat it as if it didn't exist.
+ if (vip[3] == vip[2]) {
+ b[1] = false;
+ }
+
+ // sanity checks to see if we got something meaningful
+ if ((b[1] && !b[0]) || !b[2] || !b[3]) {
+ DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
+ output.blocks.back().lines.pop_back();
+ return;
+ }
+
+ const unsigned int cnt = (2+(b[0]?1:0)+(b[1]?1:0));
+ line.counts.push_back(cnt);
+
+ for (unsigned int i = 0; i < cnt; ++i) {
+ line.indices.push_back(line.positions.size());
+ line.positions.push_back(vip[i]);
+ line.colors.push_back(clr);
+ }
}
#endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER
diff --git a/src/3rdparty/assimp/code/DXFLoader.h b/src/3rdparty/assimp/code/DXFLoader.h
index a261874f4..13af4cdec 100644
--- a/src/3rdparty/assimp/code/DXFLoader.h
+++ b/src/3rdparty/assimp/code/DXFLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,22 +23,22 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file DXFLoader.h
+/** @file DXFLoader.h
* @brief Declaration of the .dxf importer class.
*/
#ifndef AI_DXFLOADER_H_INCLUDED
@@ -46,17 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
-namespace Assimp {
- namespace DXF {
-
- class LineReader;
- struct FileData;
- struct PolyLine;
- struct Block;
- struct InsertBlock;
+namespace Assimp {
+ namespace DXF {
- typedef std::map<std::string, const DXF::Block*> BlockMap;
- }
+ class LineReader;
+ struct FileData;
+ struct PolyLine;
+ struct Block;
+ struct InsertBlock;
+
+ typedef std::map<std::string, const DXF::Block*> BlockMap;
+ }
// ---------------------------------------------------------------------------
@@ -66,85 +66,85 @@ namespace Assimp {
class DXFImporter : public BaseImporter
{
public:
- DXFImporter();
- ~DXFImporter();
+ DXFImporter();
+ ~DXFImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details*/
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details*/
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details */
- void InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details */
+ void InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- // -----------------------------------------------------
- void SkipSection(DXF::LineReader& reader);
+ // -----------------------------------------------------
+ void SkipSection(DXF::LineReader& reader);
- // -----------------------------------------------------
- void ParseHeader(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParseHeader(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParseEntities(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParseEntities(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParseBlocks(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParseBlocks(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParseBlock(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParseBlock(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParseInsertion(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParseInsertion(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParsePolyLine(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ParsePolyLine(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ParsePolyLineVertex(DXF::LineReader& reader,
- DXF::PolyLine& line);
+ // -----------------------------------------------------
+ void ParsePolyLineVertex(DXF::LineReader& reader,
+ DXF::PolyLine& line);
- // -----------------------------------------------------
- void Parse3DFace(DXF::LineReader& reader,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void Parse3DFace(DXF::LineReader& reader,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ConvertMeshes(aiScene* pScene,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void ConvertMeshes(aiScene* pScene,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void GenerateHierarchy(aiScene* pScene,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void GenerateHierarchy(aiScene* pScene,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void GenerateMaterials(aiScene* pScene,
- DXF::FileData& output);
+ // -----------------------------------------------------
+ void GenerateMaterials(aiScene* pScene,
+ DXF::FileData& output);
- // -----------------------------------------------------
- void ExpandBlockReferences(DXF::Block& bl,
- const DXF::BlockMap& blocks_by_name);
+ // -----------------------------------------------------
+ void ExpandBlockReferences(DXF::Block& bl,
+ const DXF::BlockMap& blocks_by_name);
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/DeboneProcess.cpp b/src/3rdparty/assimp/code/DeboneProcess.cpp
index c292d7224..5d688f813 100644
--- a/src/3rdparty/assimp/code/DeboneProcess.cpp
+++ b/src/3rdparty/assimp/code/DeboneProcess.cpp
@@ -1,12 +1,12 @@
- /*
+/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,11 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// @file DeboneProcess.cpp
/** Implementation of the DeboneProcess post processing step */
-#include "AssimpPCH.h"
+
// internal headers of the post-processing framework
#include "ProcessHelper.h"
#include "DeboneProcess.h"
+#include <stdio.h>
using namespace Assimp;
@@ -54,411 +55,411 @@ using namespace Assimp;
// Constructor to be privately used by Importer
DeboneProcess::DeboneProcess()
{
- mNumBones = 0;
- mNumBonesCanDoWithout = 0;
+ mNumBones = 0;
+ mNumBonesCanDoWithout = 0;
- mThreshold = AI_DEBONE_THRESHOLD;
- mAllOrNone = false;
+ mThreshold = AI_DEBONE_THRESHOLD;
+ mAllOrNone = false;
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
DeboneProcess::~DeboneProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool DeboneProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_Debone) != 0;
+ return (pFlags & aiProcess_Debone) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void DeboneProcess::SetupProperties(const Importer* pImp)
-{
- // get the current value of the property
- mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
- mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
+{
+ // get the current value of the property
+ mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
+ mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void DeboneProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("DeboneProcess begin");
-
- if(!pScene->mNumMeshes) {
- return;
- }
-
- std::vector<bool> splitList(pScene->mNumMeshes);
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
- splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
- }
-
- int numSplits = 0;
-
- if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
- for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
- if(splitList[a]) {
- numSplits++;
- }
- }
- }
-
- if(numSplits) {
- // 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<std::pair<aiMesh*,const aiBone*> > newMeshes;
-
- if(splitList[a]) {
- SplitMesh(srcMesh,newMeshes);
- }
-
- // mesh was split
- if(!newMeshes.empty()) {
- unsigned int out = 0, in = srcMesh->mNumBones;
-
- // store new meshes and indices of the new meshes
- for(unsigned int b=0;b<newMeshes.size();b++) {
- const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
-
- aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
- std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
-
- mSubMeshIndices[a].push_back(push_pair);
- meshes.push_back(newMeshes[b].first);
-
- out+=newMeshes[b].first->mNumBones;
- }
-
- if(!DefaultLogger::isNullLogger()) {
- char buffer[1024];
- ::sprintf(buffer,"Removed %i bones. Input bones: %i. Output bones: %i",in-out,in,out);
- DefaultLogger::get()->info(buffer);
- }
-
- // 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(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
- meshes.push_back(srcMesh);
- }
- }
-
- // rebuild the scene's mesh array
- pScene->mNumMeshes = 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);
- }
-
- DefaultLogger::get()->debug("DeboneProcess end");
+ DefaultLogger::get()->debug("DeboneProcess begin");
+
+ if(!pScene->mNumMeshes) {
+ return;
+ }
+
+ std::vector<bool> splitList(pScene->mNumMeshes);
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
+ }
+
+ int numSplits = 0;
+
+ if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
+ for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ if(splitList[a]) {
+ numSplits++;
+ }
+ }
+ }
+
+ if(numSplits) {
+ // we need to do something. Let's go.
+ //mSubMeshIndices.clear(); // really needed?
+ mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
+
+ // 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<std::pair<aiMesh*,const aiBone*> > newMeshes;
+
+ if(splitList[a]) {
+ SplitMesh(srcMesh,newMeshes);
+ }
+
+ // mesh was split
+ if(!newMeshes.empty()) {
+ unsigned int out = 0, in = srcMesh->mNumBones;
+
+ // store new meshes and indices of the new meshes
+ for(unsigned int b=0;b<newMeshes.size();b++) {
+ const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
+
+ aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
+ std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
+
+ mSubMeshIndices[a].push_back(push_pair);
+ meshes.push_back(newMeshes[b].first);
+
+ out+=newMeshes[b].first->mNumBones;
+ }
+
+ if(!DefaultLogger::isNullLogger()) {
+ char buffer[1024];
+ ::ai_snprintf(buffer,1024,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out);
+ DefaultLogger::get()->info(buffer);
+ }
+
+ // 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(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
+ meshes.push_back(srcMesh);
+ }
+ }
+
+ // rebuild the scene's mesh array
+ pScene->mNumMeshes = 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);
+ }
+
+ DefaultLogger::get()->debug("DeboneProcess end");
}
// ------------------------------------------------------------------------------------------------
// Counts bones total/removable in a given mesh.
bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
{
- if(!pMesh->HasBones()) {
- return false;
- }
-
- bool split = false;
-
- //interstitial faces not permitted
- bool isInterstitialRequired = false;
-
- std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
- std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
-
- const unsigned int cUnowned = UINT_MAX;
- const unsigned int cCoowned = UINT_MAX-1;
-
- for(unsigned int i=0;i<pMesh->mNumBones;i++) {
- for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
- float w = pMesh->mBones[i]->mWeights[j].mWeight;
-
- if(w==0.0f) {
- continue;
- }
-
- unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
- if(w>=mThreshold) {
-
- if(vertexBones[vid]!=cUnowned) {
- if(vertexBones[vid]==i) //double entry
- {
- DefaultLogger::get()->warn("Encountered double entry in bone weights");
- }
- else //TODO: track attraction in order to break tie
- {
- vertexBones[vid] = cCoowned;
- }
- }
- else vertexBones[vid] = i;
- }
-
- if(!isBoneNecessary[i]) {
- isBoneNecessary[i] = w<mThreshold;
- }
- }
-
- if(!isBoneNecessary[i]) {
- isInterstitialRequired = true;
- }
- }
-
- if(isInterstitialRequired) {
- for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
- unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
-
- for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
- unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
-
- if(v!=w) {
- if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
- if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
- }
- }
- }
- }
-
- for(unsigned int i=0;i<pMesh->mNumBones;i++) {
- if(!isBoneNecessary[i]) {
- mNumBonesCanDoWithout++;
- split = true;
- }
-
- mNumBones++;
- }
- return split;
+ if(!pMesh->HasBones()) {
+ return false;
+ }
+
+ bool split = false;
+
+ //interstitial faces not permitted
+ bool isInterstitialRequired = false;
+
+ std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+ std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+ const unsigned int cUnowned = UINT_MAX;
+ const unsigned int cCoowned = UINT_MAX-1;
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
+ float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+ if(w==0.0f) {
+ continue;
+ }
+
+ unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+ if(w>=mThreshold) {
+
+ if(vertexBones[vid]!=cUnowned) {
+ if(vertexBones[vid]==i) //double entry
+ {
+ DefaultLogger::get()->warn("Encountered double entry in bone weights");
+ }
+ else //TODO: track attraction in order to break tie
+ {
+ vertexBones[vid] = cCoowned;
+ }
+ }
+ else vertexBones[vid] = i;
+ }
+
+ if(!isBoneNecessary[i]) {
+ isBoneNecessary[i] = w<mThreshold;
+ }
+ }
+
+ if(!isBoneNecessary[i]) {
+ isInterstitialRequired = true;
+ }
+ }
+
+ if(isInterstitialRequired) {
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+ for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+ unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+ if(v!=w) {
+ if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+ if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+ }
+ }
+ }
+ }
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ if(!isBoneNecessary[i]) {
+ mNumBonesCanDoWithout++;
+ split = true;
+ }
+
+ mNumBones++;
+ }
+ return split;
}
// ------------------------------------------------------------------------------------------------
// Splits the given mesh by bone count.
void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const
{
- // same deal here as ConsiderMesh basically
-
- std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
- std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
-
- const unsigned int cUnowned = UINT_MAX;
- const unsigned int cCoowned = UINT_MAX-1;
-
- for(unsigned int i=0;i<pMesh->mNumBones;i++) {
- for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
- float w = pMesh->mBones[i]->mWeights[j].mWeight;
-
- if(w==0.0f) {
- continue;
- }
-
- unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
-
- if(w>=mThreshold) {
- if(vertexBones[vid]!=cUnowned) {
- if(vertexBones[vid]==i) //double entry
- {
- //DefaultLogger::get()->warn("Encountered double entry in bone weights");
- }
- else //TODO: track attraction in order to break tie
- {
- vertexBones[vid] = cCoowned;
- }
- }
- else vertexBones[vid] = i;
- }
-
- if(!isBoneNecessary[i]) {
- isBoneNecessary[i] = w<mThreshold;
- }
- }
- }
-
- unsigned int nFacesUnowned = 0;
-
- std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
- std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
-
- for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
- unsigned int nInterstitial = 1;
-
- unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
-
- for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
- unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
-
- if(v!=w) {
- if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
- if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
- }
- else nInterstitial++;
- }
-
- if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) {
- faceBones[i] = v; //primitive belongs to bone #v
- facesPerBone[v]++;
- }
- else nFacesUnowned++;
- }
-
- // invalidate any "cojoined" faces
- for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
- if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
- {
- ai_assert(facesPerBone[faceBones[i]]>0);
- facesPerBone[faceBones[i]]--;
-
- nFacesUnowned++;
- faceBones[i] = cUnowned;
- }
- }
-
- if(nFacesUnowned) {
- std::vector<unsigned int> subFaces;
-
- for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
- if(faceBones[i]==cUnowned) {
- subFaces.push_back(i);
- }
- }
-
- aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
- std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
-
- poNewMeshes.push_back(push_pair);
- }
-
- for(unsigned int i=0;i<pMesh->mNumBones;i++) {
-
- if(!isBoneNecessary[i]&&facesPerBone[i]>0) {
- std::vector<unsigned int> subFaces;
-
- for(unsigned int j=0;j<pMesh->mNumFaces;j++) {
- if(faceBones[j]==i) {
- subFaces.push_back(j);
- }
- }
-
- unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
- aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
-
- //Lifted from PretransformVertices.cpp
- ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
- std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
-
- poNewMeshes.push_back(push_pair);
- }
- }
+ // same deal here as ConsiderMesh basically
+
+ std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+ std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+ const unsigned int cUnowned = UINT_MAX;
+ const unsigned int cCoowned = UINT_MAX-1;
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+ for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
+ float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+ if(w==0.0f) {
+ continue;
+ }
+
+ unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+
+ if(w>=mThreshold) {
+ if(vertexBones[vid]!=cUnowned) {
+ if(vertexBones[vid]==i) //double entry
+ {
+ //DefaultLogger::get()->warn("Encountered double entry in bone weights");
+ }
+ else //TODO: track attraction in order to break tie
+ {
+ vertexBones[vid] = cCoowned;
+ }
+ }
+ else vertexBones[vid] = i;
+ }
+
+ if(!isBoneNecessary[i]) {
+ isBoneNecessary[i] = w<mThreshold;
+ }
+ }
+ }
+
+ unsigned int nFacesUnowned = 0;
+
+ std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
+ std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
+
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ unsigned int nInterstitial = 1;
+
+ unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+ for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+ unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+ if(v!=w) {
+ if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+ if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+ }
+ else nInterstitial++;
+ }
+
+ if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) {
+ faceBones[i] = v; //primitive belongs to bone #v
+ facesPerBone[v]++;
+ }
+ else nFacesUnowned++;
+ }
+
+ // invalidate any "cojoined" faces
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
+ {
+ ai_assert(facesPerBone[faceBones[i]]>0);
+ facesPerBone[faceBones[i]]--;
+
+ nFacesUnowned++;
+ faceBones[i] = cUnowned;
+ }
+ }
+
+ if(nFacesUnowned) {
+ std::vector<unsigned int> subFaces;
+
+ for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+ if(faceBones[i]==cUnowned) {
+ subFaces.push_back(i);
+ }
+ }
+
+ aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
+ std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
+
+ poNewMeshes.push_back(push_pair);
+ }
+
+ for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+
+ if(!isBoneNecessary[i]&&facesPerBone[i]>0) {
+ std::vector<unsigned int> subFaces;
+
+ for(unsigned int j=0;j<pMesh->mNumFaces;j++) {
+ if(faceBones[j]==i) {
+ subFaces.push_back(j);
+ }
+ }
+
+ unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
+ aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
+
+ //Lifted from PretransformVertices.cpp
+ ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
+ std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
+
+ poNewMeshes.push_back(push_pair);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Recursively updates the node's mesh list to account for the changed mesh list
void DeboneProcess::UpdateNode(aiNode* pNode) const
{
- // rebuild the node's mesh index list
-
- std::vector<unsigned int> newMeshList;
-
- // this will require two passes
-
- unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
-
- // first pass, look for meshes which have not moved
-
- for(unsigned int a=0;a<m;a++) {
-
- unsigned int srcIndex = pNode->mMeshes[a];
- const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
- unsigned int nSubmeshes = subMeshes.size();
-
- for(unsigned int b=0;b<nSubmeshes;b++) {
- if(!subMeshes[b].second) {
- newMeshList.push_back(subMeshes[b].first);
- }
- }
- }
-
- // second pass, collect deboned meshes
-
- for(unsigned int a=0;a<n;a++)
- {
- const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
- unsigned int nSubmeshes = subMeshes.size();
-
- for(unsigned int b=0;b<nSubmeshes;b++) {
- if(subMeshes[b].second == pNode) {
- newMeshList.push_back(subMeshes[b].first);
- }
- }
- }
-
- if( pNode->mNumMeshes > 0 ) {
- delete [] pNode->mMeshes; pNode->mMeshes = NULL;
- }
-
- pNode->mNumMeshes = newMeshList.size();
-
- if(pNode->mNumMeshes) {
- 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]);
- }
+ // rebuild the node's mesh index list
+
+ std::vector<unsigned int> newMeshList;
+
+ // this will require two passes
+
+ unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
+
+ // first pass, look for meshes which have not moved
+
+ for(unsigned int a=0;a<m;a++) {
+
+ unsigned int srcIndex = pNode->mMeshes[a];
+ const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
+ unsigned int nSubmeshes = subMeshes.size();
+
+ for(unsigned int b=0;b<nSubmeshes;b++) {
+ if(!subMeshes[b].second) {
+ newMeshList.push_back(subMeshes[b].first);
+ }
+ }
+ }
+
+ // second pass, collect deboned meshes
+
+ for(unsigned int a=0;a<n;a++)
+ {
+ const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
+ unsigned int nSubmeshes = subMeshes.size();
+
+ for(unsigned int b=0;b<nSubmeshes;b++) {
+ if(subMeshes[b].second == pNode) {
+ newMeshList.push_back(subMeshes[b].first);
+ }
+ }
+ }
+
+ if( pNode->mNumMeshes > 0 ) {
+ delete [] pNode->mMeshes; pNode->mMeshes = NULL;
+ }
+
+ pNode->mNumMeshes = newMeshList.size();
+
+ if(pNode->mNumMeshes) {
+ 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]);
+ }
}
// ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh
void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const
{
- // Check whether we need to transform the coordinates at all
- if (!mat.IsIdentity()) {
-
- if (mesh->HasPositions()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mVertices[i] = mat * mesh->mVertices[i];
- }
- }
- if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
- aiMatrix4x4 mWorldIT = mat;
- mWorldIT.Inverse().Transpose();
-
- // TODO: implement Inverse() for aiMatrix3x3
- aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
-
- if (mesh->HasNormals()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
- }
- }
- if (mesh->HasTangentsAndBitangents()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
- mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
- }
- }
- }
- }
+ // Check whether we need to transform the coordinates at all
+ if (!mat.IsIdentity()) {
+
+ if (mesh->HasPositions()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mVertices[i] = mat * mesh->mVertices[i];
+ }
+ }
+ if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
+ aiMatrix4x4 mWorldIT = mat;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (mesh->HasNormals()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+ }
+ }
+ if (mesh->HasTangentsAndBitangents()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
+ mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
+ }
+ }
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/DeboneProcess.h b/src/3rdparty/assimp/code/DeboneProcess.h
index 37404ecc0..5920473e2 100644
--- a/src/3rdparty/assimp/code/DeboneProcess.h
+++ b/src/3rdparty/assimp/code/DeboneProcess.h
@@ -1,12 +1,12 @@
- /*
+ /*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <utility>
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/scene.h"
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
class DeboneTest;
@@ -55,76 +55,76 @@ namespace Assimp
{
#if (!defined AI_DEBONE_THRESHOLD)
-# define AI_DEBONE_THRESHOLD 1.0f
+# define AI_DEBONE_THRESHOLD 1.0f
#endif // !! AI_DEBONE_THRESHOLD
// ---------------------------------------------------------------------------
-/** This post processing step removes bones nearly losslessly or according to
+/** This post processing step removes bones nearly losslessly or according to
* a configured threshold. In order to remove the bone, the primitives affected by
-* the bone are split from the mesh. The split off (new) mesh is boneless. At any
+* the bone are split from the mesh. The split off (new) mesh is boneless. At any
* point in time, bones without affect upon a given mesh are to be removed.
*/
class DeboneProcess : public BaseProcess
{
public:
- DeboneProcess();
- ~DeboneProcess();
+ DeboneProcess();
+ ~DeboneProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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);
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);
-
- // -------------------------------------------------------------------
- /** Counts bones total/removable in a given mesh.
- * @param pMesh The mesh to process.
- */
- bool ConsiderMesh( const aiMesh* pMesh);
-
- /// 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< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
-
- /// Recursively updates the node's mesh list to account for the changed mesh list
- void UpdateNode(aiNode* pNode) const;
-
- // -------------------------------------------------------------------
- // Apply transformation to a mesh
- void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)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);
+
+ // -------------------------------------------------------------------
+ /** Counts bones total/removable in a given mesh.
+ * @param pMesh The mesh to process.
+ */
+ bool ConsiderMesh( const aiMesh* pMesh);
+
+ /// 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< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
+
+ /// Recursively updates the node's mesh list to account for the changed mesh list
+ void UpdateNode(aiNode* pNode) const;
+
+ // -------------------------------------------------------------------
+ // Apply transformation to a mesh
+ void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
public:
- /** Number of bones present in the scene. */
- unsigned int mNumBones;
- unsigned int mNumBonesCanDoWithout;
+ /** Number of bones present in the scene. */
+ unsigned int mNumBones;
+ unsigned int mNumBonesCanDoWithout;
- float mThreshold;
- bool mAllOrNone;
+ float mThreshold;
+ bool mAllOrNone;
- /// Per mesh index: Array of indices of the new submeshes.
- std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
+ /// Per mesh index: Array of indices of the new submeshes.
+ std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/DefaultIOStream.cpp b/src/3rdparty/assimp/code/DefaultIOStream.cpp
index 3ce305971..f1809d894 100644
--- a/src/3rdparty/assimp/code/DefaultIOStream.cpp
+++ b/src/3rdparty/assimp/code/DefaultIOStream.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,90 +25,91 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file DefaultIOStream.cpp
- * @brief Default File I/O implementation for #Importer
+ * @brief Default File I/O implementation for #Importer
*/
-#include "AssimpPCH.h"
+#include <assimp/ai_assert.h>
#include "DefaultIOStream.h"
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
using namespace Assimp;
// ----------------------------------------------------------------------------------
DefaultIOStream::~DefaultIOStream()
{
- if (mFile) {
- ::fclose(mFile);
- }
+ if (mFile) {
+ ::fclose(mFile);
+ }
}
// ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Read(void* pvBuffer,
- size_t pSize,
- size_t pCount)
+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);
+ 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)
+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);
+ ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
+ return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
}
// ----------------------------------------------------------------------------------
aiReturn DefaultIOStream::Seek(size_t pOffset,
- aiOrigin pOrigin)
+ aiOrigin pOrigin)
{
- if (!mFile) {
- return AI_FAILURE;
- }
+ if (!mFile) {
+ return AI_FAILURE;
+ }
- // Just to check whether our enum maps one to one with the CRT constants
- BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR &&
- aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET);
+ // 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);
+ // 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);
+ if (!mFile) {
+ return 0;
+ }
+ return ::ftell(mFile);
}
// ----------------------------------------------------------------------------------
size_t DefaultIOStream::FileSize() const
{
- if (! mFile || mFilename.empty()) {
- return 0;
- }
-
- if (SIZE_MAX == cachedSize) {
+ if (! mFile || mFilename.empty()) {
+ return 0;
+ }
+
+ if (SIZE_MAX == cachedSize) {
// Although fseek/ftell would allow us to reuse the exising file handle here,
// it is generally unsafe because:
@@ -119,28 +120,28 @@ size_t DefaultIOStream::FileSize() const
// 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__
- struct __stat64 fileStat;
- int err = _stat64( mFilename.c_str(), &fileStat );
- if (0 != err)
- return 0;
- cachedSize = (size_t) (fileStat.st_size);
+ struct __stat64 fileStat;
+ int err = _stat64( mFilename.c_str(), &fileStat );
+ if (0 != err)
+ return 0;
+ cachedSize = (size_t) (fileStat.st_size);
#else
- struct stat fileStat;
- int err = stat(mFilename.c_str(), &fileStat );
- if (0 != err)
- return 0;
- cachedSize = (size_t) (fileStat.st_size);
+ struct stat fileStat;
+ int err = stat(mFilename.c_str(), &fileStat );
+ if (0 != err)
+ return 0;
+ cachedSize = (size_t) (fileStat.st_size);
#endif
- }
- return cachedSize;
+ }
+ return cachedSize;
}
// ----------------------------------------------------------------------------------
void DefaultIOStream::Flush()
{
- if (mFile) {
- ::fflush(mFile);
- }
+ if (mFile) {
+ ::fflush(mFile);
+ }
}
// ----------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/DefaultIOStream.h b/src/3rdparty/assimp/code/DefaultIOStream.h
index 247b14d3b..510fc1d05 100644
--- a/src/3rdparty/assimp/code/DefaultIOStream.h
+++ b/src/3rdparty/assimp/code/DefaultIOStream.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,87 +43,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_DEFAULTIOSTREAM_H_INC
#include <stdio.h>
-#include "../include/assimp/IOStream.hpp"
+#include <assimp/IOStream.hpp>
+#include <assimp/importerdesc.h>
+#include "Defines.h"
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
-//! @class DefaultIOStream
-//! @brief Default IO implementation, use standard IO operations
+//! @class DefaultIOStream
+//! @brief Default IO implementation, use standard IO operations
//! @note An instance of this class can exist without a valid file handle
//! attached to it. All calls fail, but the instance can nevertheless be
//! used with no restrictions.
class DefaultIOStream : public IOStream
{
- friend class DefaultIOSystem;
+ friend class DefaultIOSystem;
+#if __ANDROID__
+#if __ANDROID_API__ > 9
+#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+ friend class AndroidJNIIOSystem;
+#endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+#endif // __ANDROID_API__ > 9
+#endif // __ANDROID__
protected:
- DefaultIOStream ();
- DefaultIOStream (FILE* pFile, const std::string &strFilename);
+ DefaultIOStream();
+ DefaultIOStream(FILE* pFile, const std::string &strFilename);
public:
- /** Destructor public to allow simple deletion to close the file. */
- ~DefaultIOStream ();
+ /** Destructor public to allow simple deletion to close the file. */
+ ~DefaultIOStream ();
- // -------------------------------------------------------------------
- // Read from stream
- size_t Read(void* pvBuffer,
- size_t pSize,
- size_t pCount);
+ // -------------------------------------------------------------------
+ /// Read from stream
+ size_t Read(void* pvBuffer,
+ size_t pSize,
+ size_t pCount);
- // -------------------------------------------------------------------
- // Write to stream
- size_t Write(const void* pvBuffer,
- size_t pSize,
- size_t pCount);
+ // -------------------------------------------------------------------
+ /// Write to stream
+ size_t Write(const void* pvBuffer,
+ size_t pSize,
+ size_t pCount);
- // -------------------------------------------------------------------
- // Seek specific position
- aiReturn Seek(size_t pOffset,
- aiOrigin pOrigin);
+ // -------------------------------------------------------------------
+ /// Seek specific position
+ aiReturn Seek(size_t pOffset,
+ aiOrigin pOrigin);
- // -------------------------------------------------------------------
- // Get current seek position
+ // -------------------------------------------------------------------
+ /// Get current seek position
size_t Tell() const;
- // -------------------------------------------------------------------
- // Get size of file
- size_t FileSize() const;
+ // -------------------------------------------------------------------
+ /// Get size of file
+ size_t FileSize() const;
- // -------------------------------------------------------------------
- // Flush file contents
- void Flush();
+ // -------------------------------------------------------------------
+ /// Flush file contents
+ void Flush();
private:
- //! File datastructure, using clib
- FILE* mFile;
- //! Filename
- std::string mFilename;
+ // File datastructure, using clib
+ FILE* mFile;
+ // Filename
+ std::string mFilename;
- //! Cached file size
- mutable size_t cachedSize;
+ // Cached file size
+ mutable size_t cachedSize;
};
// ----------------------------------------------------------------------------------
-inline DefaultIOStream::DefaultIOStream () :
- mFile (NULL),
- mFilename (""),
- cachedSize (SIZE_MAX)
+inline DefaultIOStream::DefaultIOStream () :
+ mFile (NULL),
+ mFilename (""),
+ cachedSize (SIZE_MAX)
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------------
-inline DefaultIOStream::DefaultIOStream (FILE* pFile,
- const std::string &strFilename) :
- mFile(pFile),
- mFilename(strFilename),
- cachedSize (SIZE_MAX)
+inline DefaultIOStream::DefaultIOStream (FILE* pFile,
+ const std::string &strFilename) :
+ mFile(pFile),
+ mFilename(strFilename),
+ cachedSize (SIZE_MAX)
{
- // empty
+ // empty
}
// ----------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/DefaultIOSystem.cpp b/src/3rdparty/assimp/code/DefaultIOSystem.cpp
index 9dbe56d82..8c44c8bd0 100644
--- a/src/3rdparty/assimp/code/DefaultIOSystem.cpp
+++ b/src/3rdparty/assimp/code/DefaultIOSystem.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,26 +25,29 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Default implementation of IOSystem using the standard C file functions */
-#include "AssimpPCH.h"
-
-#include <stdlib.h>
#include "DefaultIOSystem.h"
#include "DefaultIOStream.h"
+#include "StringComparison.h"
+
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/ai_assert.h>
+#include <stdlib.h>
+
#ifdef __unix__
#include <sys/param.h>
@@ -54,50 +57,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
-// Constructor.
+// Constructor.
DefaultIOSystem::DefaultIOSystem()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
-// Destructor.
+// Destructor.
DefaultIOSystem::~DefaultIOSystem()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists( const char* pFile) const
{
- FILE* file = ::fopen( pFile, "rb");
- if( !file)
- return false;
+ FILE* file = ::fopen( pFile, "rb");
+ if( !file)
+ return false;
- ::fclose( file);
- return true;
+ ::fclose( file);
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Open a new file with a given path.
IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
{
- ai_assert(NULL != strFile);
- ai_assert(NULL != strMode);
+ ai_assert(NULL != strFile);
+ ai_assert(NULL != strMode);
- FILE* file = ::fopen( strFile, strMode);
- if( NULL == file)
- return NULL;
+ FILE* file = ::fopen( strFile, strMode);
+ if( NULL == file)
+ return NULL;
- return new DefaultIOStream(file, (std::string) strFile);
+ return new DefaultIOStream(file, (std::string) strFile);
}
// ------------------------------------------------------------------------------------------------
// Closes the given file and releases all resources associated with it.
void DefaultIOSystem::Close( IOStream* pFile)
{
- delete pFile;
+ delete pFile;
}
// ------------------------------------------------------------------------------------------------
@@ -105,9 +108,9 @@ void DefaultIOSystem::Close( IOStream* pFile)
char DefaultIOSystem::getOsSeparator() const
{
#ifndef _WIN32
- return '/';
+ return '/';
#else
- return '\\';
+ return '\\';
#endif
}
@@ -115,53 +118,82 @@ char DefaultIOSystem::getOsSeparator() const
// 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);
+ return !ASSIMP_stricmp(one,second);
}
// maximum path length
-// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
+// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
#ifdef PATH_MAX
-# define PATHLIMIT PATH_MAX
+# define PATHLIMIT PATH_MAX
#else
-# define PATHLIMIT 4096
+# define PATHLIMIT 4096
#endif
// ------------------------------------------------------------------------------------------------
// Convert a relative path into an absolute path
inline void MakeAbsolutePath (const char* in, char* _out)
{
- ai_assert(in && _out);
- char* ret;
-#ifdef _WIN32
- ret = ::_fullpath(_out, in,PATHLIMIT);
+ ai_assert(in && _out);
+ char* ret;
+#if defined( _MSC_VER ) || defined( __MINGW32__ )
+ ret = ::_fullpath( _out, in, PATHLIMIT );
#else
- // use realpath
- ret = realpath(in, _out);
-#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)
- DefaultLogger::get()->warn("Invalid path: "+std::string(in));
- strcpy(_out,in);
- }
+ // use realpath
+ ret = realpath(in, _out);
+#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)
+ DefaultLogger::get()->warn("Invalid path: "+std::string(in));
+ strcpy(_out,in);
+ }
}
// ------------------------------------------------------------------------------------------------
// 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;
-
- char temp1[PATHLIMIT];
- char temp2[PATHLIMIT];
-
- MakeAbsolutePath (one, temp1);
- MakeAbsolutePath (second, temp2);
-
- return !ASSIMP_stricmp(temp1,temp2);
+ // chances are quite good both paths are formatted identically,
+ // so we can hopefully return here already
+ if( !ASSIMP_stricmp(one,second) )
+ return true;
+
+ char temp1[PATHLIMIT];
+ char temp2[PATHLIMIT];
+
+ MakeAbsolutePath (one, temp1);
+ MakeAbsolutePath (second, temp2);
+
+ 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 != ret.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;
+}
+
+// ------------------------------------------------------------------------------------------------
+
#undef PATHLIMIT
diff --git a/src/3rdparty/assimp/code/DefaultIOSystem.h b/src/3rdparty/assimp/code/DefaultIOSystem.h
index af33684b9..49960a847 100644
--- a/src/3rdparty/assimp/code/DefaultIOSystem.h
+++ b/src/3rdparty/assimp/code/DefaultIOSystem.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,40 +42,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_DEFAULTIOSYSTEM_H_INC
#define AI_DEFAULTIOSYSTEM_H_INC
-#include "../include/assimp/IOSystem.hpp"
+#include <assimp/IOSystem.hpp>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Default implementation of IOSystem using the standard C file functions */
class DefaultIOSystem : public IOSystem
{
public:
- /** Constructor. */
+ /** Constructor. */
DefaultIOSystem();
- /** Destructor. */
- ~DefaultIOSystem();
+ /** Destructor. */
+ ~DefaultIOSystem();
- // -------------------------------------------------------------------
- /** Tests for the existence of a file at the given path. */
- bool Exists( const char* pFile) const;
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const;
- // -------------------------------------------------------------------
- /** Returns the directory separator. */
- char getOsSeparator() const;
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const;
- // -------------------------------------------------------------------
- /** Open a new file with a given path. */
- IOStream* Open( const char* pFile, const char* pMode = "rb");
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open( const char* pFile, const char* pMode = "rb");
- // -------------------------------------------------------------------
- /** Closes the given file and releases all resources associated with it. */
- void Close( IOStream* pFile);
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile);
- // -------------------------------------------------------------------
- /** Compare two paths */
- bool ComparePaths (const char* one, const char* second) const;
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths (const char* one, const char* second) const;
+
+ /** @brief get the file name of a full filepath
+ * example: /tmp/archive.tar.gz -> archive.tar.gz
+ */
+ static std::string fileName( const std::string &path );
+
+ /** @brief get the complete base name of a full filepath
+ * example: /tmp/archive.tar.gz -> archive.tar
+ */
+ static std::string completeBaseName( const std::string &path);
+
+ /** @brief get the path of a full filepath
+ * example: /tmp/archive.tar.gz -> /tmp/
+ */
+ static std::string absolutePath( const std::string &path);
};
} //!ns Assimp
diff --git a/src/3rdparty/assimp/code/DefaultLogger.cpp b/src/3rdparty/assimp/code/DefaultLogger.cpp
index 4f5e59461..5364bd8bc 100644
--- a/src/3rdparty/assimp/code/DefaultLogger.cpp
+++ b/src/3rdparty/assimp/code/DefaultLogger.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,22 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of DefaultLogger (and Logger)
*/
-#include "AssimpPCH.h"
#include "DefaultIOSystem.h"
// Default log streams
#include "Win32DebugLogStream.h"
#include "StdOStreamLogStream.h"
#include "FileLogStream.h"
+#include "StringUtils.h"
+#include <assimp/NullLogger.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/ai_assert.h>
+#include <iostream>
+#include <stdio.h>
#ifndef ASSIMP_BUILD_SINGLETHREADED
-# include <boost/thread/thread.hpp>
-# include <boost/thread/mutex.hpp>
+# include <thread>
+# include <mutex>
-boost::mutex loggerMutex;
+std::mutex loggerMutex;
#endif
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
NullLogger DefaultLogger::s_pNullLogger;
@@ -70,351 +75,350 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
// 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;
- }
+ 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*/)
+LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
+ const char* name /*= "AssimpLog.txt"*/,
+ IOSystem* io /*= NULL*/)
{
- switch (streams)
- {
- // This is a platform-specific feature
- case aiDefaultLogStream_DEBUGGER:
+ switch (streams)
+ {
+ // This is a platform-specific feature
+ case aiDefaultLogStream_DEBUGGER:
#ifdef WIN32
- return new Win32DebugLogStream();
+ return new Win32DebugLogStream();
#else
- return NULL;
+ return NULL;
#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) : NULL);
- 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;
+ // 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) : NULL);
+ 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
+// 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*/)
+ LogSeverity severity /*= NORMAL*/,
+ unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
+ IOSystem* io /*= NULL*/)
{
- // enter the mutex here to avoid concurrency problems
+ // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(loggerMutex);
+ std::lock_guard<std::mutex> lock(loggerMutex);
#endif
- if (m_pLogger && !isNullLogger() )
- delete m_pLogger;
+ if (m_pLogger && !isNullLogger() )
+ delete m_pLogger;
- m_pLogger = new DefaultLogger( severity );
+ 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));
+ // 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 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));
+ // Stream the log to CERR?
+ if (defStreams & aiDefaultLogStream_STDERR)
+ m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
- return m_pLogger;
+ // 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) {
- ai_assert(false);
- return;
- }
- return OnDebug(message);
+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) {
- ai_assert(false);
- return;
- }
- return OnInfo(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) {
- ai_assert(false);
- return;
- }
- return OnWarn(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) {
- ai_assert(false);
- return;
- }
- return OnError(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
+ // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(loggerMutex);
+ std::lock_guard<std::mutex> lock(loggerMutex);
#endif
- if (!logger)logger = &s_pNullLogger;
- if (m_pLogger && !isNullLogger() )
- delete m_pLogger;
+ if (!logger)logger = &s_pNullLogger;
+ if (m_pLogger && !isNullLogger() )
+ delete m_pLogger;
- DefaultLogger::m_pLogger = logger;
+ DefaultLogger::m_pLogger = logger;
}
// ----------------------------------------------------------------------------------
bool DefaultLogger::isNullLogger()
{
- return m_pLogger == &s_pNullLogger;
+ return m_pLogger == &s_pNullLogger;
}
// ----------------------------------------------------------------------------------
-// Singleton getter
-Logger *DefaultLogger::get()
-{
- return m_pLogger;
+Logger *DefaultLogger::get() {
+ return m_pLogger;
}
// ----------------------------------------------------------------------------------
-// Kills the only instance
+// Kills the only instance
void DefaultLogger::kill()
{
- // enter the mutex here to avoid concurrency problems
+ // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED
- boost::mutex::scoped_lock lock(loggerMutex);
+ std::lock_guard<std::mutex> lock(loggerMutex);
#endif
- if (m_pLogger == &s_pNullLogger)return;
- delete m_pLogger;
- m_pLogger = &s_pNullLogger;
+ if ( m_pLogger == &s_pNullLogger ) {
+ return;
+ }
+ delete m_pLogger;
+ m_pLogger = &s_pNullLogger;
}
// ----------------------------------------------------------------------------------
-// Debug message
+// Debug message
void DefaultLogger::OnDebug( const char* message )
{
- if ( m_Severity == Logger::NORMAL )
- return;
+ if ( m_Severity == Logger::NORMAL )
+ return;
- char msg[MAX_LOG_MESSAGE_LENGTH + 16];
- ::sprintf(msg,"Debug, T%i: %s", GetThreadID(), message );
+ 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 );
+ WriteToStreams( msg, Logger::Debugging );
}
// ----------------------------------------------------------------------------------
-// Logs an info
+// Logs an info
void DefaultLogger::OnInfo( const char* message )
{
- char msg[MAX_LOG_MESSAGE_LENGTH + 16];
- ::sprintf(msg,"Info, T%i: %s", GetThreadID(), 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 );
+ WriteToStreams( msg , Logger::Info );
}
// ----------------------------------------------------------------------------------
-// Logs a warning
+// Logs a warning
void DefaultLogger::OnWarn( const char* message )
{
- char msg[MAX_LOG_MESSAGE_LENGTH + 16];
- ::sprintf(msg,"Warn, T%i: %s", GetThreadID(), 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 );
+ WriteToStreams( msg, Logger::Warn );
}
// ----------------------------------------------------------------------------------
-// Logs an error
+// Logs an error
void DefaultLogger::OnError( const char* message )
{
- char msg[MAX_LOG_MESSAGE_LENGTH + 16];
- ::sprintf(msg,"Error, T%i: %s", GetThreadID(), 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 );
+ WriteToStreams( msg, Logger::Err );
}
// ----------------------------------------------------------------------------------
-// Will attach a new stream
+// Will attach a new stream
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
{
- if (!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;
+ if (!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;
}
// ----------------------------------------------------------------------------------
-// Detatch a stream
+// Detach a stream
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
{
- if (!pStream)
- return false;
-
- if (0 == severity) {
- severity = SeverityAll;
- }
-
- 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 = NULL;
- delete *it;
- m_StreamArray.erase( it );
- break;
- }
- return true;
- }
- }
- return false;
+ if (!pStream)
+ return false;
+
+ if (0 == severity) {
+ severity = SeverityAll;
+ }
+
+ 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 = NULL;
+ delete *it;
+ m_StreamArray.erase( it );
+ break;
+ }
+ return true;
+ }
+ }
+ return false;
}
// ----------------------------------------------------------------------------------
-// Constructor
-DefaultLogger::DefaultLogger(LogSeverity severity)
-
- : Logger ( severity )
- , noRepeatMsg (false)
- , lastLen( 0 )
+// Constructor
+DefaultLogger::DefaultLogger(LogSeverity severity)
+ : Logger ( severity )
+ , noRepeatMsg (false)
+ , lastLen( 0 )
{
- lastMsg[0] = '\0';
+ lastMsg[0] = '\0';
}
// ----------------------------------------------------------------------------------
-// Destructor
+// 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;
- }
+ 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 )
+// Writes message to stream
+void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev )
{
- ai_assert(NULL != 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);
- }
+ ai_assert(NULL != 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.
+// Returns thread id, if not supported only a zero will be returned.
unsigned int DefaultLogger::GetThreadID()
{
- // fixme: we can get this value via boost::threads
+ // 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();
+ return (unsigned int)::GetCurrentThreadId();
#else
- return 0; // not supported
+ return 0; // not supported
#endif
}
diff --git a/src/3rdparty/assimp/code/DefaultProgressHandler.h b/src/3rdparty/assimp/code/DefaultProgressHandler.h
index 6fe8e7b16..b729e4bfa 100644
--- a/src/3rdparty/assimp/code/DefaultProgressHandler.h
+++ b/src/3rdparty/assimp/code/DefaultProgressHandler.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,21 +44,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
#define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
-#include "../include/assimp/ProgressHandler.hpp"
-namespace Assimp {
+#include <assimp/ProgressHandler.hpp>
+
+namespace Assimp {
// ------------------------------------------------------------------------------------
/** @brief Internal default implementation of the #ProgressHandler interface. */
-class DefaultProgressHandler
- : public ProgressHandler {
+class DefaultProgressHandler
+ : public ProgressHandler {
+
-
- virtual bool Update(float /*percentage*/) {
- return false;
- }
+ virtual bool Update(float /*percentage*/) {
+ return false;
+ }
-}; // !class DefaultProgressHandler
+}; // !class DefaultProgressHandler
} // Namespace Assimp
#endif
diff --git a/src/3rdparty/assimp/code/Defines.h b/src/3rdparty/assimp/code/Defines.h
new file mode 100644
index 000000000..15e1d83c2
--- /dev/null
+++ b/src/3rdparty/assimp/code/Defines.h
@@ -0,0 +1,49 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+// We need those constants, workaround for any platforms where nobody defined them yet
+#if (!defined SIZE_MAX)
+# define SIZE_MAX (~((size_t)0))
+#endif
+
+#if (!defined UINT_MAX)
+# define UINT_MAX (~((unsigned int)0))
+#endif
+
diff --git a/src/3rdparty/assimp/code/Exceptional.h b/src/3rdparty/assimp/code/Exceptional.h
index 4e20d2931..e04da757c 100644
--- a/src/3rdparty/assimp/code/Exceptional.h
+++ b/src/3rdparty/assimp/code/Exceptional.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,25 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_EXCEPTIONAL_H
#include <stdexcept>
+#include "DefaultIOStream.h"
using std::runtime_error;
#ifdef _MSC_VER
-# pragma warning(disable : 4275)
+# pragma warning(disable : 4275)
#endif
// ---------------------------------------------------------------------------
-/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
+/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
* unrecoverable error occurs while importing. Loading APIs return
* NULL instead of a valid aiScene then. */
class DeadlyImportError
- : public runtime_error
+ : public runtime_error
{
public:
- /** Constructor with arguments */
- explicit DeadlyImportError( const std::string& pErrorText)
- : runtime_error(pErrorText)
- {
- }
+ /** Constructor with arguments */
+ explicit DeadlyImportError( const std::string& pErrorText)
+ : runtime_error(pErrorText)
+ {
+ }
private:
};
@@ -68,57 +69,57 @@ private:
typedef DeadlyImportError DeadlyExportError;
#ifdef _MSC_VER
-# pragma warning(default : 4275)
+# pragma warning(default : 4275)
#endif
// ---------------------------------------------------------------------------
template <typename T>
-struct ExceptionSwallower {
- T operator ()() const {
- return T();
- }
+struct ExceptionSwallower {
+ T operator ()() const {
+ return T();
+ }
};
// ---------------------------------------------------------------------------
template <typename T>
-struct ExceptionSwallower<T*> {
- T* operator ()() const {
- return NULL;
- }
+struct ExceptionSwallower<T*> {
+ T* operator ()() const {
+ return NULL;
+ }
};
// ---------------------------------------------------------------------------
template <>
-struct ExceptionSwallower<aiReturn> {
- aiReturn operator ()() const {
- try {
- throw;
- }
- catch (std::bad_alloc&) {
- return aiReturn_OUTOFMEMORY;
- }
- catch (...) {
- return aiReturn_FAILURE;
- }
- }
+struct ExceptionSwallower<aiReturn> {
+ aiReturn operator ()() const {
+ try {
+ throw;
+ }
+ catch (std::bad_alloc&) {
+ return aiReturn_OUTOFMEMORY;
+ }
+ catch (...) {
+ return aiReturn_FAILURE;
+ }
+ }
};
// ---------------------------------------------------------------------------
template <>
-struct ExceptionSwallower<void> {
- void operator ()() const {
- return;
- }
+struct ExceptionSwallower<void> {
+ void operator ()() const {
+ return;
+ }
};
#define ASSIMP_BEGIN_EXCEPTION_REGION()\
{\
- try {
+ try {
#define ASSIMP_END_EXCEPTION_REGION(type)\
- } catch(...) {\
- return ExceptionSwallower<type>()();\
- }\
+ } catch(...) {\
+ return ExceptionSwallower<type>()();\
+ }\
}
#endif // INCLUDED_EXCEPTIONAL_H
diff --git a/src/3rdparty/assimp/code/Exporter.cpp b/src/3rdparty/assimp/code/Exporter.cpp
index 9dba5c47c..af2267a62 100644
--- a/src/3rdparty/assimp/code/Exporter.cpp
+++ b/src/3rdparty/assimp/code/Exporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -50,19 +50,25 @@ description strings.
Here we implement only the C++ interface (Assimp::Exporter).
*/
-#include "AssimpPCH.h"
-
#ifndef ASSIMP_BUILD_NO_EXPORT
#include "DefaultIOSystem.h"
-#include "BlobIOSystem.h"
-#include "SceneCombiner.h"
-#include "BaseProcess.h"
+#include "BlobIOSystem.h"
+#include "SceneCombiner.h"
+#include "BaseProcess.h"
#include "Importer.h" // need this for GetPostProcessingStepInstanceList()
#include "JoinVerticesProcess.h"
#include "MakeVerboseFormat.h"
#include "ConvertToLHProcess.h"
+#include "Exceptional.h"
+#include "ScenePrivate.h"
+#include <memory>
+#include <assimp/Exporter.hpp>
+#include <assimp/mesh.h>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <memory>
namespace Assimp {
@@ -71,44 +77,80 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
// ------------------------------------------------------------------------------------------------
// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
-void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
-void ExportSceneObj(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
-void ExportScenePly(const char*,IOSystem*, const aiScene*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
+// 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 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 ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
// ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build
-Exporter::ExportFormatEntry gExporters[] =
+Exporter::ExportFormatEntry gExporters[] =
{
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
- Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
+ Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_XFILE_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( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
+ 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
- ),
+ 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( "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
-// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
-//#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( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
+ aiProcess_JoinIdenticalVertices /*| aiProcess_SortByPType*/),
+ Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
+ aiProcess_JoinIdenticalVertices /*| aiProcess_SortByPType*/),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+ Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+ Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
+#endif
};
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
@@ -117,42 +159,42 @@ Exporter::ExportFormatEntry gExporters[] =
class ExporterPimpl {
public:
- ExporterPimpl()
- : blob()
- , mIOSystem(new Assimp::DefaultIOSystem())
- , mIsDefaultIOHandler(true)
- {
- GetPostProcessingStepInstanceList(mPostProcessingSteps);
+ ExporterPimpl()
+ : blob()
+ , mIOSystem(new Assimp::DefaultIOSystem())
+ , mIsDefaultIOHandler(true)
+ {
+ GetPostProcessingStepInstanceList(mPostProcessingSteps);
- // grab all builtin exporters
- mExporters.resize(ASSIMP_NUM_EXPORTERS);
- std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
- }
+ // grab all builtin exporters
+ mExporters.resize(ASSIMP_NUM_EXPORTERS);
+ std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
+ }
- ~ExporterPimpl()
- {
- delete blob;
+ ~ExporterPimpl()
+ {
+ delete blob;
- // Delete all post-processing plug-ins
- for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
- delete mPostProcessingSteps[a];
- }
- }
+ // Delete all post-processing plug-ins
+ for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
+ delete mPostProcessingSteps[a];
+ }
+ }
public:
-
- aiExportDataBlob* blob;
- boost::shared_ptr< Assimp::IOSystem > mIOSystem;
- bool mIsDefaultIOHandler;
- /** Post processing steps we can apply at the imported data. */
- std::vector< BaseProcess* > mPostProcessingSteps;
+ aiExportDataBlob* blob;
+ std::shared_ptr< Assimp::IOSystem > mIOSystem;
+ bool mIsDefaultIOHandler;
+
+ /** Post processing steps we can apply at the imported data. */
+ std::vector< BaseProcess* > mPostProcessingSteps;
- /** Last fatal export error */
- std::string mError;
+ /** Last fatal export error */
+ std::string mError;
- /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
- std::vector<Exporter::ExportFormatEntry> mExporters;
+ /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
+ std::vector<Exporter::ExportFormatEntry> mExporters;
};
@@ -166,7 +208,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
-Exporter :: Exporter()
+Exporter :: Exporter()
: pimpl(new ExporterPimpl())
{
}
@@ -175,294 +217,408 @@ Exporter :: Exporter()
// ------------------------------------------------------------------------------------------------
Exporter :: ~Exporter()
{
- FreeBlob();
+ FreeBlob();
- delete pimpl;
+ delete pimpl;
}
// ------------------------------------------------------------------------------------------------
void Exporter :: SetIOHandler( IOSystem* pIOHandler)
{
- pimpl->mIsDefaultIOHandler = !pIOHandler;
- pimpl->mIOSystem.reset(pIOHandler);
+ pimpl->mIsDefaultIOHandler = !pIOHandler;
+ pimpl->mIOSystem.reset(pIOHandler);
}
// ------------------------------------------------------------------------------------------------
IOSystem* Exporter :: GetIOHandler() const
{
- return pimpl->mIOSystem.get();
+ return pimpl->mIOSystem.get();
}
// ------------------------------------------------------------------------------------------------
bool Exporter :: IsDefaultIOHandler() const
{
- return pimpl->mIsDefaultIOHandler;
+ return pimpl->mIsDefaultIOHandler;
}
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int )
+const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
{
- if (pimpl->blob) {
- delete pimpl->blob;
- pimpl->blob = NULL;
- }
+ if (pimpl->blob) {
+ delete pimpl->blob;
+ pimpl->blob = NULL;
+ }
- boost::shared_ptr<IOSystem> old = pimpl->mIOSystem;
+ std::shared_ptr<IOSystem> old = pimpl->mIOSystem;
- BlobIOSystem* blobio = new BlobIOSystem();
- pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio );
+ BlobIOSystem* blobio = new BlobIOSystem();
+ pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
- if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
- pimpl->mIOSystem = old;
- return NULL;
- }
+ if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
+ pimpl->mIOSystem = old;
+ return NULL;
+ }
- pimpl->blob = blobio->GetBlobChain();
- pimpl->mIOSystem = old;
+ pimpl->blob = blobio->GetBlobChain();
+ pimpl->mIOSystem = old;
- return pimpl->blob;
+ return pimpl->blob;
}
// ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiMesh* mesh)
+bool IsVerboseFormat(const aiMesh* mesh)
{
- // avoid slow vector<bool> specialization
- std::vector<unsigned int> seen(mesh->mNumVertices,0);
- for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
- const aiFace& f = mesh->mFaces[i];
- for(unsigned int j = 0; j < f.mNumIndices; ++j) {
- if(++seen[f.mIndices[j]] == 2) {
- // found a duplicate index
- return false;
- }
- }
- }
- return true;
+ // avoid slow vector<bool> specialization
+ std::vector<unsigned int> seen(mesh->mNumVertices,0);
+ for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+ const aiFace& f = mesh->mFaces[i];
+ for(unsigned int j = 0; j < f.mNumIndices; ++j) {
+ if(++seen[f.mIndices[j]] == 2) {
+ // found a duplicate index
+ return false;
+ }
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiScene* pScene)
+bool IsVerboseFormat(const aiScene* pScene)
{
- for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- if(!IsVerboseFormat(pScene->mMeshes[i])) {
- return false;
- }
- }
- return true;
+ for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ if(!IsVerboseFormat(pScene->mMeshes[i])) {
+ return false;
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
-{
- 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) || IsVerboseFormat(pScene);
-
- 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;
- SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
-
- std::auto_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 postprocessing 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 postprocessing 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)) {
- DefaultLogger::get()->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;
- }
- }
- }
-
- 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());
- }
- }
-
- // 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)) {
-
- p->Execute(scenecopy.get());
- }
- }
- ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
- ai_assert(privOut);
-
- privOut->mPPStepsApplied |= pp;
- }
-
- if(must_join_again) {
- JoinVerticesProcess proc;
- proc.Execute(scenecopy.get());
- }
-
- exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
- }
- 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;
+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) || IsVerboseFormat(pScene);
+
+ 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;
+ SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+
+ 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 postprocessing 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 postprocessing 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)) {
+ DefaultLogger::get()->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;
+ }
+ }
+ }
+
+ 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());
+ }
+ }
+
+ // 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)) {
+
+ p->Execute(scenecopy.get());
+ }
+ }
+ ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
+ ai_assert(privOut);
+
+ privOut->mPPStepsApplied |= pp;
+ }
+
+ if(must_join_again) {
+ JoinVerticesProcess proc;
+ proc.Execute(scenecopy.get());
+ }
+
+ ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
+ exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
+ }
+ 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();
+ return pimpl->mError.c_str();
}
// ------------------------------------------------------------------------------------------------
void Exporter :: FreeBlob( )
{
- delete pimpl->blob;
- pimpl->blob = NULL;
+ delete pimpl->blob;
+ pimpl->blob = NULL;
- pimpl->mError = "";
+ pimpl->mError = "";
}
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetBlob() const
+const aiExportDataBlob* Exporter :: GetBlob() const
{
- return pimpl->blob;
+ return pimpl->blob;
}
// ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
+const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
{
- const aiExportDataBlob* tmp = pimpl->blob;
- pimpl->blob = NULL;
- return tmp;
+ const aiExportDataBlob* tmp = pimpl->blob;
+ pimpl->blob = NULL;
+ return tmp;
}
// ------------------------------------------------------------------------------------------------
-size_t Exporter :: GetExportFormatCount() const
+size_t Exporter :: GetExportFormatCount() const
{
- return pimpl->mExporters.size();
+ return pimpl->mExporters.size();
}
// ------------------------------------------------------------------------------------------------
-const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
+const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
{
- if (pIndex >= GetExportFormatCount()) {
- return NULL;
- }
+ if (pIndex >= GetExportFormatCount()) {
+ return NULL;
+ }
+
+ // Return from static storage if the requested index is built-in.
+ if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) {
+ return &gExporters[pIndex].mDescription;
+ }
- return &pimpl->mExporters[pIndex].mDescription;
+ return &pimpl->mExporters[pIndex].mDescription;
}
// ------------------------------------------------------------------------------------------------
aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
{
- BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
- if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
- return aiReturn_FAILURE;
- }
- }
-
- pimpl->mExporters.push_back(desc);
- return aiReturn_SUCCESS;
+ 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;
- }
- }
+ 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() {}
+
+ExportProperties::ExportProperties(const ExportProperties &other)
+ : mIntProperties(other.mIntProperties),
+ mFloatProperties(other.mFloatProperties),
+ mStringProperties(other.mStringProperties),
+ mMatrixProperties(other.mMatrixProperties)
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// 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, float iValue)
+{
+ return SetGenericProperty<float>(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
+float ExportProperties :: GetPropertyFloat(const char* szName,
+ float iErrorReturn /*= 10e10*/) const
+{
+ return GetGenericProperty<float>(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<float>(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
diff --git a/src/3rdparty/assimp/code/FBXAnimation.cpp b/src/3rdparty/assimp/code/FBXAnimation.cpp
index ccf1d82f4..0758d4db7 100644
--- a/src/3rdparty/assimp/code/FBXAnimation.cpp
+++ b/src/3rdparty/assimp/code/FBXAnimation.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,26 +23,25 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file FBXAnimation.cpp
- * @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
- * Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
+ * @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
+ * Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -56,37 +55,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
+ using namespace Util;
// ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
: Object(id, element, name)
{
- const Scope& sc = GetRequiredScope(element);
- 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);
- }
+ 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);
+ }
}
@@ -98,62 +97,62 @@ AnimationCurve::~AnimationCurve()
// ------------------------------------------------------------------------------------------------
-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*/)
+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"};
- const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
-
- BOOST_FOREACH(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);
+ const Scope& sc = GetRequiredScope(element);
+
+ // find target node
+ const char* whitelist[] = {"Model","NodeAttribute"};
+ const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
+
+ 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);
}
@@ -167,34 +166,34 @@ AnimationCurveNode::~AnimationCurveNode()
// ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const
{
- if(curves.empty()) {
- // resolve attached animation curves
- const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
-
- BOOST_FOREACH(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;
+ 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;
}
@@ -203,10 +202,10 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
: Object(id, element, name)
, doc(doc)
{
- const Scope& sc = GetRequiredScope(element);
+ 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);
+ // note: the props table here bears little importance and is usually absent
+ props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
}
@@ -218,86 +217,86 @@ AnimationLayer::~AnimationLayer()
// ------------------------------------------------------------------------------------------------
-AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
- size_t whitelist_size /*= 0*/) const
+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());
-
- BOOST_FOREACH(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
+ 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());
-
- BOOST_FOREACH(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);
- }
+ 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);
+ }
}
diff --git a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
index b5f151c15..551b174ed 100644
--- a/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
+++ b/src/3rdparty/assimp/code/FBXBinaryTokenizer.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,12 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* we emit tokens so the parser needs almost no special handling
* for binary files.
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include "FBXTokenizer.h"
#include "FBXUtil.h"
+#include <assimp/defs.h>
+#include <stdint.h>
+#include "Exceptional.h"
+#include "ByteSwapper.h"
namespace Assimp {
namespace FBX {
@@ -55,21 +58,22 @@ namespace FBX {
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
- : sbegin(sbegin)
- , send(send)
- , type(type)
- , line(offset)
- , column(BINARY_MARKER)
-#ifdef DEBUG
- , contents(sbegin, static_cast<size_t>(send-sbegin))
-#endif
+ :
+ #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);
+ ai_assert(sbegin);
+ ai_assert(send);
- // binary tokens may have zero length because they are sometimes dummies
- // inserted by TokenizeBinary()
- ai_assert(send >= sbegin);
+ // binary tokens may have zero length because they are sometimes dummies
+ // inserted by TokenizeBinary()
+ ai_assert(send >= sbegin);
}
@@ -77,87 +81,88 @@ namespace {
// ------------------------------------------------------------------------------------------------
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
-void TokenizeError(const std::string& message, unsigned int offset)
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
{
- throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
+ throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
}
// ------------------------------------------------------------------------------------------------
uint32_t Offset(const char* begin, const char* cursor)
{
- ai_assert(begin <= cursor);
- return static_cast<unsigned int>(cursor - begin);
+ ai_assert(begin <= cursor);
+ return static_cast<unsigned int>(cursor - begin);
}
// ------------------------------------------------------------------------------------------------
void TokenizeError(const std::string& message, const char* begin, const char* cursor)
{
- TokenizeError(message, Offset(begin, cursor));
+ TokenizeError(message, Offset(begin, cursor));
}
// ------------------------------------------------------------------------------------------------
uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
{
- if(Offset(cursor, end) < 4) {
- TokenizeError("cannot ReadWord, out of bounds",input, cursor);
- }
+ if(Offset(cursor, end) < 4) {
+ TokenizeError("cannot ReadWord, out of bounds",input, cursor);
+ }
- uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
- AI_SWAP4(word);
+ uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
+ AI_SWAP4(word);
- cursor += 4;
+ cursor += 4;
- return word;
+ return word;
}
// ------------------------------------------------------------------------------------------------
uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
{
- if(Offset(cursor, end) < 1) {
- TokenizeError("cannot ReadByte, out of bounds",input, cursor);
- }
+ if(Offset(cursor, end) < 1) {
+ TokenizeError("cannot ReadByte, out of bounds",input, cursor);
+ }
- uint8_t word = *reinterpret_cast<const uint8_t*>(cursor);
- ++cursor;
+ uint8_t word = *reinterpret_cast<const uint8_t*>(cursor);
+ ++cursor;
- return word;
+ 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)
+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 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);
+ 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);
- }
+ if (Offset(cursor, end) < length) {
+ TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
+ }
- sbegin_out = cursor;
- cursor += length;
+ sbegin_out = cursor;
+ cursor += length;
- send_out = cursor;
+ 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);
- }
- }
- }
+ 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;
+ return length;
}
@@ -165,203 +170,203 @@ unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const ch
// ------------------------------------------------------------------------------------------------
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 thru
-
- // 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': {
-
- 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;
-
- default:
- ai_assert(false);
- };
+ 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': {
+
+ 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;
+
+ 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;
+ 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)
{
- // the first word contains the offset at which this block ends
- const uint32_t end_offset = 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 uint32_t prop_count = ReadWord(input, cursor, end);
-
- // the third data word contains the length of the property list
- const uint32_t prop_length = 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.
+ // the first word contains the offset at which this block ends
+ const uint32_t end_offset = 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 uint32_t prop_count = ReadWord(input, cursor, end);
+
+ // the third data word contains the length of the property list
+ const uint32_t prop_length = 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.
#define BLOCK_SENTINEL_LENGTH 13
- if (Offset(input, cursor) < end_offset) {
+ if (Offset(input, cursor) < end_offset) {
- if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
- TokenizeError("insufficient padding bytes at block end",input, cursor);
- }
+ if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_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) ));
+ 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 - BLOCK_SENTINEL_LENGTH) {
- ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
- }
- output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
+ // XXX this is vulnerable to stack overflowing ..
+ while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
+ ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
+ }
+ output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
- for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
- if(cursor[i] != '\0') {
- TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
- }
- }
- cursor += BLOCK_SENTINEL_LENGTH;
- }
+ for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
+ if(cursor[i] != '\0') {
+ TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
+ }
+ }
+ cursor += BLOCK_SENTINEL_LENGTH;
+ }
- if (Offset(input, cursor) != end_offset) {
- TokenizeError("scope length not reached, something is wrong",input, cursor);
- }
+ if (Offset(input, cursor) != end_offset) {
+ TokenizeError("scope length not reached, something is wrong",input, cursor);
+ }
- return true;
+ return true;
}
@@ -370,29 +375,29 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// ------------------------------------------------------------------------------------------------
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
{
- ai_assert(input);
+ ai_assert(input);
- if(length < 0x1b) {
- TokenizeError("file is too short",0);
- }
+ if(length < 0x1b) {
+ TokenizeError("file is too short",0);
+ }
- if (strncmp(input,"Kaydara FBX Binary",18)) {
- TokenizeError("magic bytes not found",0);
- }
+ if (strncmp(input,"Kaydara FBX Binary",18)) {
+ TokenizeError("magic bytes not found",0);
+ }
- //uint32_t offset = 0x1b;
+ //uint32_t offset = 0x1b;
- const char* cursor = input + 0x1b;
+ const char* cursor = input + 0x1b;
- while (cursor < input + length) {
- if(!ReadScope(output_tokens, input, cursor, input + length)) {
- break;
- }
- }
+ while (cursor < input + length) {
+ if(!ReadScope(output_tokens, input, cursor, input + length)) {
+ break;
+ }
+ }
}
} // !FBX
} // !Assimp
-#endif \ No newline at end of file
+#endif
diff --git a/src/3rdparty/assimp/code/FBXCompileConfig.h b/src/3rdparty/assimp/code/FBXCompileConfig.h
index ea7efaddf..901f5b330 100644
--- a/src/3rdparty/assimp/code/FBXCompileConfig.h
+++ b/src/3rdparty/assimp/code/FBXCompileConfig.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,21 +46,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#if _MSC_VER > 1500 || (defined __GNUC___)
-# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-# else
-# define fbx_unordered_map map
-# define fbx_unordered_multimap multimap
+# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
+# else
+# define fbx_unordered_map map
+# define fbx_unordered_multimap multimap
#endif
#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-# include <unordered_map>
-# if _MSC_VER > 1600
-# define fbx_unordered_map unordered_map
-# define fbx_unordered_multimap unordered_multimap
-# else
-# define fbx_unordered_map tr1::unordered_map
-# define fbx_unordered_multimap tr1::unordered_multimap
-# endif
+# include <unordered_map>
+# if _MSC_VER > 1600
+# define fbx_unordered_map unordered_map
+# define fbx_unordered_multimap unordered_multimap
+# else
+# define fbx_unordered_map tr1::unordered_map
+# define fbx_unordered_multimap tr1::unordered_multimap
+# endif
#endif
#endif
diff --git a/src/3rdparty/assimp/code/FBXConverter.cpp b/src/3rdparty/assimp/code/FBXConverter.cpp
index c6ef8c908..692cda836 100644
--- a/src/3rdparty/assimp/code/FBXConverter.cpp
+++ b/src/3rdparty/assimp/code/FBXConverter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -24,15 +24,15 @@ following conditions are met:
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
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,2939 +41,3269 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXConverter.cpp
* @brief Implementation of the FBX DOM -> aiScene converter
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-#include <iterator>
-#include <sstream>
-#include <boost/tuple/tuple.hpp>
-
-#include "FBXParser.h"
#include "FBXConverter.h"
+#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
#include "FBXUtil.h"
#include "FBXProperties.h"
#include "FBXImporter.h"
+#include "StringComparison.h"
+
+#include <assimp/scene.h>
+#include <tuple>
+#include <memory>
+
+#include <iterator>
+#include <sstream>
+#include <vector>
namespace Assimp {
namespace FBX {
- using namespace Util;
+using namespace Util;
#define MAGIC_NODE_TAG "_$AssimpFbx$"
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
- // XXX vc9's debugger won't step into anonymous namespaces
+ // XXX vc9's debugger won't step into anonymous namespaces
//namespace {
/** Dummy class to encapsulate the conversion process */
class Converter
{
public:
-
- /** the different parts that make up the final local transformation of a fbx node */
- enum TransformationComp
- {
- TransformationComp_Translation = 0,
- 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
- };
+ /**
+ * The different parts that make up the final local transformation of a fbx-node
+ */
+ enum TransformationComp
+ {
+ TransformationComp_Translation = 0,
+ 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:
+ Converter( aiScene* out, const Document& doc );
+ ~Converter();
+
+private:
+ // ------------------------------------------------------------------------------------------------
+ // find scene root and trigger recursive scene conversion
+ void ConvertRootNode();
+
+ // ------------------------------------------------------------------------------------------------
+ // collect and assign child nodes
+ void ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4() );
+
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertLights( const Model& model );
+
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCameras( const Model& model );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertLight( const Model& model, const Light& light );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCamera( const Model& model, const Camera& cam );
+
+ // ------------------------------------------------------------------------------------------------
+ // 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 );
+
+ // ------------------------------------------------------------------------------------------------
+ // note: this returns the REAL fbx property names
+ const char* NameTransformationCompProperty( TransformationComp comp );
+
+ // ------------------------------------------------------------------------------------------------
+ aiVector3D TransformationCompDefaultValue( TransformationComp comp );
- Converter(aiScene* out, const Document& doc)
- : defaultMaterialIndex()
- , 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();
- ConvertRootNode();
-
- if(doc.Settings().readAllMaterials) {
- // unfortunately this means we have to evaluate all objects
- BOOST_FOREACH(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);
- }
- }
- }
- }
-
- 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;
- }
- }
-
-
- ~Converter()
- {
- 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>());
- }
+ // ------------------------------------------------------------------------------------------------
+ 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
+ */
+ void GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes );
+
+ // ------------------------------------------------------------------------------------------------
+ void SetupNodeMetadata( const Model& model, aiNode& nd );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform );
+
+ // ------------------------------------------------------------------------------------------------
+ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
+ std::vector<unsigned int> ConvertMesh( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform );
+
+ // ------------------------------------------------------------------------------------------------
+ aiMesh* SetupEmptyMesh( const MeshGeometry& mesh );
+
+ // ------------------------------------------------------------------------------------------------
+ unsigned int ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform );
+
+ // ------------------------------------------------------------------------------------------------
+ std::vector<unsigned int> ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform );
+
+ // ------------------------------------------------------------------------------------------------
+ unsigned int ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
+ MatIndexArray::value_type index,
+ const aiMatrix4x4& node_global_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& node_global_transform = aiMatrix4x4(),
+ unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+ std::vector<unsigned int>* outputVertStartIndices = NULL );
+
+ // ------------------------------------------------------------------------------------------------
+ void ConvertCluster( std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
+ std::vector<size_t>& out_indices,
+ std::vector<size_t>& index_out_indices,
+ std::vector<size_t>& count_out_indices,
+ const aiMatrix4x4& node_global_transform );
+
+ // ------------------------------------------------------------------------------------------------
+ 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 );
+
+ // ------------------------------------------------------------------------------------------------
+ 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 );
+
+ // ------------------------------------------------------------------------------------------------
+ void SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props );
+
+ // ------------------------------------------------------------------------------------------------
+ // 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();
+
+ // ------------------------------------------------------------------------------------------------
+ // rename a node already partially converted. fixed_name is a string previously returned by
+ // FixNodeName, new_name specifies the string FixNodeName should return on all further invocations
+ // which would previously have returned the old value.
+ //
+ // this also updates names in node animations, cameras and light sources and is thus slow.
+ //
+ // NOTE: the caller is responsible for ensuring that the new name is unique and does
+ // not collide with any other identifiers. The best way to ensure this is to only
+ // append to the old name, which is guaranteed to match these requirements.
+ void RenameNode( const std::string& fixed_name, const std::string& new_name );
+
+ // ------------------------------------------------------------------------------------------------
+ // 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 );
+
+ 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 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 );
+
+ // ------------------------------------------------------------------------------------------------
+ // copy generated meshes, animations, lights, cameras and textures to the output scene
+ void TransferDataToScene();
private:
- // ------------------------------------------------------------------------------------------------
- // find scene root and trigger recursive scene conversion
- void ConvertRootNode()
- {
- out->mRootNode = new aiNode();
- out->mRootNode->mName.Set("RootNode");
+ // 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;
+
+ typedef std::map<const Material*, unsigned int> MaterialMap;
+ MaterialMap materials_converted;
+
+ typedef std::map<const Video*, unsigned int> VideoMap;
+ VideoMap textures_converted;
+
+ typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
+ MeshMap meshes_converted;
+
+ // fixed node name -> which trafo chain components have animations?
+ typedef std::map<std::string, unsigned int> NodeAnimBitMap;
+ NodeAnimBitMap node_anim_chain_bits;
+
+ // name -> has had its prefix_stripped?
+ typedef std::map<std::string, bool> NodeNameMap;
+ NodeNameMap node_names;
+
+ typedef std::map<std::string, std::string> NameNameMap;
+ NameNameMap renamed_nodes;
+
+ double anim_fps;
+
+ aiScene* const out;
+ const FBX::Document& doc;
+};
+
+Converter::Converter( aiScene* out, const Document& doc )
+ : defaultMaterialIndex()
+ , 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();
+ 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 );
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+}
+
+
+Converter::~Converter()
+{
+ 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 Converter::ConvertRootNode()
+{
+ out->mRootNode = new aiNode();
+ out->mRootNode->mName.Set( "RootNode" );
+
+ // root has ID 0
+ ConvertNodes( 0L, *out->mRootNode );
+}
+
+
+void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform )
+{
+ const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" );
+
+ std::vector<aiNode*> nodes;
+ nodes.reserve( conns.size() );
+
+ std::vector<aiNode*> nodes_chain;
+
+ try {
+ for( const Connection* con : conns ) {
+
+ // ignore object-property links
+ if ( con->PropertyName().length() ) {
+ continue;
+ }
+
+ const Object* const object = con->SourceObject();
+ if ( !object ) {
+ FBXImporter::LogWarn( "failed to convert source object for Model link" );
+ continue;
+ }
- // root has ID 0
- ConvertNodes(0L, *out->mRootNode);
- }
+ const Model* const model = dynamic_cast<const Model*>( object );
+ if ( model ) {
+ nodes_chain.clear();
- // ------------------------------------------------------------------------------------------------
- // collect and assign child nodes
- void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4())
- {
- const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
+ aiMatrix4x4 new_abs_transform = parent_transform;
- std::vector<aiNode*> nodes;
- nodes.reserve(conns.size());
-
- std::vector<aiNode*> nodes_chain;
-
- try {
- BOOST_FOREACH(const Connection* con, conns) {
+ // 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.
+ GenerateTransformationNodeChain( *model, nodes_chain );
- // ignore object-property links
- if(con->PropertyName().length()) {
- continue;
- }
-
- const Object* const object = con->SourceObject();
- if(!object) {
- FBXImporter::LogWarn("failed to convert source object for Model link");
- continue;
- }
-
- const Model* const model = dynamic_cast<const Model*>(object);
-
- if(model) {
- nodes_chain.clear();
-
- aiMatrix4x4 new_abs_transform = parent_transform;
-
- // 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.
- GenerateTransformationNodeChain(*model,nodes_chain);
-
- ai_assert(nodes_chain.size());
-
- const std::string& original_name = FixNodeName(model->Name());
-
- // check if any of the nodes in the chain has the name the fbx node
- // is supposed to have. If there is none, add another node to
- // preserve the name - people might have scripts etc. that rely
- // on specific node names.
- aiNode* name_carrier = NULL;
- BOOST_FOREACH(aiNode* prenode, nodes_chain) {
- if ( !strcmp(prenode->mName.C_Str(), original_name.c_str()) ) {
- name_carrier = prenode;
- break;
- }
- }
-
- if(!name_carrier) {
- nodes_chain.push_back(new aiNode(original_name));
- name_carrier = nodes_chain.back();
- }
-
- //setup metadata on newest node
- SetupNodeMetadata(*model, *nodes_chain.back());
-
- // link all nodes in a row
- aiNode* last_parent = &parent;
- BOOST_FOREACH(aiNode* prenode, nodes_chain) {
- ai_assert(prenode);
-
- if(last_parent != &parent) {
- last_parent->mNumChildren = 1;
- last_parent->mChildren = new aiNode*[1];
- last_parent->mChildren[0] = prenode;
- }
-
- prenode->mParent = last_parent;
- last_parent = prenode;
-
- new_abs_transform *= prenode->mTransformation;
- }
-
- // attach geometry
- ConvertModel(*model, *nodes_chain.back(), new_abs_transform);
-
- // attach sub-nodes
- ConvertNodes(model->ID(), *nodes_chain.back(), new_abs_transform);
-
- if(doc.Settings().readLights) {
- ConvertLights(*model);
- }
-
- if(doc.Settings().readCameras) {
- ConvertCameras(*model);
- }
-
- 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);
- }
- }
- 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);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertLights(const Model& model)
- {
- const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
- BOOST_FOREACH(const NodeAttribute* attr, node_attrs) {
- const Light* const light = dynamic_cast<const Light*>(attr);
- if(light) {
- ConvertLight(model, *light);
- }
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertCameras(const Model& model)
- {
- const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
- BOOST_FOREACH(const NodeAttribute* attr, node_attrs) {
- const Camera* const cam = dynamic_cast<const Camera*>(attr);
- if(cam) {
- ConvertCamera(model, *cam);
- }
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertLight(const Model& model, const Light& light)
- {
- lights.push_back(new aiLight());
- aiLight* const out_light = lights.back();
-
- out_light->mName.Set(FixNodeName(model.Name()));
-
- const float intensity = light.Intensity();
- 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;
-
- 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);
- }
-
- // XXX: how to best convert the near and far decay ranges?
- switch(light.DecayType())
- {
- case Light::Decay_None:
- out_light->mAttenuationConstant = 1.0f;
- break;
- case Light::Decay_Linear:
- out_light->mAttenuationLinear = 1.0f;
- break;
- case Light::Decay_Quadratic:
- out_light->mAttenuationQuadratic = 1.0f;
- break;
- case Light::Decay_Cubic:
- FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic");
- out_light->mAttenuationQuadratic = 1.0f;
- break;
- default:
- ai_assert(false);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertCamera(const Model& model, const Camera& cam)
- {
- cameras.push_back(new aiCamera());
- aiCamera* const out_camera = cameras.back();
-
- out_camera->mName.Set(FixNodeName(model.Name()));
-
- out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
- out_camera->mPosition = cam.Position();
- out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition;
-
- // BUG HERE cam.FieldOfView() returns 1.0f every time. 1.0f is default value.
- out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // 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)
- {
- 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_MAXIMUM: // this is to silence compiler warnings
- break;
- }
-
- ai_assert(false);
- return NULL;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // note: this returns the REAL fbx property names
- const char* 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_MAXIMUM: // this is to silence compiler warnings
- break;
- }
-
- ai_assert(false);
- return NULL;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiVector3D 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 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 = 1e-6f;
-
- 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);
- }
-
- ai_assert((order[0] >= 0) && (order[0] <= 2));
- ai_assert((order[1] >= 0) && (order[1] <= 2));
- ai_assert((order[2] >= 0) && (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]];
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- /** checks if a node has more than just scaling, rotation and translation components */
- bool NeedsComplexTransformationChain(const Model& model)
- {
- const PropertyTable& props = model.Props();
- bool ok;
-
- const float zero_epsilon = 1e-6f;
- 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 ||
- comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
- continue;
- }
-
- const aiVector3D& v = PropertyGet<aiVector3D>(props,NameTransformationCompProperty(comp),ok);
- if(ok && v.SquareLength() > zero_epsilon) {
- return true;
- }
- }
-
- return false;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // note: name must be a FixNodeName() result
- std::string NameTransformationChainNode(const std::string& name, TransformationComp comp)
- {
- return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- /** note: memory for output_nodes will be managed by the caller */
- void GenerateTransformationNodeChain(const Model& model,
- std::vector<aiNode*>& output_nodes)
- {
- const PropertyTable& props = model.Props();
- const Model::RotOrder rot = model.RotationOrder();
-
- bool ok;
-
- aiMatrix4x4 chain[TransformationComp_MAXIMUM];
- std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
-
- // generate transformation matrices for all the different transformation components
- const float zero_epsilon = 1e-6f;
- bool is_complex = false;
-
- const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props,"PreRotation",ok);
- if(ok && PreRotation.SquareLength() > zero_epsilon) {
- is_complex = true;
-
- GetRotationMatrix(rot, PreRotation, chain[TransformationComp_PreRotation]);
- }
-
- const aiVector3D& PostRotation = PropertyGet<aiVector3D>(props,"PostRotation",ok);
- if(ok && PostRotation.SquareLength() > zero_epsilon) {
- is_complex = true;
-
- GetRotationMatrix(rot, PostRotation, chain[TransformationComp_PostRotation]);
- }
-
- const aiVector3D& RotationPivot = PropertyGet<aiVector3D>(props,"RotationPivot",ok);
- if(ok && RotationPivot.SquareLength() > zero_epsilon) {
- is_complex = true;
-
- 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) {
- is_complex = true;
-
- aiMatrix4x4::Translation(RotationOffset,chain[TransformationComp_RotationOffset]);
- }
-
- const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>(props,"ScalingOffset",ok);
- if(ok && ScalingOffset.SquareLength() > zero_epsilon) {
- is_complex = true;
-
- aiMatrix4x4::Translation(ScalingOffset,chain[TransformationComp_ScalingOffset]);
- }
-
- const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>(props,"ScalingPivot",ok);
- if(ok && ScalingPivot.SquareLength() > zero_epsilon) {
- is_complex = true;
-
- 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) {
- aiMatrix4x4::Translation(Translation,chain[TransformationComp_Translation]);
- }
-
- const aiVector3D& Scaling = PropertyGet<aiVector3D>(props,"Lcl Scaling",ok);
- if(ok && std::fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
- aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]);
- }
-
- const aiVector3D& Rotation = PropertyGet<aiVector3D>(props,"Lcl Rotation",ok);
- if(ok && Rotation.SquareLength() > zero_epsilon) {
- GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]);
- }
-
- const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
- if (ok && std::fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
- aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
- }
-
- const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>(props, "GeometricRotation", ok);
- if (ok && GeometricRotation.SquareLength() > zero_epsilon) {
- GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]);
- }
-
- const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>(props, "GeometricTranslation", ok);
- if (ok && GeometricTranslation.SquareLength() > zero_epsilon){
- aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]);
- }
-
- // 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) == is_complex);
-
- const std::string& name = FixNodeName(model.Name());
-
- // 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(is_complex && 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 (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) {
- continue;
- }
-
- aiNode* nd = new aiNode();
- output_nodes.push_back(nd);
-
- nd->mName.Set(NameTransformationChainNode(name, comp));
- nd->mTransformation = chain[i];
- }
-
- ai_assert(output_nodes.size());
- return;
- }
-
- // else, we can just multiply the matrices together
- aiNode* nd = new aiNode();
- output_nodes.push_back(nd);
-
- nd->mName.Set(name);
-
- for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
- nd->mTransformation = nd->mTransformation * chain[i];
- }
- }
-
- // ------------------------------------------------------------------------------------------------
-
- void SetupNodeMetadata(const Model& model, aiNode& nd)
- {
- const PropertyTable& props = model.Props();
- DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
-
- // create metadata on node
- std::size_t numStaticMetaData = 2;
- aiMetadata* data = new aiMetadata();
- data->mNumProperties = unparsedProperties.size() + numStaticMetaData;
- data->mKeys = new aiString[data->mNumProperties]();
- data->mValues = new aiMetadataEntry[data->mNumProperties]();
- nd.mMetaData = data;
- int index = 0;
-
- // find user defined properties (3ds Max)
- data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
- unparsedProperties.erase("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
- BOOST_FOREACH(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
- assert(false);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform)
- {
- const std::vector<const Geometry*>& geos = model.GetGeometry();
-
- std::vector<unsigned int> meshes;
- meshes.reserve(geos.size());
-
- BOOST_FOREACH(const Geometry* geo, geos) {
-
- const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
- if(mesh) {
- const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform);
- std::copy(indices.begin(),indices.end(),std::back_inserter(meshes) );
- }
- else {
- FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name());
- }
- }
-
- if(meshes.size()) {
- nd.mMeshes = new unsigned int[meshes.size()]();
- nd.mNumMeshes = static_cast<unsigned int>(meshes.size());
-
- std::swap_ranges(meshes.begin(),meshes.end(),nd.mMeshes);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
- std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh,const Model& model,
- const aiMatrix4x4& node_global_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];
- BOOST_FOREACH(MatIndexArray::value_type index, mindices) {
- if(index != base) {
- return ConvertMeshMultiMaterial(mesh, model, node_global_transform);
- }
- }
- }
-
- // faster codepath, just copy the data
- temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform));
- return temp;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiMesh* SetupEmptyMesh(const MeshGeometry& mesh)
- {
- 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);
- }
-
- return out_mesh;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform)
- {
- const MatIndexArray& mindices = mesh.GetMaterialIndices();
- aiMesh* const out_mesh = SetupEmptyMesh(mesh);
-
- 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;
- BOOST_FOREACH(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 = NULL;
- }
- }
-
- if(binormals) {
- ai_assert(tangents.size() == vertices.size() && 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()];
- BOOST_FOREACH(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() != NULL) {
- ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION);
- }
-
- return static_cast<unsigned int>(meshes.size() - 1);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- const aiMatrix4x4& node_global_transform)
- {
- const MatIndexArray& mindices = mesh.GetMaterialIndices();
- ai_assert(mindices.size());
-
- std::set<MatIndexArray::value_type> had;
- std::vector<unsigned int> indices;
-
- BOOST_FOREACH(MatIndexArray::value_type index, mindices) {
- if(had.find(index) == had.end()) {
-
- indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform));
- had.insert(index);
- }
- }
-
- return indices;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
- MatIndexArray::value_type index,
- const aiMatrix4x4& node_global_transform)
- {
- aiMesh* const out_mesh = SetupEmptyMesh(mesh);
-
- 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() != NULL;
-
- 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
- std::vector<unsigned int> reverseMapping;
-
- if (process_weights) {
- 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();
-
- if(tangents.size()) {
- std::vector<aiVector3D> tempBinormals;
- 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 = NULL;
- }
- }
-
- 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;
- }
-
- 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 i = 0; i < num_uvs; ++i) {
- const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords(i);
- out_mesh->mTextureCoords[i][cursor] = aiVector3D(uvs[in_cursor].x,uvs[in_cursor].y, 0.0f);
- }
-
- for (unsigned int i = 0; i < num_vcs; ++i) {
- const std::vector<aiColor4D>& cols = mesh.GetVertexColors(i);
- out_mesh->mColors[i][cursor] = cols[in_cursor];
- }
- }
- }
-
- ConvertMaterialForMesh(out_mesh,model,mesh,index);
-
- if(process_weights) {
- ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping);
- }
-
- return static_cast<unsigned int>(meshes.size() - 1);
- }
-
- 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& node_global_transform = aiMatrix4x4(),
- unsigned int materialIndex = NO_MATERIAL_SEPARATION,
- std::vector<unsigned int>* outputVertStartIndices = NULL)
- {
- 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;
- bones.reserve(sk.Clusters().size());
-
- const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
- ai_assert(no_mat_check || outputVertStartIndices);
-
- try {
-
- BOOST_FOREACH(const Cluster* cluster, sk.Clusters()) {
- ai_assert(cluster);
-
- const WeightIndexArray& indices = cluster->GetIndices();
-
- if(indices.empty()) {
- continue;
- }
-
- const MatIndexArray& mats = geo.GetMaterialIndices();
-
- bool ok = false;
-
- 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.
- BOOST_FOREACH(WeightIndexArray::value_type index, indices) {
-
- unsigned int count = 0;
- const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count);
-
- 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();
- ok = true;
- }
- }
- }
-
- // 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.
- if (ok) {
- ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
- count_out_indices, node_global_transform);
- }
- }
- }
- catch (std::exception&) {
- std::for_each(bones.begin(),bones.end(),Util::delete_fun<aiBone>());
- throw;
- }
-
- if(bones.empty()) {
- return;
- }
-
- out->mBones = new aiBone*[bones.size()]();
- out->mNumBones = static_cast<unsigned int>(bones.size());
-
- std::swap_ranges(bones.begin(),bones.end(),out->mBones);
- }
+ ai_assert( nodes_chain.size() );
+ const std::string& original_name = FixNodeName( model->Name() );
+ // check if any of the nodes in the chain has the name the fbx node
+ // is supposed to have. If there is none, add another node to
+ // preserve the name - people might have scripts etc. that rely
+ // on specific node names.
+ aiNode* name_carrier = NULL;
+ for( aiNode* prenode : nodes_chain ) {
+ if ( !strcmp( prenode->mName.C_Str(), original_name.c_str() ) ) {
+ name_carrier = prenode;
+ break;
+ }
+ }
- // ------------------------------------------------------------------------------------------------
- void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl,
- std::vector<size_t>& out_indices,
- std::vector<size_t>& index_out_indices,
- std::vector<size_t>& count_out_indices,
- const aiMatrix4x4& node_global_transform)
- {
+ if ( !name_carrier ) {
+ nodes_chain.push_back( new aiNode( original_name ) );
+ name_carrier = nodes_chain.back();
+ }
- aiBone* const bone = new aiBone();
- bones.push_back(bone);
+ //setup metadata on newest node
+ SetupNodeMetadata( *model, *nodes_chain.back() );
- bone->mName = FixNodeName(cl.TargetNode()->Name());
+ // link all nodes in a row
+ aiNode* last_parent = &parent;
+ for( aiNode* prenode : nodes_chain ) {
+ ai_assert( prenode );
- bone->mOffsetMatrix = cl.TransformLink();
- bone->mOffsetMatrix.Inverse();
-
- bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform;
-
- bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
- aiVertexWeight* 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) {
- aiVertexWeight& out_weight = *cursor++;
-
- out_weight.mVertexId = static_cast<unsigned int>(out_indices[index_index + j]);
- out_weight.mWeight = weights[i];
- }
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void 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 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;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // Material -> aiMaterial
- unsigned int 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;
-
- // stip 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);
- }
-
- // shading stuff and colors
- SetShadingPropertiesCommon(out_mat,props);
-
- // texture assignments
- SetTextureProperties(out_mat,material.Textures(), mesh);
- SetTextureProperties(out_mat,material.LayeredTextures(), mesh);
-
- return static_cast<unsigned int>(materials.size() - 1);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void 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;
- path.Set(tex->RelativeFilename());
-
- 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)
- {
- BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
- const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
- if(!mesh) {
- continue;
- }
-
- const MatIndexArray& mats = mesh->GetMaterialIndices();
- if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
- continue;
- }
-
- int index = -1;
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- if(mesh->GetTextureCoords(i).empty()) {
- break;
- }
- const std::string& name = mesh->GetTextureCoordChannelName(i);
- if(name == uvSet) {
- index = static_cast<int>(i);
- break;
- }
- }
- if(index == -1) {
- FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
- continue;
- }
-
- if(uvIndex == -1) {
- uvIndex = index;
- }
- else {
- FBXImporter::LogWarn("the UV channel named " + uvSet +
- " appears at different positions in meshes, results will be wrong");
- }
- }
- }
- else
- {
- int index = -1;
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- if(mesh->GetTextureCoords(i).empty()) {
- 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 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;
- }
-
- const Texture* const tex = (*it).second->getTexture();
-
- aiString path;
- path.Set(tex->RelativeFilename());
-
- 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)
- {
- BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) {
- const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
- if(!mesh) {
- continue;
- }
-
- const MatIndexArray& mats = mesh->GetMaterialIndices();
- if(std::find(mats.begin(),mats.end(),matIndex) == mats.end()) {
- continue;
- }
-
- int index = -1;
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- if(mesh->GetTextureCoords(i).empty()) {
- break;
- }
- const std::string& name = mesh->GetTextureCoordChannelName(i);
- if(name == uvSet) {
- index = static_cast<int>(i);
- break;
- }
- }
- if(index == -1) {
- FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
- continue;
- }
-
- if(uvIndex == -1) {
- uvIndex = index;
- }
- else {
- FBXImporter::LogWarn("the UV channel named " + uvSet +
- " appears at different positions in meshes, results will be wrong");
- }
- }
+ if ( last_parent != &parent ) {
+ last_parent->mNumChildren = 1;
+ last_parent->mChildren = new aiNode*[ 1 ];
+ last_parent->mChildren[ 0 ] = prenode;
+ }
+
+ prenode->mParent = last_parent;
+ last_parent = prenode;
+
+ new_abs_transform *= prenode->mTransformation;
+ }
+
+ // attach geometry
+ ConvertModel( *model, *nodes_chain.back(), new_abs_transform );
+
+ // attach sub-nodes
+ ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform );
+
+ if ( doc.Settings().readLights ) {
+ ConvertLights( *model );
+ }
+
+ if ( doc.Settings().readCameras ) {
+ ConvertCameras( *model );
+ }
+
+ 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 );
}
+ }
+ 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 );
+ }
+}
+
+
+void Converter::ConvertLights( const Model& model )
+{
+ 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( model, *light );
+ }
+ }
+}
+
+void Converter::ConvertCameras( const Model& model )
+{
+ 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( model, *cam );
+ }
+ }
+}
+
+
+void Converter::ConvertLight( const Model& model, const Light& light )
+{
+ lights.push_back( new aiLight() );
+ aiLight* const out_light = lights.back();
+
+ out_light->mName.Set( FixNodeName( model.Name() ) );
+
+ const float intensity = light.Intensity();
+ 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;
+
+ 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 );
+ }
+
+ // XXX: how to best convert the near and far decay ranges?
+ switch ( light.DecayType() )
+ {
+ case Light::Decay_None:
+ out_light->mAttenuationConstant = 1.0f;
+ break;
+ case Light::Decay_Linear:
+ out_light->mAttenuationLinear = 1.0f;
+ break;
+ case Light::Decay_Quadratic:
+ out_light->mAttenuationQuadratic = 1.0f;
+ break;
+ case Light::Decay_Cubic:
+ FBXImporter::LogWarn( "cannot represent cubic attenuation, set to Quadratic" );
+ out_light->mAttenuationQuadratic = 1.0f;
+ break;
+ default:
+ ai_assert( false );
+ }
+}
+
+void Converter::ConvertCamera( const Model& model, const Camera& cam )
+{
+ cameras.push_back( new aiCamera() );
+ aiCamera* const out_camera = cameras.back();
+
+ out_camera->mName.Set( FixNodeName( model.Name() ) );
+
+ out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
+ out_camera->mPosition = cam.Position();
+ out_camera->mUp = cam.UpVector();
+ out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition;
+ out_camera->mHorizontalFOV = AI_DEG_TO_RAD( cam.FieldOfView() );
+}
+
+
+const char* Converter::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_MAXIMUM: // this is to silence compiler warnings
+ default:
+ break;
+ }
+
+ ai_assert( false );
+ return NULL;
+}
+
+
+const char* Converter::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_MAXIMUM: // this is to silence compiler warnings
+ break;
+ }
+
+ ai_assert( false );
+ return NULL;
+}
+
+aiVector3D Converter::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 Converter::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 = 1e-6f;
+
+ 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 );
+ }
+
+ ai_assert( ( order[ 0 ] >= 0 ) && ( order[ 0 ] <= 2 ) );
+ ai_assert( ( order[ 1 ] >= 0 ) && ( order[ 1 ] <= 2 ) );
+ ai_assert( ( order[ 2 ] >= 0 ) && ( 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 Converter::NeedsComplexTransformationChain( const Model& model )
+{
+ const PropertyTable& props = model.Props();
+ bool ok;
+
+ const float zero_epsilon = 1e-6f;
+ 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 ||
+ comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
+ continue;
+ }
+
+ const aiVector3D& v = PropertyGet<aiVector3D>( props, NameTransformationCompProperty( comp ), ok );
+ if ( ok && v.SquareLength() > zero_epsilon ) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+std::string Converter::NameTransformationChainNode( const std::string& name, TransformationComp comp )
+{
+ return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
+}
+
+void Converter::GenerateTransformationNodeChain( const Model& model,
+ std::vector<aiNode*>& output_nodes )
+{
+ const PropertyTable& props = model.Props();
+ const Model::RotOrder rot = model.RotationOrder();
+
+ bool ok;
+
+ aiMatrix4x4 chain[ TransformationComp_MAXIMUM ];
+ std::fill_n( chain, static_cast<unsigned int>( TransformationComp_MAXIMUM ), aiMatrix4x4() );
+
+ // generate transformation matrices for all the different transformation components
+ const float zero_epsilon = 1e-6f;
+ bool is_complex = false;
+
+ const aiVector3D& PreRotation = PropertyGet<aiVector3D>( props, "PreRotation", ok );
+ if ( ok && PreRotation.SquareLength() > zero_epsilon ) {
+ is_complex = true;
+
+ GetRotationMatrix( rot, PreRotation, chain[ TransformationComp_PreRotation ] );
+ }
+
+ const aiVector3D& PostRotation = PropertyGet<aiVector3D>( props, "PostRotation", ok );
+ if ( ok && PostRotation.SquareLength() > zero_epsilon ) {
+ is_complex = true;
+
+ GetRotationMatrix( rot, PostRotation, chain[ TransformationComp_PostRotation ] );
+ }
+
+ const aiVector3D& RotationPivot = PropertyGet<aiVector3D>( props, "RotationPivot", ok );
+ if ( ok && RotationPivot.SquareLength() > zero_epsilon ) {
+ is_complex = true;
+
+ 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 ) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation( RotationOffset, chain[ TransformationComp_RotationOffset ] );
+ }
+
+ const aiVector3D& ScalingOffset = PropertyGet<aiVector3D>( props, "ScalingOffset", ok );
+ if ( ok && ScalingOffset.SquareLength() > zero_epsilon ) {
+ is_complex = true;
+
+ aiMatrix4x4::Translation( ScalingOffset, chain[ TransformationComp_ScalingOffset ] );
+ }
+
+ const aiVector3D& ScalingPivot = PropertyGet<aiVector3D>( props, "ScalingPivot", ok );
+ if ( ok && ScalingPivot.SquareLength() > zero_epsilon ) {
+ is_complex = true;
+
+ 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 ) {
+ aiMatrix4x4::Translation( Translation, chain[ TransformationComp_Translation ] );
+ }
+
+ const aiVector3D& Scaling = PropertyGet<aiVector3D>( props, "Lcl Scaling", ok );
+ if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) {
+ aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] );
+ }
+
+ const aiVector3D& Rotation = PropertyGet<aiVector3D>( props, "Lcl Rotation", ok );
+ if ( ok && Rotation.SquareLength() > zero_epsilon ) {
+ GetRotationMatrix( rot, Rotation, chain[ TransformationComp_Rotation ] );
+ }
+
+ const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>( props, "GeometricScaling", ok );
+ if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) {
+ aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] );
+ }
+
+ const aiVector3D& GeometricRotation = PropertyGet<aiVector3D>( props, "GeometricRotation", ok );
+ if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) {
+ GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] );
+ }
+
+ const aiVector3D& GeometricTranslation = PropertyGet<aiVector3D>( props, "GeometricTranslation", ok );
+ if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) {
+ aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] );
+ }
+
+ // 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 ) == is_complex );
+
+ const std::string& name = FixNodeName( model.Name() );
+
+ // 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 ( is_complex && 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 ( chain[ i ].IsIdentity() && ( anim_chain_bitmask & bit ) == 0 ) {
+ continue;
+ }
+
+ aiNode* nd = new aiNode();
+ output_nodes.push_back( nd );
+
+ nd->mName.Set( NameTransformationChainNode( name, comp ) );
+ nd->mTransformation = chain[ i ];
+ }
+
+ ai_assert( output_nodes.size() );
+ return;
+ }
+
+ // else, we can just multiply the matrices together
+ aiNode* nd = new aiNode();
+ output_nodes.push_back( nd );
+
+ nd->mName.Set( name );
+
+ for (const auto &transform : chain) {
+ nd->mTransformation = nd->mTransformation * transform;
+ }
+}
+
+
+void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
+{
+ const PropertyTable& props = model.Props();
+ DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
+
+ // create metadata on node
+ std::size_t numStaticMetaData = 2;
+ aiMetadata* data = new aiMetadata();
+ data->mNumProperties = unparsedProperties.size() + numStaticMetaData;
+ data->mKeys = new aiString[ data->mNumProperties ]();
+ data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
+ 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
+ assert( false );
+ }
+}
+
+void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_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 );
+ if ( mesh ) {
+ const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform );
+ std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
+ }
+ else {
+ FBXImporter::LogWarn( "ignoring unrecognized geometry: " + geo->Name() );
+ }
+ }
+
+ if ( meshes.size() ) {
+ nd.mMeshes = new unsigned int[ meshes.size() ]();
+ nd.mNumMeshes = static_cast< unsigned int >( meshes.size() );
+
+ std::swap_ranges( meshes.begin(), meshes.end(), nd.mMeshes );
+ }
+}
+
+
+std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_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, node_global_transform );
+ }
+ }
+ }
+
+ // faster code-path, just copy the data
+ temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) );
+ return temp;
+}
+
+
+aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
+{
+ 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 );
+ }
+
+ return out_mesh;
+}
+
+
+unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_transform )
+{
+ const MatIndexArray& mindices = mesh.GetMaterialIndices();
+ aiMesh* const out_mesh = SetupEmptyMesh( mesh );
+
+ 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 )
{
- 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 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, "TransparentColor", aiTextureType_OPACITY, mesh);
- TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh);
- TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh);
- TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh);
- TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh);
- TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh);
- }
-
- // ------------------------------------------------------------------------------------------------
- void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, 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, "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);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
- bool& result)
- {
- result = true;
-
- bool ok;
- const aiVector3D& Diffuse = PropertyGet<aiVector3D>(props,baseName,ok);
- if(ok) {
- return aiColor3D(Diffuse.x,Diffuse.y,Diffuse.z);
- }
- else {
- aiVector3D DiffuseColor = PropertyGet<aiVector3D>(props,baseName + "Color",ok);
- if(ok) {
- float DiffuseFactor = PropertyGet<float>(props,baseName + "Factor",ok);
- if(ok) {
- DiffuseColor *= DiffuseFactor;
- }
-
- return aiColor3D(DiffuseColor.x,DiffuseColor.y,DiffuseColor.z);
- }
- }
- result = false;
- return aiColor3D(0.0f,0.0f,0.0f);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props)
- {
- // set shading properties. There are various, redundant ways in which FBX materials
- // specify their shading settings (depending on shading models, prop
- // template etc.). No idea which one is right in a particular context.
- // Just try to make sense of it - there's no spec to verify this against,
- // so why should we.
- 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);
- }
-
- const aiColor3D& Specular = GetColorPropertyFromMaterial(props,"Specular",ok);
- if(ok) {
- out_mat->AddProperty(&Specular,1,AI_MATKEY_COLOR_SPECULAR);
- }
-
- const float Opacity = PropertyGet<float>(props,"Opacity",ok);
- if(ok) {
- out_mat->AddProperty(&Opacity,1,AI_MATKEY_OPACITY);
- }
-
- const float Reflectivity = PropertyGet<float>(props,"Reflectivity",ok);
- if(ok) {
- out_mat->AddProperty(&Reflectivity,1,AI_MATKEY_REFLECTIVITY);
- }
-
- const float Shininess = PropertyGet<float>(props,"Shininess",ok);
- if(ok) {
- out_mat->AddProperty(&Shininess,1,AI_MATKEY_SHININESS_STRENGTH);
- }
-
- const float ShininessExponent = PropertyGet<float>(props,"ShininessExponent",ok);
- if(ok) {
- out_mat->AddProperty(&ShininessExponent,1,AI_MATKEY_SHININESS);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // get the number of fps for a FrameRate enumerated value
- static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0)
- {
- 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;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // convert animation data to aiAnimation et al
- void 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();
- BOOST_FOREACH(const AnimationStack* stack, animations) {
- ConvertAnimationStack(*stack);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // rename a node already partially converted. fixed_name is a string previously returned by
- // FixNodeName, new_name specifies the string FixNodeName should return on all further invocations
- // which would previously have returned the old value.
- //
- // this also updates names in node animations, cameras and light sources and is thus slow.
- //
- // NOTE: the caller is responsible for ensuring that the new name is unique and does
- // not collide with any other identifiers. The best way to ensure this is to only
- // append to the old name, which is guaranteed to match these requirements.
- void RenameNode(const std::string& fixed_name, const std::string& new_name)
- {
- ai_assert(node_names.find(fixed_name) != node_names.end());
- ai_assert(node_names.find(new_name) == node_names.end());
-
- renamed_nodes[fixed_name] = new_name;
-
- const aiString fn(fixed_name);
-
- BOOST_FOREACH(aiCamera* cam, cameras) {
- if (cam->mName == fn) {
- cam->mName.Set(new_name);
- break;
- }
- }
-
- BOOST_FOREACH(aiLight* light, lights) {
- if (light->mName == fn) {
- light->mName.Set(new_name);
- break;
- }
- }
-
- BOOST_FOREACH(aiAnimation* anim, animations) {
- for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
- aiNodeAnim* const na = anim->mChannels[i];
- if (na->mNodeName == fn) {
- na->mNodeName.Set(new_name);
- break;
- }
- }
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // 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)
- {
- // 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);
-
- const NodeNameMap::const_iterator it = node_names.find(temp);
- if (it != node_names.end()) {
- if (!(*it).second) {
- return FixNodeName(name + "_");
- }
- }
- node_names[temp] = true;
-
- const NameNameMap::const_iterator rit = renamed_nodes.find(temp);
- return rit == renamed_nodes.end() ? temp : (*rit).second;
- }
-
- const NodeNameMap::const_iterator it = node_names.find(name);
- if (it != node_names.end()) {
- if ((*it).second) {
- return FixNodeName(name + "_");
- }
- }
- node_names[name] = false;
-
- const NameNameMap::const_iterator rit = renamed_nodes.find(name);
- return rit == renamed_nodes.end() ? name : (*rit).second;
- }
-
-
- 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)
- {
- 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);
- }
-
- 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"
- };
-
- BOOST_FOREACH(const AnimationLayer* layer, layers) {
- ai_assert(layer);
-
- const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 3);
- BOOST_FOREACH(const AnimationCurveNode* node, nodes) {
- ai_assert(node);
-
- const Model* const model = dynamic_cast<const Model*>(node->Target());
- // this can happen - it could also be a NodeAttribute (i.e. for camera animations)
- if(!model) {
- continue;
- }
-
- const std::string& name = FixNodeName(model->Name());
- node_map[name].push_back(node);
-
- layer_map[node] = layer;
- }
- }
-
- // generate node animations
- std::vector<aiNodeAnim*> node_anims;
-
- double min_time = 1e10;
- double max_time = -1e10;
-
- try {
- BOOST_FOREACH(const NodeMap::value_type& kv, node_map) {
- GenerateNodeAnimations(node_anims,
- kv.first,
- kv.second,
- layer_map,
- 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()) {
- 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);
- }
- else {
- // empty animations would fail validation, so drop them
- delete anim;
- animations.pop_back();
- FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name);
- return;
- }
-
- // for some mysterious reason, mDuration is simply the maximum key -- the
- // validator always assumes animations to start at zero.
- anim->mDuration = max_time /*- min_time */;
- anim->mTicksPerSecond = anim_fps;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
- const std::string& fixed_name,
- const std::vector<const AnimationCurveNode*>& curves,
- const LayerMap& layer_map,
- double& max_time,
- double& min_time)
- {
-
- NodeMap node_property_map;
- ai_assert(curves.size());
-
- // sanity check whether the input is ok
+ 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 = NULL;
+ }
+ }
+
+ 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() != NULL ) {
+ ConvertWeights( out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION );
+ }
+
+ return static_cast<unsigned int>( meshes.size() - 1 );
+}
+
+std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
+ const aiMatrix4x4& node_global_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, node_global_transform ) );
+ had.insert( index );
+ }
+ }
+
+ return indices;
+}
+
+unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
+ MatIndexArray::value_type index,
+ const aiMatrix4x4& node_global_transform )
+{
+ aiMesh* const out_mesh = SetupEmptyMesh( mesh );
+
+ 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() != NULL;
+
+ 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
+ std::vector<unsigned int> reverseMapping;
+
+ if ( process_weights ) {
+ 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();
+
+ if ( tangents.size() ) {
+ std::vector<aiVector3D> tempBinormals;
+ 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 = NULL;
+ }
+ }
+
+ 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;
+ }
+
+ 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 i = 0; i < num_uvs; ++i ) {
+ const std::vector<aiVector2D>& uvs = mesh.GetTextureCoords( i );
+ out_mesh->mTextureCoords[ i ][ cursor ] = aiVector3D( uvs[ in_cursor ].x, uvs[ in_cursor ].y, 0.0f );
+ }
+
+ for ( unsigned int i = 0; i < num_vcs; ++i ) {
+ const std::vector<aiColor4D>& cols = mesh.GetVertexColors( i );
+ out_mesh->mColors[ i ][ cursor ] = cols[ in_cursor ];
+ }
+ }
+ }
+
+ ConvertMaterialForMesh( out_mesh, model, mesh, index );
+
+ if ( process_weights ) {
+ ConvertWeights( out_mesh, model, mesh, node_global_transform, index, &reverseMapping );
+ }
+
+ return static_cast<unsigned int>( meshes.size() - 1 );
+}
+
+
+void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo,
+ const aiMatrix4x4& node_global_transform ,
+ 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;
+ bones.reserve( sk.Clusters().size() );
+
+ const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
+ ai_assert( no_mat_check || outputVertStartIndices );
+
+ try {
+
+ for( const Cluster* cluster : sk.Clusters() ) {
+ ai_assert( cluster );
+
+ const WeightIndexArray& indices = cluster->GetIndices();
+
+ if ( indices.empty() ) {
+ continue;
+ }
+
+ const MatIndexArray& mats = geo.GetMaterialIndices();
+
+ bool ok = false;
+
+ 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 NULL if index is out of bounds
+ // which should never happen
+ ai_assert( out_idx != NULL );
+
+ 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();
+ ok = true;
+ }
+ }
+ }
+
+ // 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.
+ if ( ok ) {
+ ConvertCluster( bones, model, *cluster, out_indices, index_out_indices,
+ count_out_indices, node_global_transform );
+ }
+ }
+ }
+ catch ( std::exception& ) {
+ std::for_each( bones.begin(), bones.end(), Util::delete_fun<aiBone>() );
+ throw;
+ }
+
+ if ( bones.empty() ) {
+ return;
+ }
+
+ out->mBones = new aiBone*[ bones.size() ]();
+ out->mNumBones = static_cast<unsigned int>( bones.size() );
+
+ std::swap_ranges( bones.begin(), bones.end(), out->mBones );
+}
+
+void Converter::ConvertCluster( std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
+ std::vector<size_t>& out_indices,
+ std::vector<size_t>& index_out_indices,
+ std::vector<size_t>& count_out_indices,
+ const aiMatrix4x4& node_global_transform )
+{
+
+ aiBone* const bone = new aiBone();
+ bones.push_back( bone );
+
+ bone->mName = FixNodeName( cl.TargetNode()->Name() );
+
+ bone->mOffsetMatrix = cl.TransformLink();
+ bone->mOffsetMatrix.Inverse();
+
+ bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform;
+
+ bone->mNumWeights = static_cast<unsigned int>( out_indices.size() );
+ aiVertexWeight* 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 ) {
+ aiVertexWeight& out_weight = *cursor++;
+
+ out_weight.mVertexId = static_cast<unsigned int>( out_indices[ index_index + j ] );
+ out_weight.mWeight = weights[ i ];
+ }
+ }
+}
+
+
+void Converter::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 Converter::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 Converter::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;
+
+ // stip 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 );
+ }
+
+ // shading stuff and colors
+ SetShadingPropertiesCommon( out_mat, props );
+
+ // texture assignments
+ SetTextureProperties( out_mat, material.Textures(), mesh );
+ SetTextureProperties( out_mat, material.LayeredTextures(), mesh );
+
+ return static_cast<unsigned int>( materials.size() - 1 );
+}
+
+unsigned int Converter::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.FileName().empty() ? video.RelativeFilename() : video.FileName();
+ std::string ext = BaseImporter::GetExtension( filename );
+
+ if ( ext == "jpeg" ) {
+ ext = "jpg";
+ }
+
+ if ( ext.size() <= 3 ) {
+ memcpy( out_tex->achFormatHint, ext.c_str(), ext.size() );
+ }
+
+ return static_cast<unsigned int>( textures.size() - 1 );
+}
+
+void Converter::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;
+ path.Set( tex->RelativeFilename() );
+
+ const Video* media = tex->Media();
+ if ( media != 0 && 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, _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 mesh = dynamic_cast<const MeshGeometry*> ( v.first );
+ if ( !mesh ) {
+ continue;
+ }
+
+ const MatIndexArray& mats = mesh->GetMaterialIndices();
+ if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) {
+ continue;
+ }
+
+ int index = -1;
+ for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
+ if ( mesh->GetTextureCoords( i ).empty() ) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName( i );
+ if ( name == uvSet ) {
+ index = static_cast<int>( i );
+ break;
+ }
+ }
+ if ( index == -1 ) {
+ FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" );
+ continue;
+ }
+
+ if ( uvIndex == -1 ) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn( "the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong" );
+ }
+ }
+ }
+ else
+ {
+ int index = -1;
+ for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
+ if ( mesh->GetTextureCoords( i ).empty() ) {
+ 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 Converter::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;
+ }
+
+ const Texture* const tex = ( *it ).second->getTexture();
+
+ aiString path;
+ path.Set( tex->RelativeFilename() );
+
+ 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 mesh = dynamic_cast<const MeshGeometry*> ( v.first );
+ if ( !mesh ) {
+ continue;
+ }
+
+ const MatIndexArray& mats = mesh->GetMaterialIndices();
+ if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) {
+ continue;
+ }
+
+ int index = -1;
+ for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
+ if ( mesh->GetTextureCoords( i ).empty() ) {
+ break;
+ }
+ const std::string& name = mesh->GetTextureCoordChannelName( i );
+ if ( name == uvSet ) {
+ index = static_cast<int>( i );
+ break;
+ }
+ }
+ if ( index == -1 ) {
+ FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" );
+ continue;
+ }
+
+ if ( uvIndex == -1 ) {
+ uvIndex = index;
+ }
+ else {
+ FBXImporter::LogWarn( "the UV channel named " + uvSet +
+ " appears at different positions in meshes, results will be wrong" );
+ }
+ }
+ }
+ else
+ {
+ int index = -1;
+ for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) {
+ if ( mesh->GetTextureCoords( i ).empty() ) {
+ 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 Converter::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, "TransparentColor", aiTextureType_OPACITY, mesh );
+ TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh );
+ TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh );
+ TrySetTextureProperties( out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh );
+ TrySetTextureProperties( out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh );
+ TrySetTextureProperties( out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh );
+}
+
+void Converter::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, "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 );
+}
+
+aiColor3D Converter::GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName,
+ bool& result )
+{
+ result = true;
+
+ bool ok;
+ const aiVector3D& Diffuse = PropertyGet<aiVector3D>( props, baseName, ok );
+ if ( ok ) {
+ return aiColor3D( Diffuse.x, Diffuse.y, Diffuse.z );
+ }
+ else {
+ aiVector3D DiffuseColor = PropertyGet<aiVector3D>( props, baseName + "Color", ok );
+ if ( ok ) {
+ float DiffuseFactor = PropertyGet<float>( props, baseName + "Factor", ok );
+ if ( ok ) {
+ DiffuseColor *= DiffuseFactor;
+ }
+
+ return aiColor3D( DiffuseColor.x, DiffuseColor.y, DiffuseColor.z );
+ }
+ }
+ result = false;
+ return aiColor3D( 0.0f, 0.0f, 0.0f );
+}
+
+
+void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props )
+{
+ // set shading properties. There are various, redundant ways in which FBX materials
+ // specify their shading settings (depending on shading models, prop
+ // template etc.). No idea which one is right in a particular context.
+ // Just try to make sense of it - there's no spec to verify this against,
+ // so why should we.
+ 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 );
+ }
+
+ const aiColor3D& Specular = GetColorPropertyFromMaterial( props, "Specular", ok );
+ if ( ok ) {
+ out_mat->AddProperty( &Specular, 1, AI_MATKEY_COLOR_SPECULAR );
+ }
+
+ const float Opacity = PropertyGet<float>( props, "Opacity", ok );
+ if ( ok ) {
+ out_mat->AddProperty( &Opacity, 1, AI_MATKEY_OPACITY );
+ }
+
+ const float Reflectivity = PropertyGet<float>( props, "Reflectivity", ok );
+ if ( ok ) {
+ out_mat->AddProperty( &Reflectivity, 1, AI_MATKEY_REFLECTIVITY );
+ }
+
+ const float Shininess = PropertyGet<float>( props, "Shininess", ok );
+ if ( ok ) {
+ out_mat->AddProperty( &Shininess, 1, AI_MATKEY_SHININESS_STRENGTH );
+ }
+
+ const float ShininessExponent = PropertyGet<float>( props, "ShininessExponent", ok );
+ if ( ok ) {
+ out_mat->AddProperty( &ShininessExponent, 1, AI_MATKEY_SHININESS );
+ }
+}
+
+
+double Converter::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 Converter::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 );
+ }
+}
+
+
+void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name )
+{
+ ai_assert( node_names.find( fixed_name ) != node_names.end() );
+ ai_assert( node_names.find( new_name ) == node_names.end() );
+
+ renamed_nodes[ fixed_name ] = new_name;
+
+ const aiString fn( fixed_name );
+
+ for( aiCamera* cam : cameras ) {
+ if ( cam->mName == fn ) {
+ cam->mName.Set( new_name );
+ break;
+ }
+ }
+
+ for( aiLight* light : lights ) {
+ if ( light->mName == fn ) {
+ light->mName.Set( new_name );
+ break;
+ }
+ }
+
+ for( aiAnimation* anim : animations ) {
+ for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) {
+ aiNodeAnim* const na = anim->mChannels[ i ];
+ if ( na->mNodeName == fn ) {
+ na->mNodeName.Set( new_name );
+ break;
+ }
+ }
+ }
+}
+
+
+std::string Converter::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 );
+
+ const NodeNameMap::const_iterator it = node_names.find( temp );
+ if ( it != node_names.end() ) {
+ if ( !( *it ).second ) {
+ return FixNodeName( name + "_" );
+ }
+ }
+ node_names[ temp ] = true;
+
+ const NameNameMap::const_iterator rit = renamed_nodes.find( temp );
+ return rit == renamed_nodes.end() ? temp : ( *rit ).second;
+ }
+
+ const NodeNameMap::const_iterator it = node_names.find( name );
+ if ( it != node_names.end() ) {
+ if ( ( *it ).second ) {
+ return FixNodeName( name + "_" );
+ }
+ }
+ node_names[ name ] = false;
+
+ const NameNameMap::const_iterator rit = renamed_nodes.find( name );
+ return rit == renamed_nodes.end() ? name : ( *rit ).second;
+}
+
+void Converter::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"
+ };
+
+ for( const AnimationLayer* layer : layers ) {
+ ai_assert( layer );
+
+ const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 );
+ for( const AnimationCurveNode* node : nodes ) {
+ ai_assert( node );
+
+ const Model* const model = dynamic_cast<const Model*>( node->Target() );
+ // this can happen - it could also be a NodeAttribute (i.e. for camera animations)
+ if ( !model ) {
+ continue;
+ }
+
+ const std::string& name = FixNodeName( model->Name() );
+ node_map[ name ].push_back( node );
+
+ layer_map[ node ] = layer;
+ }
+ }
+
+ // 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();
+ double start_timeF = CONVERT_FBX_TIME( start_time );
+ double stop_timeF = CONVERT_FBX_TIME( stop_time );
+
+ 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() ) {
+ 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 );
+ }
+ else {
+ // empty animations would fail validation, so drop them
+ delete anim;
+ animations.pop_back();
+ FBXImporter::LogInfo( "ignoring empty AnimationStack (using IK?): " + name );
+ return;
+ }
+
+ //adjust relative timing for animation
+ {
+ double start_fps = start_timeF * anim_fps;
+
+ 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_fps;
+ for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ )
+ channel->mRotationKeys[ i ].mTime -= start_fps;
+ for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ )
+ channel->mScalingKeys[ i ].mTime -= start_fps;
+ }
+
+ max_time -= min_time;
+ }
+
+ // for some mysterious reason, mDuration is simply the maximum key -- the
+ // validator always assumes animations to start at zero.
+ anim->mDuration = ( stop_timeF - start_timeF ) * anim_fps;
+ anim->mTicksPerSecond = anim_fps;
+}
+
+// ------------------------------------------------------------------------------------------------
+// sanity check whether the input is ok
+static void validateAnimCurveNodes( const std::vector<const AnimationCurveNode*>& curves,
+ bool strictMode ) {
+ const Object* target( NULL );
+ 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 );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Converter::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
- { const Object* target = NULL;
- BOOST_FOREACH(const AnimationCurveNode* node, curves) {
- if(!target) {
- target = node->Target();
- }
- ai_assert(node->Target() == target);
- }}
+ validateAnimCurveNodes( curves, doc.Settings().strictMode );
#endif
+ const AnimationCurveNode* curve_node = NULL;
+ for( const AnimationCurveNode* node : curves ) {
+ ai_assert( node );
- const AnimationCurveNode* curve_node = NULL;
- BOOST_FOREACH(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 &&
- comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation )
- {
- 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,
- max_time,
- min_time,
- true // input is TRS order, assimp is SRT
- );
-
- ai_assert(nd);
- 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;
- switch(comp)
- {
- case TransformationComp_Rotation:
- case TransformationComp_PreRotation:
- case TransformationComp_PostRotation:
- case TransformationComp_GeometricRotation:
- na = GenerateRotationNodeAnim(chain_name,
- target,
- (*chain[i]).second,
- layer_map,
- 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,
- 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,
- max_time,
- min_time,
- true);
-
- ai_assert(inv);
- 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,
- max_time,
- min_time,
- true);
-
- ai_assert(inv);
- 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,
- max_time,
- min_time);
-
- break;
-
- default:
- ai_assert(false);
- }
-
- ai_assert(na);
- node_anims.push_back(na);
- continue;
- }
- }
-
- node_anim_chain_bits[fixed_name] = flags;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- bool 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 = 1e-6f;
- return (dyn_val - static_val).SquareLength() < epsilon;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiNodeAnim* GenerateRotationNodeAnim(const std::string& name,
- const Model& target,
- const std::vector<const AnimationCurveNode*>& curves,
- const LayerMap& layer_map,
- double& max_time,
- double& min_time)
- {
- ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
- na->mNodeName.Set(name);
-
- ConvertRotationKeys(na, curves, layer_map, 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.dismiss();
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
- const Model& target,
- const std::vector<const AnimationCurveNode*>& curves,
- const LayerMap& layer_map,
- double& max_time,
- double& min_time)
- {
- ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
- na->mNodeName.Set(name);
-
- ConvertScaleKeys(na, curves, layer_map, 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.dismiss();
- }
-
-
- // ------------------------------------------------------------------------------------------------
- aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
- const Model& target,
- const std::vector<const AnimationCurveNode*>& curves,
- const LayerMap& layer_map,
- double& max_time,
- double& min_time,
- bool inverse = false)
- {
- ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
- na->mNodeName.Set(name);
-
- ConvertTranslationKeys(na, curves, layer_map, 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.dismiss();
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // 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,
- double& max_time,
- double& min_time,
- bool reverse_order = false)
-
- {
- ScopeGuard<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, def_translate;
- aiQuaternion def_rot;
-
- KeyFrameListList scaling;
- KeyFrameListList translation;
- KeyFrameListList rotation;
-
- if(chain[TransformationComp_Scaling] != iter_end) {
- scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second);
- }
- else {
- def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f));
- }
-
- if(chain[TransformationComp_Translation] != iter_end) {
- translation = GetKeyframeList((*chain[TransformationComp_Translation]).second);
- }
- else {
- def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f));
- }
-
- if(chain[TransformationComp_Rotation] != iter_end) {
- rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second);
- }
- else {
- def_rot = EulerToQuaternion(PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)),
- target.RotationOrder());
- }
-
- 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()];
-
- 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, (*chain[TransformationComp_Scaling]).second,
- layer_map,
- 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, (*chain[TransformationComp_Rotation]).second,
- layer_map,
- 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, (*chain[TransformationComp_Translation]).second,
- layer_map,
- 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.dismiss();
- }
-
-
-
- // key (time), value, mapto (component index)
- typedef boost::tuple< const KeyTimeList*, const KeyValueList*, unsigned int > KeyFrameList;
- typedef std::vector<KeyFrameList> KeyFrameListList;
-
-
-
- // ------------------------------------------------------------------------------------------------
- KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes)
- {
- KeyFrameListList inputs;
- inputs.reserve(nodes.size()*3);
-
- BOOST_FOREACH(const AnimationCurveNode* node, nodes) {
- ai_assert(node);
-
- const AnimationCurveMap& curves = node->Curves();
- BOOST_FOREACH(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());
-
- inputs.push_back(boost::make_tuple(&curve->GetKeys(), &curve->GetValues(), mapto));
- }
- }
- return inputs; // pray for NRVO :-)
- }
-
-
- // ------------------------------------------------------------------------------------------------
- KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs)
- {
- ai_assert(inputs.size());
-
- // reserve some space upfront - it is likely that the keyframe lists
- // have matching time values, so max(of all keyframe lists) should
- // be a good estimate.
- KeyTimeList keys;
-
- size_t estimate = 0;
- BOOST_FOREACH(const KeyFrameList& kfl, inputs) {
- estimate = std::max(estimate, kfl.get<0>()->size());
- }
-
- keys.reserve(estimate);
-
- std::vector<unsigned int> next_pos;
- next_pos.resize(inputs.size(),0);
-
- const size_t count = inputs.size();
- while(true) {
-
- uint64_t min_tick = std::numeric_limits<uint64_t>::max();
- for (size_t i = 0; i < count; ++i) {
- const KeyFrameList& kfl = inputs[i];
-
- if (kfl.get<0>()->size() > next_pos[i] && kfl.get<0>()->at(next_pos[i]) < min_tick) {
- min_tick = kfl.get<0>()->at(next_pos[i]);
- }
- }
-
- if (min_tick == std::numeric_limits<uint64_t>::max()) {
- break;
- }
- keys.push_back(min_tick);
-
- for (size_t i = 0; i < count; ++i) {
- const KeyFrameList& kfl = inputs[i];
-
-
- while(kfl.get<0>()->size() > next_pos[i] && kfl.get<0>()->at(next_pos[i]) == min_tick) {
- ++next_pos[i];
- }
- }
- }
-
- return keys;
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void InterpolateKeys(aiVectorKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs,
- const bool geom,
- double& max_time,
- double& min_time)
-
- {
- ai_assert(keys.size());
- ai_assert(valOut);
-
- std::vector<unsigned int> next_pos;
- const size_t count = inputs.size();
-
- next_pos.resize(inputs.size(),0);
-
- BOOST_FOREACH(KeyTimeList::value_type time, keys) {
- float result[3] = {0.0f, 0.0f, 0.0f};
- if(geom) {
- result[0] = result[1] = result[2] = 1.0f;
- }
-
- for (size_t i = 0; i < count; ++i) {
- const KeyFrameList& kfl = inputs[i];
-
- const size_t ksize = kfl.get<0>()->size();
- if (ksize > next_pos[i] && kfl.get<0>()->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 = kfl.get<1>()->at(id0);
- const KeyValueList::value_type valueB = kfl.get<1>()->at(id1);
-
- const KeyTimeList::value_type timeA = kfl.get<0>()->at(id0);
- const KeyTimeList::value_type timeB = kfl.get<0>()->at(id1);
-
- // do the actual interpolation in double-precision arithmetics
- // because it is a bit sensitive to rounding errors.
- const double factor = timeB == timeA ? 0. : static_cast<double>((time - timeA) / (timeB - timeA));
- const float interpValue = static_cast<float>(valueA + (valueB - valueA) * factor);
-
- if(geom) {
- result[kfl.get<2>()] *= interpValue;
- }
- else {
- result[kfl.get<2>()] += 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 InterpolateKeys(aiQuatKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs,
- const bool geom,
- double& maxTime,
- double& minTime,
- Model::RotOrder order)
- {
- ai_assert(keys.size());
- ai_assert(valOut);
-
- boost::scoped_array<aiVectorKey> temp(new aiVectorKey[keys.size()]);
- InterpolateKeys(temp.get(),keys,inputs,geom,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 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 aiQuaternion& def_rotation)
- {
- if (rotation.size()) {
- InterpolateKeys(out_quat, times, rotation, false, 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 = def_rotation;
- }
- }
-
- if (scaling.size()) {
- InterpolateKeys(out_scale, times, scaling, true, 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, false, 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);
- }
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // euler xyz -> quat
- aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order)
- {
- aiMatrix4x4 m;
- GetRotationMatrix(order, rot, m);
-
- return aiQuaternion(aiMatrix3x3(m));
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers,
- 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);
- const KeyTimeList& keys = GetKeyTimeList(inputs);
-
- na->mNumScalingKeys = static_cast<unsigned int>(keys.size());
- na->mScalingKeys = new aiVectorKey[keys.size()];
- InterpolateKeys(na->mScalingKeys, keys, inputs, true, maxTime, minTime);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
- const LayerMap& layers,
- double& maxTime,
- double& minTime)
- {
- ai_assert(nodes.size());
-
- // XXX see notes in ConvertScaleKeys()
- const KeyFrameListList& inputs = GetKeyframeList(nodes);
- const KeyTimeList& keys = GetKeyTimeList(inputs);
-
- na->mNumPositionKeys = static_cast<unsigned int>(keys.size());
- na->mPositionKeys = new aiVectorKey[keys.size()];
- InterpolateKeys(na->mPositionKeys, keys, inputs, false, maxTime, minTime);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
- const LayerMap& layers,
- double& maxTime,
- double& minTime,
- Model::RotOrder order)
- {
- ai_assert(nodes.size());
-
- // XXX see notes in ConvertScaleKeys()
- const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes);
- const KeyTimeList& keys = GetKeyTimeList(inputs);
-
- na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
- na->mRotationKeys = new aiQuatKey[keys.size()];
- InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime, order);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // copy generated meshes, animations, lights, cameras and textures to the output scene
- void TransferDataToScene()
- {
- ai_assert(!out->mMeshes && !out->mNumMeshes);
+ if ( node->TargetProperty().empty() ) {
+ FBXImporter::LogWarn( "target property for animation curve not set: " + node->Name() );
+ continue;
+ }
- // note: the trailing () ensures initialization with NULL - not
- // many C++ users seem to know this, so pointing it out to avoid
- // confusion why this code works.
+ curve_node = node;
+ if ( node->Curves().empty() ) {
+ FBXImporter::LogWarn( "no animation curves assigned to AnimationCurveNode: " + node->Name() );
+ continue;
+ }
- if(meshes.size()) {
- out->mMeshes = new aiMesh*[meshes.size()]();
- out->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ node_property_map[ node->TargetProperty() ].push_back( node );
+ }
- std::swap_ranges(meshes.begin(),meshes.end(),out->mMeshes);
- }
+ ai_assert( curve_node );
+ ai_assert( curve_node->TargetAsModel() );
- if(materials.size()) {
- out->mMaterials = new aiMaterial*[materials.size()]();
- out->mNumMaterials = static_cast<unsigned int>(materials.size());
+ const Model& target = *curve_node->TargetAsModel();
- std::swap_ranges(materials.begin(),materials.end(),out->mMaterials);
- }
+ // check for all possible transformation components
+ NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ];
- if(animations.size()) {
- out->mAnimations = new aiAnimation*[animations.size()]();
- out->mNumAnimations = static_cast<unsigned int>(animations.size());
+ bool has_any = false;
+ bool has_complex = false;
- std::swap_ranges(animations.begin(),animations.end(),out->mAnimations);
- }
+ for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) {
+ const TransformationComp comp = static_cast<TransformationComp>( i );
- if(lights.size()) {
- out->mLights = new aiLight*[lights.size()]();
- out->mNumLights = static_cast<unsigned int>(lights.size());
+ // 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;
+ }
- std::swap_ranges(lights.begin(),lights.end(),out->mLights);
- }
+ chain[ i ] = node_property_map.find( NameTransformationCompProperty( comp ) );
+ if ( chain[ i ] != node_property_map.end() ) {
- if(cameras.size()) {
- out->mCameras = new aiCamera*[cameras.size()]();
- out->mNumCameras = static_cast<unsigned int>(cameras.size());
+ // 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 ) ) {
- std::swap_ranges(cameras.begin(),cameras.end(),out->mCameras);
- }
- }
+ FBXImporter::LogDebug( "dropping redundant animation channel for node " + target.Name() );
+ continue;
+ }
+ has_any = true;
-private:
+ if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation &&
+ comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation )
+ {
+ 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;
+ }
+ }
- // 0: not assigned yet, others: index is value - 1
- unsigned int defaultMaterialIndex;
+ node_anim_chain_bits[ fixed_name ] = flags;
+}
- std::vector<aiMesh*> meshes;
- std::vector<aiMaterial*> materials;
- std::vector<aiAnimation*> animations;
- std::vector<aiLight*> lights;
- std::vector<aiCamera*> cameras;
+bool Converter::IsRedundantAnimationData( const Model& target,
+ TransformationComp comp,
+ const std::vector<const AnimationCurveNode*>& curves )
+{
+ ai_assert( curves.size() );
- typedef std::map<const Material*, unsigned int> MaterialMap;
- MaterialMap materials_converted;
+ // 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.
- typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
- MeshMap meshes_converted;
+ if ( curves.size() > 1 ) {
+ return false;
+ }
- // fixed node name -> which trafo chain components have animations?
- typedef std::map<std::string, unsigned int> NodeAnimBitMap;
- NodeAnimBitMap node_anim_chain_bits;
+ const AnimationCurveNode& nd = *curves.front();
+ const AnimationCurveMap& sub_curves = nd.Curves();
- // name -> has had its prefix_stripped?
- typedef std::map<std::string, bool> NodeNameMap;
- NodeNameMap node_names;
+ 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" );
- typedef std::map<std::string, std::string> NameNameMap;
- NameNameMap renamed_nodes;
+ if ( dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end() ) {
+ return false;
+ }
- double anim_fps;
+ const KeyValueList& vx = ( *dx ).second->GetValues();
+ const KeyValueList& vy = ( *dy ).second->GetValues();
+ const KeyValueList& vz = ( *dz ).second->GetValues();
- aiScene* const out;
- const FBX::Document& doc;
-};
+ 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 = 1e-6f;
+ return ( dyn_val - static_val ).SquareLength() < epsilon;
+}
+
+
+aiNodeAnim* Converter::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 )
+{
+ ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ na->mNodeName.Set( name );
+
+ ConvertRotationKeys( na, 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.dismiss();
+}
+
+aiNodeAnim* Converter::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 )
+{
+ ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ na->mNodeName.Set( name );
+
+ ConvertScaleKeys( na, 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.dismiss();
+}
+
+
+aiNodeAnim* Converter::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 )
+{
+ ScopeGuard<aiNodeAnim> na( new aiNodeAnim() );
+ na->mNodeName.Set( name );
+
+ ConvertTranslationKeys( na, 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.dismiss();
+}
+
+aiNodeAnim* Converter::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 )
+
+{
+ ScopeGuard<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, ( *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, ( *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, ( *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.dismiss();
+}
+
+Converter::KeyFrameListList Converter::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 int count = curve->GetKeys().size();
+ Keys->reserve( count );
+ Values->reserve( count );
+ for ( int 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 Converter::GetKeyTimeList( const KeyFrameListList& inputs )
+{
+ ai_assert( inputs.size() );
+
+ // reserve some space upfront - it is likely that the keyframe lists
+ // have matching time values, so max(of all keyframe 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 Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& max_time,
+ double& min_time )
+
+{
+ ai_assert( keys.size() );
+ ai_assert( 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 ) {
+ float 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 > 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 );
+
+ // do the actual interpolation in double-precision arithmetics
+ // because it is a bit sensitive to rounding errors.
+ const double factor = timeB == timeA ? 0. : static_cast<double>( ( time - timeA ) / ( timeB - timeA ) );
+ const float interpValue = static_cast<float>( 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 Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
+ const aiVector3D& def_value,
+ double& maxTime,
+ double& minTime,
+ Model::RotOrder order )
+{
+ ai_assert( keys.size() );
+ ai_assert( 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 Converter::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 Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
+{
+ aiMatrix4x4 m;
+ GetRotationMatrix( order, rot, m );
+
+ return aiQuaternion( aiMatrix3x3( m ) );
+}
+
+
+void Converter::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 Converter::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 Converter::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.size() > 0 )
+ InterpolateKeys( na->mRotationKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime, order );
+}
+
+void Converter::TransferDataToScene()
+{
+ ai_assert( !out->mMeshes && !out->mNumMeshes );
+
+ // note: the trailing () ensures initialization with NULL - 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 );
+ }
+}
//} // !anon
// ------------------------------------------------------------------------------------------------
void ConvertToAssimpScene(aiScene* out, const Document& doc)
{
- Converter converter(out,doc);
+ Converter converter(out,doc);
}
} // !FBX
diff --git a/src/3rdparty/assimp/code/FBXConverter.h b/src/3rdparty/assimp/code/FBXConverter.h
index 0585bf5cf..ddbbbbf25 100644
--- a/src/3rdparty/assimp/code/FBXConverter.h
+++ b/src/3rdparty/assimp/code/FBXConverter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,20 +44,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_CONVERTER_H
#define INCLUDED_AI_FBX_CONVERTER_H
+struct aiScene;
+
namespace Assimp {
namespace FBX {
- class Document;
-
+class Document;
-/** Convert a FBX #Document to #aiScene
+/**
+ * Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated
- * @param doc Parsed FBX document */
+ * @param doc Parsed FBX document
+ */
void ConvertToAssimpScene(aiScene* out, const Document& doc);
-
}
}
-
-#endif
+#endif // INCLUDED_AI_FBX_CONVERTER_H
diff --git a/src/3rdparty/assimp/code/FBXDeformer.cpp b/src/3rdparty/assimp/code/FBXDeformer.cpp
index 22e8aa25b..47db96563 100644
--- a/src/3rdparty/assimp/code/FBXDeformer.cpp
+++ b/src/3rdparty/assimp/code/FBXDeformer.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXNoteAttribute.cpp
* @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -55,16 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
+ using namespace Util;
// ------------------------------------------------------------------------------------------------
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
- : Object(id,element,name)
+ : Object(id,element,name)
{
- const Scope& sc = GetRequiredScope(element);
+ const Scope& sc = GetRequiredScope(element);
- const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
- props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
+ const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+ props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
}
@@ -80,44 +79,44 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const
: 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");
- BOOST_FOREACH(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);
- }
+ 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);
+ }
}
@@ -131,26 +130,26 @@ Cluster::~Cluster()
// ------------------------------------------------------------------------------------------------
Skin::Skin(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 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());
- BOOST_FOREACH(const Connection* con, conns) {
-
- const Cluster* const cluster = ProcessSimpleConnection<Cluster>(*con, false, "Cluster -> Skin", element);
- if(cluster) {
- clusters.push_back(cluster);
- continue;
- }
- }
+, 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;
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/FBXDocument.cpp b/src/3rdparty/assimp/code/FBXDocument.cpp
index 404a8d6e2..cf5f6da86 100644
--- a/src/3rdparty/assimp/code/FBXDocument.cpp
+++ b/src/3rdparty/assimp/code/FBXDocument.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,20 +41,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXDocument.cpp
* @brief Implementation of the FBX DOM classes
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
-#include <functional>
-
-#include "FBXParser.h"
#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>
+
+
namespace Assimp {
namespace FBX {
@@ -77,143 +79,156 @@ LazyObject::~LazyObject()
}
// ------------------------------------------------------------------------------------------------
+static void dumpObjectClassInfo( const char* obtype, const std::string &classtag ) {
+ DefaultLogger::get()->debug( "obtype: " + std::string(obtype ));
+ DefaultLogger::get()->debug( "Classtag: " + classtag );
+}
+
+// ------------------------------------------------------------------------------------------------
const Object* LazyObject::Get(bool dieOnError)
{
- if(IsBeingConstructed() || FailedToConstruct()) {
- return NULL;
- }
-
- if (object.get()) {
- return object.get();
- }
-
- // if this is the root object, we return a dummy since there
- // is no root object int he fbx file - it is just referenced
- // with id 0.
- if(id == 0L) {
- object.reset(new Object(id, element, "Model::RootNode"));
- 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());
- if (!strncmp(obtype,"Geometry",length)) {
- if (!strcmp(classtag.c_str(),"Mesh")) {
- object.reset(new MeshGeometry(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 (!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,"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()) {
- DefaultLogger::get()->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();
+ if(IsBeingConstructed() || FailedToConstruct()) {
+ return NULL;
+ }
+
+ if (object.get()) {
+ return object.get();
+ }
+
+ // if this is the root object, we return a dummy since there
+ // is no root object int he fbx file - it is just referenced
+ // with id 0.
+ if(id == 0L) {
+ object.reset(new Object(id, element, "Model::RootNode"));
+ 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));
+ }
+ }
+ 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 ( !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()) {
+ DefaultLogger::get()->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();
}
// ------------------------------------------------------------------------------------------------
@@ -233,9 +248,9 @@ Object::~Object()
// ------------------------------------------------------------------------------------------------
-FileGlobalSettings::FileGlobalSettings(const Document& doc, boost::shared_ptr<const PropertyTable> props)
+FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
: props(props)
-, doc(doc)
+, doc(doc)
{
}
@@ -253,209 +268,215 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings)
, parser(parser)
{
- // cannot use array default initialization syntax because vc8 fails on it
- for (unsigned int i = 0; i < 7; ++i) {
- creationTimeStamp[i] = 0;
- }
+ // Cannot use array default initialization syntax because vc8 fails on it
+ for (auto &timeStamp : creationTimeStamp) {
+ timeStamp = 0;
+ }
- ReadHeader();
- ReadPropertyTemplates();
+ ReadHeader();
+ ReadPropertyTemplates();
- ReadGlobalSettings();
+ 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();
+ // 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()
{
- BOOST_FOREACH(ObjectMap::value_type& v, objects) {
- delete v.second;
- }
+ 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 int LowerSupportedVersion = 7100;
+static const 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 maye have some success with newer files, we don't support
- // the older 6.n fbx format
- if(fbxVersion < 7100) {
- DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
- }
- if(fbxVersion > 7300) {
- 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));
- }
+ // 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 maye 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(!ehead || !ehead->Compound()) {
- DOMWarning("no GlobalSettings dictionary found");
+ const Scope& sc = parser.GetRootScope();
+ const Element* const ehead = sc["GlobalSettings"];
+ if(!ehead || !ehead->Compound()) {
+ DOMWarning("no GlobalSettings dictionary found");
- globals.reset(new FileGlobalSettings(*this, boost::make_shared<const PropertyTable>()));
- return;
- }
+ globals.reset(new FileGlobalSettings(*this, std::make_shared<const PropertyTable>()));
+ return;
+ }
- boost::shared_ptr<const PropertyTable> props = GetPropertyTable(*this, "", *ehead, *ehead->Compound(), true);
+ std::shared_ptr<const PropertyTable> props = GetPropertyTable(*this, "", *ehead, *ehead->Compound(), true);
- if(!props) {
- DOMError("GlobalSettings dictionary contains no property table");
- }
+ if(!props) {
+ DOMError("GlobalSettings dictionary contains no property table");
+ }
- globals.reset(new FileGlobalSettings(*this, props));
+ 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();
- BOOST_FOREACH(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);
- }
- }
+ // 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) {
- boost::shared_ptr<const PropertyTable> props = boost::make_shared<const PropertyTable>(
- *Properties70,boost::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
- );
-
- templates[oname+"."+pname] = props;
- }
- }
- }
+ 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;
+ }
+ }
+ }
}
@@ -463,202 +484,207 @@ void Document::ReadPropertyTemplates()
// ------------------------------------------------------------------------------------------------
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));
- 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 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.size()) {
- return animationStacksResolved;
- }
-
- animationStacksResolved.reserve(animationStacks.size());
- BOOST_FOREACH(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;
+ if (!animationStacksResolved.empty() || !animationStacks.size()) {
+ 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() ? NULL : (*it).second;
+ ObjectMap::const_iterator it = objects.find(id);
+ return it == objects.end() ? NULL : (*it).second;
}
#define MAX_CLASSNAMES 6
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
- const ConnectionMap& conns) const
+std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
+ const ConnectionMap& conns) const
{
- std::vector<const Connection*> temp;
+ std::vector<const Connection*> temp;
- const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
- conns.equal_range(id);
+ 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);
- }
+ 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_fun(&Connection::Compare));
+ std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
- return temp; // NRVO should handle this
+ 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
+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 && count <= MAX_CLASSNAMES);
+ ai_assert(classnames);
+ ai_assert(count != 0 && count <= MAX_CLASSNAMES);
- size_t lenghts[MAX_CLASSNAMES];
+ size_t lenghts[MAX_CLASSNAMES];
- const size_t c = count;
- for (size_t i = 0; i < c; ++i) {
- lenghts[i] = strlen(classnames[i]);
- }
+ const size_t c = count;
+ for (size_t i = 0; i < c; ++i) {
+ lenghts[i] = strlen(classnames[i]);
+ }
- std::vector<const Connection*> temp;
+ std::vector<const Connection*> temp;
- const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
- conns.equal_range(id);
+ 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();
+ 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();
+ 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())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
- obtype = NULL;
- break;
- }
- }
+ for (size_t i = 0; i < c; ++i) {
+ ai_assert(classnames[i]);
+ if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
+ obtype = NULL;
+ break;
+ }
+ }
- if(obtype) {
- continue;
- }
+ if(obtype) {
+ continue;
+ }
- temp.push_back((*it).second);
- }
+ temp.push_back((*it).second);
+ }
- std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
- return temp; // NRVO should handle this
+ std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare));
+ return temp; // NRVO should handle this
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{
- return GetConnectionsSequenced(source, ConnectionsBySource());
+ return GetConnectionsSequenced(source, ConnectionsBySource());
}
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest,
- const char* classname) const
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest,
+ const char* classname) const
{
- const char* arr[] = {classname};
- return GetConnectionsBySourceSequenced(dest, arr,1);
+ const char* arr[] = {classname};
+ return GetConnectionsBySourceSequenced(dest, arr,1);
}
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
- const char* const* classnames, size_t count) const
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
+ const char* const* classnames, size_t count) const
{
- return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
+ return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
}
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
- const char* classname) const
+std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char* classname) const
{
- const char* arr[] = {classname};
- return GetConnectionsByDestinationSequenced(dest, arr,1);
+ const char* arr[] = {classname};
+ return GetConnectionsByDestinationSequenced(dest, arr,1);
}
// ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
{
- return GetConnectionsSequenced(dest, ConnectionsByDestination());
+ return GetConnectionsSequenced(dest, ConnectionsByDestination());
}
// ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
- const char* const* classnames, size_t count) const
+std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
+ const char* const* classnames, size_t count) const
{
- return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
+ 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)
+Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
+ const Document& doc)
: insertionOrder(insertionOrder)
, prop(prop)
@@ -666,9 +692,9 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co
, 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());
+ 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());
}
@@ -682,36 +708,36 @@ Connection::~Connection()
// ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazySourceObject() const
{
- LazyObject* const lazy = doc.GetObject(src);
- ai_assert(lazy);
- return *lazy;
+ 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;
+ 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();
+ 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();
+ LazyObject* const lazy = doc.GetObject(dest);
+ ai_assert(lazy);
+ return lazy->Get();
}
} // !FBX
diff --git a/src/3rdparty/assimp/code/FBXDocument.h b/src/3rdparty/assimp/code/FBXDocument.h
index 9dd5c79dd..62d463bab 100644
--- a/src/3rdparty/assimp/code/FBXDocument.h
+++ b/src/3rdparty/assimp/code/FBXDocument.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,31 +44,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_DOCUMENT_H
#define INCLUDED_AI_FBX_DOCUMENT_H
-#include <vector>
-#include <map>
-#include <string>
-
+#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 Parser;
+class Object;
+struct ImportSettings;
+
+class PropertyTable;
+class Document;
+class Material;
+class Geometry;
- class PropertyTable;
- class Document;
- class Material;
- class Geometry;
+class Video;
- class AnimationCurve;
- class AnimationCurveNode;
- class AnimationLayer;
- class AnimationStack;
+class AnimationCurve;
+class AnimationCurveNode;
+class AnimationLayer;
+class AnimationStack;
- class Skin;
- class Cluster;
+class Skin;
+class Cluster;
/** Represents a delay-parsed FBX objects. Many objects in the scene
@@ -77,54 +82,52 @@ namespace FBX {
class LazyObject
{
public:
-
- LazyObject(uint64_t id, const Element& element, const Document& doc);
- ~LazyObject();
+ LazyObject(uint64_t id, const Element& element, const Document& doc);
+ ~LazyObject();
public:
- const Object* Get(bool dieOnError = false);
+ 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;
- }
+ 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;
- }
+ uint64_t ID() const {
+ return id;
+ }
- bool IsBeingConstructed() const {
- return (flags & BEING_CONSTRUCTED) != 0;
- }
+ bool IsBeingConstructed() const {
+ return (flags & BEING_CONSTRUCTED) != 0;
+ }
- bool FailedToConstruct() const {
- return (flags & FAILED_TO_CONSTRUCT) != 0;
- }
+ bool FailedToConstruct() const {
+ return (flags & FAILED_TO_CONSTRUCT) != 0;
+ }
- const Element& GetElement() const {
- return element;
- }
+ const Element& GetElement() const {
+ return element;
+ }
- const Document& GetDocument() const {
- return doc;
- }
+ const Document& GetDocument() const {
+ return doc;
+ }
private:
+ const Document& doc;
+ const Element& element;
+ std::unique_ptr<const Object> object;
- const Document& doc;
- const Element& element;
- boost::scoped_ptr<const Object> object;
-
- const uint64_t id;
+ const uint64_t id;
- enum Flags {
- BEING_CONSTRUCTED = 0x1,
- FAILED_TO_CONSTRUCT = 0x2
- };
+ enum Flags {
+ BEING_CONSTRUCTED = 0x1,
+ FAILED_TO_CONSTRUCT = 0x2
+ };
- unsigned int flags;
+ unsigned int flags;
};
@@ -133,28 +136,26 @@ private:
class Object
{
public:
+ Object(uint64_t id, const Element& element, const std::string& name);
- Object(uint64_t id, const Element& element, const std::string& name);
- virtual ~Object();
+ virtual ~Object();
-public:
-
- const Element& SourceElement() const {
- return element;
- }
+ const Element& SourceElement() const {
+ return element;
+ }
- const std::string& Name() const {
- return name;
- }
+ const std::string& Name() const {
+ return name;
+ }
- uint64_t ID() const {
- return id;
- }
+ uint64_t ID() const {
+ return id;
+ }
protected:
- const Element& element;
- const std::string name;
- const uint64_t id;
+ const Element& element;
+ const std::string name;
+ const uint64_t id;
};
@@ -164,20 +165,16 @@ protected:
class NodeAttribute : public Object
{
public:
+ NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~NodeAttribute();
- NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~NodeAttribute();
-
-public:
-
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
private:
-
- boost::shared_ptr<const PropertyTable> props;
+ std::shared_ptr<const PropertyTable> props;
};
@@ -185,79 +182,69 @@ private:
class CameraSwitcher : public NodeAttribute
{
public:
+ CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~CameraSwitcher();
- CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~CameraSwitcher();
-
-public:
-
- int CameraID() const {
- return cameraId;
- }
-
- const std::string& CameraName() const {
- return cameraName;
- }
+ int CameraID() const {
+ return cameraId;
+ }
+ const std::string& CameraName() const {
+ return cameraName;
+ }
- const std::string& CameraIndexName() const {
- return cameraIndexName;
- }
+ const std::string& CameraIndexName() const {
+ return cameraIndexName;
+ }
private:
-
- int cameraId;
- std::string cameraName;
- std::string cameraIndexName;
+ 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)); \
- }
+ 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); \
+ 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);
- ~Camera();
+ Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Camera();
public:
+ 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(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(FilmAspectRatio, float, 1.0f);
- fbx_simple_property(ApertureMode, int, 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(FieldOfView, float, 1.0f);
- fbx_simple_property(FocalLength, float, 1.0f);
+ fbx_simple_property(FilmAspectRatio, float, 1.0f)
+ fbx_simple_property(ApertureMode, int, 0)
-private:
+ fbx_simple_property(FieldOfView, float, 1.0f)
+ fbx_simple_property(FocalLength, float, 1.0f)
};
@@ -265,9 +252,8 @@ private:
class Null : public NodeAttribute
{
public:
-
- Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Null();
+ Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Null();
};
@@ -275,9 +261,8 @@ public:
class LimbNode : public NodeAttribute
{
public:
-
- LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~LimbNode();
+ LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~LimbNode();
};
@@ -285,69 +270,63 @@ public:
class Light : public NodeAttribute
{
public:
-
- Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Light();
+ Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Light();
public:
-
- 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
- };
+ 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
+ };
public:
-
- 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, 1.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, 0);
- fbx_simple_property(DecayStart, int, 0);
- 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);
-
-
-private:
+ 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, 1.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, 0)
+ fbx_simple_property(DecayStart, int, 0)
+ 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)
};
@@ -355,563 +334,415 @@ private:
class Model : public Object
{
public:
-
- Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Model();
+ Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Model();
public:
+ enum RotOrder
+ {
+ RotOrder_EulerXYZ = 0,
+ RotOrder_EulerXZY,
+ RotOrder_EulerYZX,
+ RotOrder_EulerYXZ,
+ RotOrder_EulerZXY,
+ RotOrder_EulerZYX,
- enum RotOrder
- {
- RotOrder_EulerXYZ = 0,
- RotOrder_EulerXZY,
- RotOrder_EulerYZX,
- RotOrder_EulerYXZ,
- RotOrder_EulerZXY,
- RotOrder_EulerZYX,
-
- RotOrder_SphericXYZ,
+ RotOrder_SphericXYZ,
- RotOrder_MAX // end-of-enum sentinel
- };
+ RotOrder_MAX // end-of-enum sentinel
+ };
- enum TransformInheritance
- {
- TransformInheritance_RrSs = 0,
- TransformInheritance_RSrs,
- TransformInheritance_Rrs,
+ enum TransformInheritance
+ {
+ TransformInheritance_RrSs = 0,
+ TransformInheritance_RSrs,
+ TransformInheritance_Rrs,
- TransformInheritance_MAX // end-of-enum sentinel
- };
+ TransformInheritance_MAX // end-of-enum sentinel
+ };
public:
-
- 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);
+ 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)
public:
+ const std::string& Shading() const {
+ return shading;
+ }
- const std::string& Shading() const {
- return shading;
- }
-
- const std::string& Culling() const {
- return culling;
- }
+ const std::string& Culling() const {
+ return culling;
+ }
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- /** Get material links */
- const std::vector<const Material*>& GetMaterials() const {
- return materials;
- }
+ /** 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 geometry links */
+ const std::vector<const Geometry*>& GetGeometry() const {
+ return geometry;
+ }
- /** Get node attachments */
- const std::vector<const NodeAttribute*>& GetAttributes() const {
- return attributes;
- }
+ /** Get node attachments */
+ const std::vector<const NodeAttribute*>& GetAttributes() const {
+ return attributes;
+ }
-public:
-
- /** convenience method to check if the node has a Null node marker */
- bool IsNull() const;
+ /** convenience method to check if the node has a Null node marker */
+ bool IsNull() const;
private:
-
- void ResolveLinks(const Element& element, const Document& doc);
+ 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::vector<const Material*> materials;
- std::vector<const Geometry*> geometry;
- std::vector<const NodeAttribute*> attributes;
-
- std::string shading;
- std::string culling;
- boost::shared_ptr<const PropertyTable> props;
+ 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);
- ~Texture();
+ Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Texture();
public:
+ const std::string& Type() const {
+ return type;
+ }
- const std::string& Type() const {
- return type;
- }
+ const std::string& FileName() const {
+ return fileName;
+ }
- const std::string& FileName() const {
- return fileName;
- }
+ const std::string& RelativeFilename() const {
+ return relativeFileName;
+ }
- const std::string& RelativeFilename() const {
- return relativeFileName;
- }
+ const std::string& AlphaSource() const {
+ return alphaSource;
+ }
- const std::string& AlphaSource() const {
- return alphaSource;
- }
+ const aiVector2D& UVTranslation() const {
+ return uvTrans;
+ }
- const aiVector2D& UVTranslation() const {
- return uvTrans;
- }
+ const aiVector2D& UVScaling() const {
+ return uvScaling;
+ }
- const aiVector2D& UVScaling() const {
- return uvScaling;
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ // return a 4-tuple
+ const unsigned int* Crop() const {
+ return crop;
+ }
- // return a 4-tuple
- const unsigned int* Crop() const {
- return crop;
- }
+ const Video* Media() const {
+ return media;
+ }
private:
+ aiVector2D uvTrans;
+ aiVector2D uvScaling;
- aiVector2D uvTrans;
- aiVector2D uvScaling;
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ std::string alphaSource;
+ std::shared_ptr<const PropertyTable> props;
- std::string type;
- std::string relativeFileName;
- std::string fileName;
- std::string alphaSource;
- boost::shared_ptr<const PropertyTable> props;
+ unsigned int crop[4];
- 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() const
+ {
+ return texture;
+ }
+
+ BlendMode GetBlendMode()
+ {
+ return blendMode;
+ }
+
+ float Alpha()
+ {
+ return alpha;
+ }
- LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~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() const
- {
- return texture;
- }
- BlendMode GetBlendMode()
- {
- return blendMode;
- }
- float Alpha()
- {
- return alpha;
- }
private:
- const Texture* texture;
- BlendMode blendMode;
- float alpha;
+ const Texture* texture;
+ 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 materials */
-class Material : public Object
+/** DOM class for generic FBX videos */
+class Video : public Object
{
public:
-
- Material(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Material();
+ Video(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Video();
public:
-
- 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;
- }
+ 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;
+ }
+
+ const uint32_t ContentLength() const {
+ return contentLength;
+ }
+
+ uint8_t* RelinquishContent() {
+ uint8_t* ptr = content;
+ content = 0;
+ return ptr;
+ }
private:
+ std::string type;
+ std::string relativeFileName;
+ std::string fileName;
+ std::shared_ptr<const PropertyTable> props;
- std::string shading;
- bool multilayer;
- boost::shared_ptr<const PropertyTable> props;
-
- TextureMap textures;
- LayeredTextureMap layeredTextures;
+ uint32_t contentLength;
+ uint8_t* content;
};
-
-/** 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);
- ~Geometry();
-
-public:
-
- /** Get the Skin attached to this geometry or NULL */
- const Skin* const DeformerSkin() const {
- return skin;
- }
-
-private:
-
- const Skin* skin;
-};
-
-
-typedef std::vector<int> MatIndexArray;
-
-
-/** DOM class for FBX geometry of type "Mesh"*/
-class MeshGeometry : public Geometry
+/** 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();
- MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
- ~MeshGeometry();
-
-public:
-
- /** Get a list of all vertex points, non-unique*/
- const std::vector<aiVector3D>& GetVertices() const {
- return vertices;
- }
-
- /** Get a list of all vertex normals or an empty array if
- * no normals are specified. */
- const std::vector<aiVector3D>& GetNormals() const {
- return normals;
- }
-
- /** Get a list of all vertex tangents or an empty array
- * if no tangents are specified */
- const std::vector<aiVector3D>& GetTangents() const {
- return tangents;
- }
-
- /** Get a list of all vertex binormals or an empty array
- * if no binormals are specified */
- const std::vector<aiVector3D>& GetBinormals() const {
- return binormals;
- }
-
- /** 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 {
- return faces;
- }
-
- /** 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 {
- static const std::vector<aiVector2D> empty;
- return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[index];
- }
-
-
- /** Get a UV coordinate slot, returns an empty array if
- * the requested slot does not exist. */
- std::string GetTextureCoordChannelName(unsigned int index) const {
- return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : uvNames[index];
- }
-
- /** 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 {
- static const std::vector<aiColor4D> empty;
- return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : colors[index];
- }
-
-
- /** Get per-face-vertex material assignments */
- const MatIndexArray& GetMaterialIndices() const {
- return materials;
- }
-
-
- /** 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 {
- if(in_index >= mapping_counts.size()) {
- return NULL;
- }
-
- ai_assert(mapping_counts.size() == mapping_offsets.size());
- count = mapping_counts[in_index];
-
- ai_assert(count != 0);
- ai_assert(mapping_offsets[in_index] + count <= mappings.size());
-
- return &mappings[mapping_offsets[in_index]];
- }
-
-
- /** Determine the face to which a particular output vertex index belongs.
- * This mapping is always unique. */
- unsigned int FaceForVertexIndex(unsigned int in_index) const {
- ai_assert(in_index < 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 (facesVertexStartIndices.empty()) {
- facesVertexStartIndices.resize(faces.size() + 1, 0);
-
- std::partial_sum(faces.begin(), faces.end(), facesVertexStartIndices.begin() + 1);
- facesVertexStartIndices.pop_back();
- }
-
- ai_assert(facesVertexStartIndices.size() == faces.size());
- const std::vector<unsigned int>::iterator it = std::upper_bound(
- facesVertexStartIndices.begin(),
- facesVertexStartIndices.end(),
- in_index
- );
-
- return static_cast<unsigned int>(std::distance(facesVertexStartIndices.begin(), it - 1));
- }
-
-public:
-
-private:
-
- void ReadLayer(const Scope& layer);
- void ReadLayerElement(const Scope& layerElement);
- void ReadVertexData(const std::string& type, int index, const Scope& source);
+ const std::string& GetShadingModel() const {
+ return shading;
+ }
- void ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType);
+ bool IsMultilayer() const {
+ return multilayer;
+ }
- void ReadVertexDataNormals(std::vector<aiVector3D>& normals_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType);
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- void ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType);
+ const TextureMap& Textures() const {
+ return textures;
+ }
- 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);
+ const LayeredTextureMap& LayeredTextures() const {
+ return layeredTextures;
+ }
private:
+ std::string shading;
+ bool multilayer;
+ std::shared_ptr<const PropertyTable> props;
- // cached data arrays
- MatIndexArray materials;
- std::vector<aiVector3D> vertices;
- std::vector<unsigned int> faces;
- mutable std::vector<unsigned int> facesVertexStartIndices;
- std::vector<aiVector3D> tangents;
- std::vector<aiVector3D> binormals;
- std::vector<aiVector3D> normals;
-
- std::string uvNames[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- std::vector<aiVector2D> uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- std::vector<aiColor4D> colors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
- std::vector<unsigned int> mapping_counts;
- std::vector<unsigned int> mapping_offsets;
- std::vector<unsigned int> mappings;
+ TextureMap textures;
+ LayeredTextureMap layeredTextures;
};
-typedef std::vector<uint64_t> KeyTimeList;
+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();
- AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
- ~AnimationCurve();
-
-public:
-
- /** get list of keyframe positions (time).
- * Invariant: |GetKeys()| > 0 */
- const KeyTimeList& GetKeys() const {
- return keys;
- }
+ /** 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;
- }
+ /** 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<float>& GetAttributes() const {
+ return attributes;
+ }
- const std::vector<unsigned int>& GetFlags() const {
- return flags;
- }
+ const std::vector<unsigned int>& GetFlags() const {
+ return flags;
+ }
private:
-
- KeyTimeList keys;
- KeyValueList values;
- std::vector<float> attributes;
- std::vector<unsigned int> flags;
+ KeyTimeList keys;
+ KeyValueList values;
+ std::vector<float> attributes;
+ std::vector<unsigned int> flags;
};
// property-name -> animation curve
@@ -922,53 +753,49 @@ typedef std::map<std::string, const AnimationCurve*> AnimationCurveMap;
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);
- /* the optional whitelist 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);
-
- ~AnimationCurveNode();
-
-public:
+ virtual ~AnimationCurveNode();
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- const AnimationCurveMap& Curves() const;
+ 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;
- }
+ /** 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 Model* TargetAsModel() const {
+ return dynamic_cast<const Model*>(target);
+ }
- const NodeAttribute* TargetAsNodeAttribute() const {
- return dynamic_cast<const NodeAttribute*>(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;
- }
+ /** 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;
- const Object* target;
- boost::shared_ptr<const PropertyTable> props;
- mutable AnimationCurveMap curves;
-
- std::string prop;
- const Document& doc;
+ std::string prop;
+ const Document& doc;
};
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
@@ -978,27 +805,22 @@ typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
class AnimationLayer : public Object
{
public:
+ AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+ virtual ~AnimationLayer();
-
- AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
- ~AnimationLayer();
-
-public:
-
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- /* the optional whitelist 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 = NULL, size_t whitelist_size = 0) const;
+ /* 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 = NULL, size_t whitelist_size = 0) const;
private:
-
- boost::shared_ptr<const PropertyTable> props;
- const Document& doc;
+ std::shared_ptr<const PropertyTable> props;
+ const Document& doc;
};
@@ -1009,33 +831,27 @@ typedef std::vector<const AnimationLayer*> AnimationLayerList;
class AnimationStack : public Object
{
public:
-
- AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
- ~AnimationStack();
+ AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+ virtual ~AnimationStack();
public:
+ 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)
- fbx_simple_property(LocalStart, uint64_t, 0L);
- fbx_simple_property(LocalStop, uint64_t, 0L);
- fbx_simple_property(ReferenceStart, uint64_t, 0L);
- fbx_simple_property(ReferenceStop, uint64_t, 0L);
-
-
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
-
-
- const AnimationLayerList& Layers() const {
- return layers;
- }
+ const AnimationLayerList& Layers() const {
+ return layers;
+ }
private:
-
- boost::shared_ptr<const PropertyTable> props;
- AnimationLayerList layers;
+ std::shared_ptr<const PropertyTable> props;
+ AnimationLayerList layers;
};
@@ -1043,20 +859,16 @@ private:
class Deformer : public Object
{
public:
+ Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+ virtual ~Deformer();
- Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Deformer();
-
-public:
-
- const PropertyTable& Props() const {
- ai_assert(props.get());
- return *props.get();
- }
+ const PropertyTable& Props() const {
+ ai_assert(props.get());
+ return *props.get();
+ }
private:
-
- boost::shared_ptr<const PropertyTable> props;
+ std::shared_ptr<const PropertyTable> props;
};
typedef std::vector<float> WeightArray;
@@ -1067,48 +879,44 @@ typedef std::vector<unsigned int> WeightIndexArray;
class Cluster : public Deformer
{
public:
-
- Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Cluster();
-
-public:
-
- /** 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* const TargetNode() const {
- return node;
- }
+ 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;
- WeightArray weights;
- WeightIndexArray indices;
+ aiMatrix4x4 transform;
+ aiMatrix4x4 transformLink;
- aiMatrix4x4 transform;
- aiMatrix4x4 transformLink;
-
- const Model* node;
+ const Model* node;
};
@@ -1117,93 +925,87 @@ private:
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;
+ }
- Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
- ~Skin();
+ 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();
- float DeformAccuracy() const {
- return accuracy;
- }
+ // 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;
- const std::vector<const Cluster*>& Clusters() const {
- return clusters;
- }
-private:
+ /** 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;
+ }
- float accuracy;
- std::vector<const Cluster*> clusters;
-};
+ uint64_t InsertionOrder() const {
+ return insertionOrder;
+ }
+ int CompareTo(const Connection* c) const {
+ ai_assert( NULL != 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;
+ }
-/** Represents a link between two FBX objects. */
-class Connection
-{
-public:
+ bool Compare(const Connection* c) const {
+ ai_assert( NULL != c );
- 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 {
- // 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 {
- return InsertionOrder() < c->InsertionOrder();
- }
+ return InsertionOrder() < c->InsertionOrder();
+ }
public:
+ uint64_t insertionOrder;
+ const std::string prop;
- uint64_t insertionOrder;
- const std::string prop;
-
- uint64_t src, dest;
- const Document& doc;
+ 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::map<uint64_t, LazyObject*> ObjectMap;
- typedef std::fbx_unordered_map<std::string, boost::shared_ptr<const PropertyTable> > PropertyTemplateMap;
+// 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::map<uint64_t, LazyObject*> ObjectMap;
+typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
- typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
+typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
/** DOM class for global document settings, a single instance per document can
@@ -1211,183 +1013,171 @@ public:
class FileGlobalSettings
{
public:
-
- FileGlobalSettings(const Document& doc, boost::shared_ptr<const PropertyTable> props);
- ~FileGlobalSettings();
-
-public:
-
- 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, double, 1);
- fbx_simple_property(OriginalUnitScaleFactor, double, 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);
-
+ 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, double, 1)
+ fbx_simple_property(OriginalUnitScaleFactor, double, 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:
-
- boost::shared_ptr<const PropertyTable> props;
- const Document& doc;
+ std::shared_ptr<const PropertyTable> props;
+ const Document& doc;
};
/** DOM root for a FBX file */
-class Document
+class Document
{
public:
+ Document(const Parser& parser, const ImportSettings& settings);
+ ~Document();
- Document(const Parser& parser, const ImportSettings& settings);
- ~Document();
+ LazyObject* GetObject(uint64_t id) const;
-public:
-
- LazyObject* GetObject(uint64_t id) const;
+ bool IsBinary() const {
+ return parser.IsBinary();
+ }
- bool IsBinary() const {
- return parser.IsBinary();
- }
+ unsigned int FBXVersion() const {
+ return fbxVersion;
+ }
- unsigned int FBXVersion() const {
- return fbxVersion;
- }
+ const std::string& Creator() const {
+ return creator;
+ }
- const std::string& Creator() const {
- return creator;
- }
+ // elements (in this order): Year, Month, Day, Hour, Second, Millisecond
+ const unsigned int* CreationTimeStamp() const {
+ return creationTimeStamp;
+ }
- // elements (in this order): Uear, Month, Day, Hour, Second, Millisecond
- const unsigned int* CreationTimeStamp() const {
- return creationTimeStamp;
- }
+ const FileGlobalSettings& GlobalSettings() const {
+ ai_assert(globals.get());
+ return *globals.get();
+ }
- const FileGlobalSettings& GlobalSettings() const {
- ai_assert(globals.get());
- return *globals.get();
- }
+ const PropertyTemplateMap& Templates() const {
+ return templates;
+ }
- const PropertyTemplateMap& Templates() const {
- return templates;
- }
+ const ObjectMap& Objects() const {
+ return objects;
+ }
- const ObjectMap& Objects() const {
- return objects;
- }
+ const ImportSettings& Settings() const {
+ return settings;
+ }
- const ImportSettings& Settings() const {
- return settings;
- }
+ const ConnectionMap& ConnectionsBySource() const {
+ return src_connections;
+ }
- const ConnectionMap& ConnectionsBySource() const {
- return src_connections;
- }
+ const ConnectionMap& ConnectionsByDestination() const {
+ return dest_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.
- // 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;
- 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* 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;
- 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;
+ 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;
+ 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;
private:
-
- void ReadHeader();
- void ReadObjects();
- void ReadPropertyTemplates();
- void ReadConnections();
- void ReadGlobalSettings();
+ void ReadHeader();
+ void ReadObjects();
+ void ReadPropertyTemplates();
+ void ReadConnections();
+ void ReadGlobalSettings();
private:
+ const ImportSettings& settings;
- const ImportSettings& settings;
-
- ObjectMap objects;
- const Parser& parser;
+ ObjectMap objects;
+ const Parser& parser;
- PropertyTemplateMap templates;
- ConnectionMap src_connections;
- ConnectionMap dest_connections;
+ PropertyTemplateMap templates;
+ ConnectionMap src_connections;
+ ConnectionMap dest_connections;
- unsigned int fbxVersion;
- std::string creator;
- unsigned int creationTimeStamp[7];
+ unsigned int fbxVersion;
+ std::string creator;
+ unsigned int creationTimeStamp[7];
- std::vector<uint64_t> animationStacks;
- mutable std::vector<const AnimationStack*> animationStacksResolved;
+ std::vector<uint64_t> animationStacks;
+ mutable std::vector<const AnimationStack*> animationStacksResolved;
- boost::scoped_ptr<FileGlobalSettings> globals;
+ std::unique_ptr<FileGlobalSettings> globals;
};
-}
-}
+} // Namespace FBX
+} // Namespace Assimp
-#endif
+#endif // INCLUDED_AI_FBX_DOCUMENT_H
diff --git a/src/3rdparty/assimp/code/FBXDocumentUtil.cpp b/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
index 5efbcb2b7..442c60b5d 100644
--- a/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
+++ b/src/3rdparty/assimp/code/FBXDocumentUtil.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ 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
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -51,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocumentUtil.h"
#include "FBXProperties.h"
+
namespace Assimp {
namespace FBX {
namespace Util {
@@ -59,16 +59,16 @@ 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));
+ 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);
+ if(element) {
+ DOMError(message,element->KeyToken());
+ }
+ throw DeadlyImportError("FBX-DOM " + message);
}
@@ -76,55 +76,55 @@ void DOMError(const std::string& message, const Element* element /*= NULL*/)
// print warning, do return
void DOMWarning(const std::string& message, const Token& token)
{
- if(DefaultLogger::get()) {
- DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token));
- }
+ if(DefaultLogger::get()) {
+ DefaultLogger::get()->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()) {
- DefaultLogger::get()->warn("FBX-DOM: " + message);
- }
+ if(element) {
+ DOMWarning(message,element->KeyToken());
+ return;
+ }
+ if(DefaultLogger::get()) {
+ DefaultLogger::get()->warn("FBX-DOM: " + message);
+ }
}
// ------------------------------------------------------------------------------------------------
-// fetch a property table and the corresponding property template
-boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
- const std::string& templateName,
- const Element &element,
- const Scope& sc,
- bool no_warn /*= false*/)
+// 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"];
- boost::shared_ptr<const PropertyTable> templateProps = boost::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) {
- if(!no_warn) {
- DOMWarning("property table (Properties70) not found",&element);
- }
- if(templateProps) {
- return templateProps;
- }
- else {
- return boost::make_shared<const PropertyTable>();
- }
- }
- return boost::make_shared<const PropertyTable>(*Properties70,templateProps);
+ 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) {
+ 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
diff --git a/src/3rdparty/assimp/code/FBXDocumentUtil.h b/src/3rdparty/assimp/code/FBXDocumentUtil.h
index 6f150b6d5..98fae75ca 100644
--- a/src/3rdparty/assimp/code/FBXDocumentUtil.h
+++ b/src/3rdparty/assimp/code/FBXDocumentUtil.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,6 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_DOCUMENT_UTIL_H
#define INCLUDED_AI_FBX_DOCUMENT_UTIL_H
+#include "../include/assimp/defs.h"
+#include <string>
+#include <memory>
+#include "FBXDocument.h"
+
+struct Token;
+struct Element;
+
namespace Assimp {
namespace FBX {
namespace Util {
@@ -58,52 +66,52 @@ 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
-boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
- const std::string& templateName,
- const Element &element,
- const Scope& sc,
- bool no_warn = false);
+// 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 = NULL)
+inline const T* ProcessSimpleConnection(const Connection& con,
+ bool is_object_property_conn,
+ const char* name,
+ const Element& element,
+ const char** propNameOut = NULL)
{
- if (is_object_property_conn && !con.PropertyName().length()) {
- DOMWarning("expected incoming " + std::string(name) +
- " link to be an object-object connection, ignoring",
- &element
- );
- return NULL;
- }
- 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 NULL;
- }
-
- 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 NULL;
- }
-
- return dynamic_cast<const T*>(ob);
+ if (is_object_property_conn && !con.PropertyName().length()) {
+ DOMWarning("expected incoming " + std::string(name) +
+ " link to be an object-object connection, ignoring",
+ &element
+ );
+ return NULL;
+ }
+ 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 NULL;
+ }
+
+ 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 NULL;
+ }
+
+ return dynamic_cast<const T*>(ob);
}
diff --git a/src/3rdparty/assimp/code/FBXImportSettings.h b/src/3rdparty/assimp/code/FBXImportSettings.h
index 2020273d7..df7cdbd37 100644
--- a/src/3rdparty/assimp/code/FBXImportSettings.h
+++ b/src/3rdparty/assimp/code/FBXImportSettings.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,90 +48,94 @@ namespace Assimp {
namespace FBX {
/** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
-struct ImportSettings
+struct ImportSettings
{
- ImportSettings()
- : strictMode(true)
- , readAllLayers(true)
- , readAllMaterials(false)
- , readMaterials(true)
- , readCameras(true)
- , readLights(true)
- , readAnimations(true)
- , readWeights(true)
- , preservePivots(true)
- , optimizeEmptyAnimationCurves(true)
- {}
-
-
- /** 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 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;
+ ImportSettings()
+ : strictMode(true)
+ , readAllLayers(true)
+ , readAllMaterials(false)
+ , readMaterials(true)
+ , readTextures(true)
+ , readCameras(true)
+ , readLights(true)
+ , readAnimations(true)
+ , readWeights(true)
+ , preservePivots(true)
+ , optimizeEmptyAnimationCurves(true)
+ {}
+
+
+ /** 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;
};
diff --git a/src/3rdparty/assimp/code/FBXImporter.cpp b/src/3rdparty/assimp/code/FBXImporter.cpp
index 56e99063b..b319da8b6 100644
--- a/src/3rdparty/assimp/code/FBXImporter.cpp
+++ b/src/3rdparty/assimp/code/FBXImporter.cpp
@@ -2,17 +2,17 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,13 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXImporter.cpp
* @brief Implementation of the FBX importer.
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include <exception>
#include <iterator>
-#include <boost/tuple/tuple.hpp>
#include "FBXImporter.h"
@@ -59,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
+#include <assimp/Importer.hpp>
namespace Assimp {
- template<> const std::string LogFunctions<FBXImporter>::log_prefix = "FBX: ";
+ template<> const std::string LogFunctions<FBXImporter>::log_prefix = "FBX: ";
}
using namespace Assimp;
@@ -70,52 +69,53 @@ using namespace Assimp::FBX;
namespace {
static const aiImporterDesc desc = {
- "Autodesk FBX Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "fbx"
+ "Autodesk FBX Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "fbx"
};
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by #Importer
FBXImporter::FBXImporter()
-{}
+{
+}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
FBXImporter::~FBXImporter()
{
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// 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 == "fbx") {
- 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;
+ const std::string& extension = GetExtension(pFile);
+ if (extension == "fbx") {
+ 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;
+ return &desc;
}
@@ -123,67 +123,70 @@ const aiImporterDesc* FBXImporter::GetInfo () const
// 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.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.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);
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void FBXImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void FBXImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_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());
-
- stream->Read(&*contents.begin(),contents.size(),1);
- 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);
- }
- catch(std::exception&) {
- std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
- throw;
- }
+ 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);
+
+ 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
diff --git a/src/3rdparty/assimp/code/FBXImporter.h b/src/3rdparty/assimp/code/FBXImporter.h
index 635411397..350ecfb67 100644
--- a/src/3rdparty/assimp/code/FBXImporter.h
+++ b/src/3rdparty/assimp/code/FBXImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,14 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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;
- }
+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.
@@ -67,39 +66,31 @@ namespace Assimp {
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
{
public:
- FBXImporter();
- ~FBXImporter();
+ FBXImporter();
+ virtual ~FBXImporter();
-
-public:
-
- // --------------------
- bool CanRead( const std::string& pFile,
- IOSystem* pIOHandler,
- bool checkSig
- ) const;
+ // --------------------
+ bool CanRead( const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const;
protected:
- // --------------------
- const aiImporterDesc* GetInfo () const;
+ // --------------------
+ const aiImporterDesc* GetInfo () const;
- // --------------------
- void SetupProperties(const Importer* pImp);
+ // --------------------
+ void SetupProperties(const Importer* pImp);
- // --------------------
- void InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler
- );
+ // --------------------
+ void InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ );
private:
-
-
-private:
-
- FBX::ImportSettings settings;
-
+ FBX::ImportSettings settings;
}; // !class FBXImporter
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/FBXMaterial.cpp b/src/3rdparty/assimp/code/FBXMaterial.cpp
index a5e2a1169..43e501d67 100644
--- a/src/3rdparty/assimp/code/FBXMaterial.cpp
+++ b/src/3rdparty/assimp/code/FBXMaterial.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXMaterial.cpp
* @brief Assimp::FBX::Material and Assimp::FBX::Texture implementation
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -51,89 +50,90 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXImportSettings.h"
#include "FBXDocumentUtil.h"
#include "FBXProperties.h"
+#include "ByteSwapper.h"
namespace Assimp {
namespace FBX {
- using namespace Util;
+ 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;
-
- const char* const sh = shading.c_str();
- if(!strcmp(sh,"phong")) {
- templateName = "Material.FbxSurfacePhong";
- }
- else if(!strcmp(sh,"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());
- BOOST_FOREACH(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;
- }
-
- }
+ 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;
+
+ const char* const sh = shading.c_str();
+ if(!strcmp(sh,"phong")) {
+ templateName = "Material.FbxSurfacePhong";
+ }
+ else if(!strcmp(sh,"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;
+ }
+
+ }
}
@@ -147,58 +147,76 @@ 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);
+ 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);
+
+ // 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;
+ }
+ }
+ }
}
@@ -207,26 +225,26 @@ Texture::~Texture()
}
-LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
: Object(id,element,name)
,texture(0)
,blendMode(BlendMode_Modulate)
,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));
- }
+ 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()
@@ -236,21 +254,83 @@ 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 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 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);
+ const Texture* const tex = dynamic_cast<const Texture*>(ob);
- texture = tex;
- }
+ texture = 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["FileName"];
+ 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) {
+ const Token& token = GetRequiredToken(*Content, 0);
+ const char* data = token.begin();
+ if(!token.IsBinary()) {
+ DOMWarning("video content is not binary data, ignoring", &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);
+ }
+ }
+
+ props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
+}
+
+
+Video::~Video()
+{
+ if(content) {
+ delete[] content;
+ }
}
} //!FBX
diff --git a/src/3rdparty/assimp/code/FBXMeshGeometry.cpp b/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
index be3fbd621..e9d83911b 100644
--- a/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
+++ b/src/3rdparty/assimp/code/FBXMeshGeometry.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,13 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXMeshGeometry.cpp
* @brief Assimp::FBX::MeshGeometry implementation
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include <functional>
-#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
#include "FBXImportSettings.h"
@@ -57,22 +56,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
-
+using namespace Util;
// ------------------------------------------------------------------------------------------------
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
- : Object(id, element,name)
- , skin()
+ : Object(id, element,name)
+ , skin()
{
- const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
- BOOST_FOREACH(const Connection* con, conns) {
- const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
- if(sk) {
- skin = sk;
- break;
- }
- }
+ 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;
+ break;
+ }
+ }
}
@@ -82,253 +80,335 @@ Geometry::~Geometry()
}
+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");
- return;
- }
-
- std::vector<int> tempFaces;
- ParseVectorDataArray(tempFaces,PolygonVertexIndex);
-
- if(tempFaces.empty()) {
- FBXImporter::LogWarn("encountered mesh with no faces");
- return;
- }
-
- vertices.reserve(tempFaces.size());
- faces.reserve(tempFaces.size() / 3);
-
- mapping_offsets.resize(tempVerts.size());
- mapping_counts.resize(tempVerts.size(),0);
- 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;
- BOOST_FOREACH(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);
- }
-
- vertices.push_back(tempVerts[absi]);
- ++count;
-
- ++mapping_counts[absi];
-
- if (index < 0) {
- faces.push_back(count);
- count = 0;
- }
- }
-
- unsigned int cursor = 0;
- for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
- mapping_offsets[i] = cursor;
- cursor += mapping_counts[i];
-
- mapping_counts[i] = 0;
- }
-
- cursor = 0;
- BOOST_FOREACH(int index, tempFaces) {
- const int absi = index < 0 ? (-index - 1) : index;
- mappings[mapping_offsets[absi] + 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");
- }
- }
+ 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");
+ return;
+ }
+
+ std::vector<int> tempFaces;
+ ParseVectorDataArray(tempFaces,PolygonVertexIndex);
+
+ if(tempFaces.empty()) {
+ FBXImporter::LogWarn("encountered mesh with no faces");
+ return;
+ }
+
+ vertices.reserve(tempFaces.size());
+ faces.reserve(tempFaces.size() / 3);
+
+ mapping_offsets.resize(tempVerts.size());
+ mapping_counts.resize(tempVerts.size(),0);
+ 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);
+ }
+
+ vertices.push_back(tempVerts[absi]);
+ ++count;
+
+ ++mapping_counts[absi];
+
+ if (index < 0) {
+ faces.push_back(count);
+ count = 0;
+ }
+ }
+
+ unsigned int cursor = 0;
+ for (size_t i = 0, e = tempVerts.size(); i < e; ++i) {
+ mapping_offsets[i] = cursor;
+ cursor += mapping_counts[i];
+
+ mapping_counts[i] = 0;
+ }
+
+ cursor = 0;
+ for(int index : tempFaces) {
+ const int absi = index < 0 ? (-index - 1) : index;
+ mappings[mapping_offsets[absi] + 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()
{
}
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
+ return vertices;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetNormals() const {
+ return normals;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetTangents() const {
+ return tangents;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& MeshGeometry::GetBinormals() const {
+ return binormals;
+}
+
+// ------------------------------------------------------------------------------------------------
+const std::vector<unsigned int>& MeshGeometry::GetFaceIndexCounts() const {
+ return 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 : uvs[ index ];
+}
+
+std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const {
+ return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : 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 : colors[ index ];
+}
+
+const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
+ return materials;
+}
+
+// ------------------------------------------------------------------------------------------------
+const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
+ if ( in_index >= mapping_counts.size() ) {
+ return NULL;
+ }
+
+ ai_assert( mapping_counts.size() == mapping_offsets.size() );
+ count = mapping_counts[ in_index ];
+
+ ai_assert( count != 0 );
+ ai_assert( mapping_offsets[ in_index ] + count <= mappings.size() );
+ return &mappings[ mapping_offsets[ in_index ] ];
+}
+
+// ------------------------------------------------------------------------------------------------
+unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const {
+ ai_assert( in_index < 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 ( facesVertexStartIndices.empty() ) {
+ facesVertexStartIndices.resize( faces.size() + 1, 0 );
+
+ std::partial_sum( faces.begin(), faces.end(), facesVertexStartIndices.begin() + 1 );
+ facesVertexStartIndices.pop_back();
+ }
+
+ ai_assert( facesVertexStartIndices.size() == faces.size() );
+ const std::vector<unsigned int>::iterator it = std::upper_bound(
+ facesVertexStartIndices.begin(),
+ facesVertexStartIndices.end(),
+ in_index
+ );
+
+ return static_cast< unsigned int >( std::distance( 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);
+ 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);
- }
+ ReadLayerElement(elayer);
+ }
}
// ------------------------------------------------------------------------------------------------
void MeshGeometry::ReadLayerElement(const Scope& layerElement)
{
- const Element& Type = GetRequiredElement(layerElement,"Type");
- const Element& TypedIndex = GetRequiredElement(layerElement,"TypedIndex");
+ 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 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);
+ 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;
- }
- }
+ 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);
+ 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"];
- uvNames[index] = "";
- if(Name) {
- uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
- }
-
- ReadVertexDataUV(uvs[index],source,
- MappingInformationType,
- ReferenceInformationType
- );
- }
- else if (type == "LayerElementMaterial") {
- if (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 loosing 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(),std::bind2nd(std::less<int>(),0));
- if(count_neg == temp_materials.size()) {
- FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
- return;
- }
-
- std::swap(temp_materials, materials);
- }
- else if (type == "LayerElementNormal") {
- if (normals.size() > 0) {
- FBXImporter::LogError("ignoring additional normal layer");
- return;
- }
-
- ReadVertexDataNormals(normals,source,
- MappingInformationType,
- ReferenceInformationType
- );
- }
- else if (type == "LayerElementTangent") {
- if (tangents.size() > 0) {
- FBXImporter::LogError("ignoring additional tangent layer");
- return;
- }
-
- ReadVertexDataTangents(tangents,source,
- MappingInformationType,
- ReferenceInformationType
- );
- }
- else if (type == "LayerElementBinormal") {
- if (binormals.size() > 0) {
- FBXImporter::LogError("ignoring additional binormal layer");
- return;
- }
-
- ReadVertexDataBinormals(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(colors[index],source,
- MappingInformationType,
- ReferenceInformationType
- );
- }
+ 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"];
+ uvNames[index] = "";
+ if(Name) {
+ uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
+ }
+
+ ReadVertexDataUV(uvs[index],source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementMaterial") {
+ if (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(),std::bind2nd(std::less<int>(),0));
+ if(count_neg == temp_materials.size()) {
+ FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)");
+ return;
+ }
+
+ std::swap(temp_materials, materials);
+ }
+ else if (type == "LayerElementNormal") {
+ if (normals.size() > 0) {
+ FBXImporter::LogError("ignoring additional normal layer");
+ return;
+ }
+
+ ReadVertexDataNormals(normals,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementTangent") {
+ if (tangents.size() > 0) {
+ FBXImporter::LogError("ignoring additional tangent layer");
+ return;
+ }
+
+ ReadVertexDataTangents(tangents,source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
+ else if (type == "LayerElementBinormal") {
+ if (binormals.size() > 0) {
+ FBXImporter::LogError("ignoring additional binormal layer");
+ return;
+ }
+
+ ReadVertexDataBinormals(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(colors[index],source,
+ MappingInformationType,
+ ReferenceInformationType
+ );
+ }
}
@@ -337,200 +417,219 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
// 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)
+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)
{
- std::vector<T> tempUV;
- ParseVectorDataArray(tempUV,GetRequiredElement(source,dataElementName));
-
- // 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" && ReferenceInformationType == "Direct") {
- data_out.resize(vertex_count);
- for (size_t i = 0, e = tempUV.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]] = tempUV[i];
- }
- }
- }
- else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {
- 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]) >= tempUV.size()) {
- DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
- }
- data_out[mappings[j]] = tempUV[uvIndices[i]];
- }
- }
- }
- else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {
- if (tempUV.size() != vertex_count) {
- FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")
- << tempUV.size() << ", expected " << vertex_count
- );
- return;
- }
-
- data_out.swap(tempUV);
- }
- else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {
- 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;
- }
-
- unsigned int next = 0;
- BOOST_FOREACH(int i, uvIndices) {
- if(static_cast<size_t>(i) >= tempUV.size()) {
- DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
- }
-
- data_out[next++] = tempUV[i];
- }
- }
- else {
- FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ")
- << MappingInformationType << "," << ReferenceInformationType);
- }
+
+
+ // 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" && ReferenceInformationType == "Direct") {
+ 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" && ReferenceInformationType == "IndexToDirect") {
+ 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" && ReferenceInformationType == "Direct") {
+ 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" && ReferenceInformationType == "IndexToDirect") {
+ 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;
+ }
+
+ unsigned int next = 0;
+ for(int i : uvIndices) {
+ 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)
+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",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ ResolveVertexDataArray(normals_out,source,MappingInformationType,ReferenceInformationType,
+ "Normals",
+ "NormalsIndex",
+ vertices.size(),
+ mapping_counts,
+ mapping_offsets,
+ mappings);
}
// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataUV(std::vector<aiVector2D>& uv_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType)
+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",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ ResolveVertexDataArray(uv_out,source,MappingInformationType,ReferenceInformationType,
+ "UV",
+ "UVIndex",
+ vertices.size(),
+ mapping_counts,
+ mapping_offsets,
+ mappings);
}
// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataColors(std::vector<aiColor4D>& colors_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType)
+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",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ ResolveVertexDataArray(colors_out,source,MappingInformationType,ReferenceInformationType,
+ "Colors",
+ "ColorIndex",
+ vertices.size(),
+ mapping_counts,
+ mapping_offsets,
+ mappings);
}
-
// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType)
+static const std::string TangentIndexToken = "TangentIndex";
+static const std::string TangentsIndexToken = "TangentsIndex";
+
+void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
{
- ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
- "Tangent",
- "TangentIndex",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
+ const char * strIdx = source.Elements().count( "Tangents" ) > 0 ? TangentsIndexToken.c_str() : TangentIndexToken.c_str();
+ ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
+ str,
+ strIdx,
+ vertices.size(),
+ mapping_counts,
+ mapping_offsets,
+ mappings);
}
-
// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType)
+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)
{
- ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
- "Binormal",
- "BinormalIndex",
- vertices.size(),
- mapping_counts,
- mapping_offsets,
- mappings);
+ 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,
+ vertices.size(),
+ mapping_counts,
+ mapping_offsets,
+ mappings);
}
// ------------------------------------------------------------------------------------------------
-void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
- const std::string& MappingInformationType,
- const std::string& ReferenceInformationType)
+void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, const Scope& source,
+ const std::string& MappingInformationType,
+ const std::string& ReferenceInformationType)
{
- const size_t face_count = faces.size();
- ai_assert(face_count);
-
- // 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.assign(vertices.size(),materials_out[0]);
- }
- else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
- materials.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);
- }
+ const size_t face_count = faces.size();
+ ai_assert(face_count);
+
+ // 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.assign(vertices.size(),materials_out[0]);
+ }
+ else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
+ materials.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);
+ }
}
} // !FBX
diff --git a/src/3rdparty/assimp/code/FBXMeshGeometry.h b/src/3rdparty/assimp/code/FBXMeshGeometry.h
new file mode 100644
index 000000000..48ac550c1
--- /dev/null
+++ b/src/3rdparty/assimp/code/FBXMeshGeometry.h
@@ -0,0 +1,180 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @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;
+
+private:
+ const Skin* skin;
+};
+
+
+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 binormals or an empty array
+ * if no binormals 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 materials;
+ std::vector<aiVector3D> vertices;
+ std::vector<unsigned int> faces;
+ mutable std::vector<unsigned int> facesVertexStartIndices;
+ std::vector<aiVector3D> tangents;
+ std::vector<aiVector3D> binormals;
+ std::vector<aiVector3D> normals;
+
+ std::string uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiVector2D> uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ std::vector<aiColor4D> colors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
+
+ std::vector<unsigned int> mapping_counts;
+ std::vector<unsigned int> mapping_offsets;
+ std::vector<unsigned int> mappings;
+};
+
+}
+}
+
+#endif // INCLUDED_AI_FBX_MESHGEOMETRY_H
+
diff --git a/src/3rdparty/assimp/code/FBXModel.cpp b/src/3rdparty/assimp/code/FBXModel.cpp
index d6d329801..bbeb14bfb 100644
--- a/src/3rdparty/assimp/code/FBXModel.cpp
+++ b/src/3rdparty/assimp/code/FBXModel.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,11 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXModel.cpp
* @brief Assimp::FBX::Model implementation
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#include "FBXParser.h"
+#include "FBXMeshGeometry.h"
#include "FBXDocument.h"
#include "FBXImporter.h"
#include "FBXImportSettings.h"
@@ -55,27 +55,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
+using namespace Util;
// ------------------------------------------------------------------------------------------------
Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name)
- : Object(id,element,name)
- , shading("Y")
+ : Object(id,element,name)
+ , shading("Y")
{
- const Scope& sc = GetRequiredScope(element);
- const Element* const Shading = sc["Shading"];
- const Element* const Culling = sc["Culling"];
+ 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(Shading) {
+ shading = GetRequiredToken(*Shading,0).StringContents();
+ }
- if (Culling) {
- culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
- }
+ if (Culling) {
+ culling = ParseTokenAsString(GetRequiredToken(*Culling,0));
+ }
- props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
- ResolveLinks(element,doc);
+ props = GetPropertyTable(doc,"Model.FbxNode",element,sc);
+ ResolveLinks(element,doc);
}
@@ -89,64 +89,64 @@ 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());
- BOOST_FOREACH(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;
- }
+ 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();
- BOOST_FOREACH(const NodeAttribute* att, attrs) {
-
- const Null* null_tag = dynamic_cast<const Null*>(att);
- if(null_tag) {
- return true;
- }
- }
-
- return false;
+ 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;
}
diff --git a/src/3rdparty/assimp/code/FBXNodeAttribute.cpp b/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
index 1b7314666..405ce7206 100644
--- a/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
+++ b/src/3rdparty/assimp/code/FBXNodeAttribute.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXNoteAttribute.cpp
* @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -55,21 +54,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
+ using namespace Util;
// ------------------------------------------------------------------------------------------------
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
- : Object(id,element,name)
+: Object(id,element,name)
+, props()
{
- const Scope& sc = GetRequiredScope(element);
+ const Scope& sc = GetRequiredScope(element);
- const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+ 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);
+ // 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);
}
@@ -82,24 +82,24 @@ NodeAttribute::~NodeAttribute()
// ------------------------------------------------------------------------------------------------
CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
- : NodeAttribute(id,element,doc,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();
- }
+ 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();
+ }
}
diff --git a/src/3rdparty/assimp/code/FBXParser.cpp b/src/3rdparty/assimp/code/FBXParser.cpp
index f6dc2e7e2..beca20b14 100644
--- a/src/3rdparty/assimp/code/FBXParser.cpp
+++ b/src/3rdparty/assimp/code/FBXParser.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,15 +41,14 @@ 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
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
+# include <zlib.h>
#else
-# include "../contrib/zlib/zlib.h"
+# include "../contrib/zlib/zlib.h"
#endif
@@ -59,6 +58,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include "ByteSwapper.h"
+
+#include <iostream>
using namespace Assimp;
using namespace Assimp::FBX;
@@ -66,53 +68,46 @@ using namespace Assimp::FBX;
namespace {
- // ------------------------------------------------------------------------------------------------
- // signal parse error, this is always unrecoverable. Throws DeadlyImportError.
- void ParseError(const std::string& message, const Token& token)
- {
- throw DeadlyImportError(Util::AddTokenText("FBX-Parser",message,&token));
- }
-
- // ------------------------------------------------------------------------------------------------
- void ParseError(const std::string& message, const Element* element = NULL)
- {
- if(element) {
- ParseError(message,element->KeyToken());
- }
- throw DeadlyImportError("FBX-Parser " + message);
- }
-
-
- // ------------------------------------------------------------------------------------------------
- // print warning, do return
- void ParseWarning(const std::string& message, const Token& token)
- {
- if(DefaultLogger::get()) {
- DefaultLogger::get()->warn(Util::AddTokenText("FBX-Parser",message,&token));
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- void ParseWarning(const std::string& message, const Element* element = NULL)
- {
- if(element) {
- ParseWarning(message,element->KeyToken());
- return;
- }
- if(DefaultLogger::get()) {
- DefaultLogger::get()->warn("FBX-Parser: " + message);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- void ParseError(const std::string& message, TokenPtr token)
- {
- if(token) {
- ParseError(message, *token);
- }
- ParseError(message);
- }
-
+ // ------------------------------------------------------------------------------------------------
+ // 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.
+ 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 {
@@ -122,92 +117,99 @@ namespace FBX {
Element::Element(const Token& key_token, Parser& parser)
: key_token(key_token)
{
- TokenPtr n = NULL;
- 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);
-
- n = parser.AdvanceToNextToken();
- if(!n) {
- ParseError("unexpected end of file, expected bracket, comma or key",parser.LastToken());
- }
+ TokenPtr n = NULL;
+ 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();
- if (ty != TokenType_OPEN_BRACKET && ty != TokenType_CLOSE_BRACKET && ty != TokenType_COMMA && ty != TokenType_KEY) {
- ParseError("unexpected token; expected bracket, comma or key",n);
+
+ // 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 (n->Type() == TokenType_OPEN_BRACKET) {
- compound.reset(new Scope(parser));
+ if (ty != TokenType_OPEN_BRACKET && ty != TokenType_CLOSE_BRACKET && ty != TokenType_COMMA && ty != TokenType_KEY) {
+ ParseError("unexpected token; expected bracket, comma or key",n);
+ }
+ }
- // current token should be a TOK_CLOSE_BRACKET
- n = parser.CurrentToken();
- ai_assert(n);
+ if (n->Type() == TokenType_OPEN_BRACKET) {
+ compound.reset(new Scope(parser));
- if (n->Type() != TokenType_CLOSE_BRACKET) {
- ParseError("expected closing bracket",n);
- }
+ // 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);
+ 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
+ // 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());
- }
- }
+ 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()
{
- BOOST_FOREACH(ElementMap::value_type& v, elements) {
- delete v.second;
- }
+ for(ElementMap::value_type& v : elements) {
+ delete v.second;
+ }
}
@@ -219,7 +221,7 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
, cursor(tokens.begin())
, is_binary(is_binary)
{
- root.reset(new Scope(*this,true));
+ root.reset(new Scope(*this,true));
}
@@ -232,250 +234,267 @@ Parser::~Parser()
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken()
{
- last = current;
- if (cursor == tokens.end()) {
- current = NULL;
- }
- else {
- current = *cursor++;
- }
- return current;
+ last = current;
+ if (cursor == tokens.end()) {
+ current = NULL;
+ }
+ else {
+ current = *cursor++;
+ }
+ return current;
}
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::CurrentToken() const
{
- return current;
+ return current;
}
// ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const
{
- return last;
+ 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;
- }
-
- ai_assert(t.end() - data == 9);
-
- BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
- 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;
- 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;
+ 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;
+ 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;
- }
-
- ai_assert(t.end() - data == 9);
- BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
- 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;
- 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;
+ // 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;
+ 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') {
- // Actual size validation happens during Tokenization so
- // this is valid as an assertion.
- ai_assert(t.end() - data == sizeof(float) + 1);
- // Initially, we did reinterpret_cast, breaking strict aliasing rules.
- // This actually caused trouble on Android, so let's be safe this time.
- // https://github.com/assimp/assimp/issues/24
-
- float out_float;
- ::memcpy(&out_float, data+1, sizeof(float));
- return out_float;
- }
- else {
- ai_assert(t.end() - data == sizeof(double) + 1);
-
- // Same
- double out_double;
- ::memcpy(&out_double, data+1, sizeof(double));
- return static_cast<float>(out_double);
- }
- }
-
- // 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.
+ 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';
+ 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);
+ 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;
- }
-
- ai_assert(t.end() - data == 5);
- BE_NCONST int32_t ival = *reinterpret_cast<const int32_t*>(data+1);
- 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;
+ 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;
+ 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 "";
- }
-
- ai_assert(t.end() - data >= 5);
-
- // read string length
- BE_NCONST int32_t len = *reinterpret_cast<const int32_t*>(data+1);
- 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);
+ 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);
}
@@ -483,107 +502,107 @@ 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)
+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);
- }
+ 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;
+ // data type
+ type = *data;
- // read number of elements
- BE_NCONST uint32_t len = *reinterpret_cast<const uint32_t*>(data+1);
- AI_SWAP4(len);
+ // read number of elements
+ BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
+ AI_SWAP4(len);
- count = len;
- data += 5;
+ 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)
+void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
+ std::vector<char>& buff,
+ const Element& /*el*/)
{
- ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
-
- BE_NCONST uint32_t encmode = *reinterpret_cast<const uint32_t*>(data);
- AI_SWAP4(encmode);
- data += 4;
-
- // next comes the compressed length
- BE_NCONST uint32_t comp_len = *reinterpret_cast<const uint32_t*>(data);
- 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
- inflateInit(&zstream);
-
- zstream.next_in = reinterpret_cast<Bytef*>( const_cast<char*>(data) );
- zstream.avail_in = comp_len;
-
- zstream.avail_out = 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);
- }
+ 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 = 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);
- }
+ else {
+ // runtime check for this happens at tokenization stage
+ ai_assert(false);
+ }
#endif
- data += comp_len;
- ai_assert(data == end);
+ data += comp_len;
+ ai_assert(data == end);
}
} // !anon
@@ -593,80 +612,87 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
// read an array of float3 tuples
void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
{
- out.clear();
-
- 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<float>(d[0]),
- static_cast<float>(d[1]),
- static_cast<float>(d[2])));
- }
- }
- 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);
- }
+ 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<float>(d[0]),
+ static_cast<float>(d[1]),
+ static_cast<float>(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);
+ }
}
@@ -674,78 +700,78 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
// read an array of color4 tuples
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
{
- out.clear();
- 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);
- }
+ 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);
+ }
}
@@ -753,75 +779,75 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
// read an array of float2 tuples
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
{
- out.clear();
- 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);
- }
+ 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);
+ }
}
@@ -829,57 +855,57 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
// read an array of ints
void ParseVectorDataArray(std::vector<int>& out, const Element& el)
{
- out.clear();
- const TokenList& tok = el.Tokens();
- if(tok.empty()) {
- ParseError("unexpected empty 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();
+ 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);
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
- if(!count) {
- return;
- }
+ if(!count) {
+ return;
+ }
- if (type != 'i') {
- ParseError("expected int array (binary)",&el);
- }
+ if (type != 'i') {
+ ParseError("expected int array (binary)",&el);
+ }
- std::vector<char> buff;
- ReadBinaryDataArray(type, count, data, end, buff, el);
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
- ai_assert(data == end);
- ai_assert(buff.size() == count * 4);
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 4);
- out.reserve(count);
+ 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);
- }
+ 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;
- }
+ return;
+ }
- const size_t dim = ParseTokenAsDim(*tok[0]);
+ const size_t dim = ParseTokenAsDim(*tok[0]);
- // see notes in ParseVectorDataArray()
- out.reserve(dim);
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
- const Scope& scope = GetRequiredScope(el);
- const Element& a = GetRequiredElement(scope,"a",&el);
+ 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);
- }
+ for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
+ const int ival = ParseTokenAsInt(**it++);
+ out.push_back(ival);
+ }
}
@@ -887,223 +913,280 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
// read an array of floats
void ParseVectorDataArray(std::vector<float>& out, const Element& el)
{
- out.clear();
- const TokenList& tok = el.Tokens();
- if(tok.empty()) {
- ParseError("unexpected empty 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();
+ 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);
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
- if(!count) {
- return;
- }
+ if(!count) {
+ return;
+ }
- if (type != 'd' && type != 'f') {
- ParseError("expected float or double array (binary)",&el);
- }
+ if (type != 'i') {
+ ParseError("expected (u)int array (binary)",&el);
+ }
- std::vector<char> buff;
- ReadBinaryDataArray(type, count, data, end, buff, 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));
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 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);
- }
- }
+ 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)");
+ }
- return;
- }
+ AI_SWAP4(val);
+ out.push_back(val);
+ }
- const size_t dim = ParseTokenAsDim(*tok[0]);
+ return;
+ }
- // see notes in ParseVectorDataArray()
- out.reserve(dim);
+ const size_t dim = ParseTokenAsDim(*tok[0]);
- const Scope& scope = GetRequiredScope(el);
- const Element& a = GetRequiredElement(scope,"a",&el);
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
- for (TokenList::const_iterator it = a.Tokens().begin(), end = a.Tokens().end(); it != end; ) {
- const float ival = ParseTokenAsFloat(**it++);
- out.push_back(ival);
- }
+ 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 uints
-void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
+// read an array of uint64_ts
+void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
{
- out.clear();
- const TokenList& tok = el.Tokens();
- if(tok.empty()) {
- ParseError("unexpected empty 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();
+ 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);
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
- if(!count) {
- return;
- }
+ if(!count) {
+ return;
+ }
- if (type != 'i') {
- ParseError("expected (u)int array (binary)",&el);
- }
+ if (type != 'l') {
+ ParseError("expected long array (binary)",&el);
+ }
- std::vector<char> buff;
- ReadBinaryDataArray(type, count, data, end, buff, el);
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
- ai_assert(data == end);
- ai_assert(buff.size() == count * 4);
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 8);
- out.reserve(count);
+ 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)");
- }
+ 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);
+ }
- AI_SWAP4(val);
- out.push_back(val);
- }
+ return;
+ }
- return;
- }
+ const size_t dim = ParseTokenAsDim(*tok[0]);
- const size_t dim = ParseTokenAsDim(*tok[0]);
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
- // see notes in ParseVectorDataArray()
- out.reserve(dim);
+ const Scope& scope = GetRequiredScope(el);
+ const Element& a = GetRequiredElement(scope,"a",&el);
- 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++);
- 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));
- }
+ out.push_back(ival);
+ }
}
-
// ------------------------------------------------------------------------------------------------
-// read an array of uint64_ts
-void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
+// read an array of int64_ts
+void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
{
- out.clear();
- const TokenList& tok = el.Tokens();
- if(tok.empty()) {
- ParseError("unexpected empty 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();
+ 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);
+ char type;
+ uint32_t count;
+ ReadBinaryDataArrayHead(data, end, type, count, el);
- if(!count) {
- return;
- }
+ if (!count) {
+ return;
+ }
- if (type != 'l') {
- ParseError("expected long array (binary)",&el);
- }
+ if (type != 'l') {
+ ParseError("expected long array (binary)", &el);
+ }
- std::vector<char> buff;
- ReadBinaryDataArray(type, count, data, end, buff, el);
+ std::vector<char> buff;
+ ReadBinaryDataArray(type, count, data, end, buff, el);
- ai_assert(data == end);
- ai_assert(buff.size() == count * 8);
+ ai_assert(data == end);
+ ai_assert(buff.size() == count * 8);
- out.reserve(count);
+ 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);
- }
+ 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;
- }
+ return;
+ }
- const size_t dim = ParseTokenAsDim(*tok[0]);
+ const size_t dim = ParseTokenAsDim(*tok[0]);
- // see notes in ParseVectorDataArray()
- out.reserve(dim);
+ // see notes in ParseVectorDataArray()
+ out.reserve(dim);
- const Scope& scope = GetRequiredScope(el);
- const Element& a = GetRequiredElement(scope,"a",&el);
+ 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);
- }
-}
+ 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);
+ std::vector<float> values;
+ ParseVectorDataArray(values,element);
- if(values.size() != 16) {
- ParseError("expected 16 matrix elements");
- }
+ if(values.size() != 16) {
+ ParseError("expected 16 matrix elements");
+ }
- aiMatrix4x4 result;
+ aiMatrix4x4 result;
- result.a1 = values[0];
- result.a2 = values[1];
- result.a3 = values[2];
- result.a4 = values[3];
+ 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.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.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.d1 = values[12];
+ result.d2 = values[13];
+ result.d3 = values[14];
+ result.d4 = values[15];
- result.Transpose();
- return result;
+ result.Transpose();
+ return result;
}
@@ -1111,24 +1194,24 @@ aiMatrix4x4 ReadMatrix(const Element& element)
// 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;
+ const char* err;
+ const std::string& i = ParseTokenAsString(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
}
// ------------------------------------------------------------------------------------------------
// 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& 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;
+ const Element* el = sc[index];
+ if(!el) {
+ ParseError("did not find required element \"" + index + "\"",element);
+ }
+ return *el;
}
@@ -1136,12 +1219,12 @@ const Element& GetRequiredElement(const Scope& sc, const std::string& index, con
// extract required compound scope
const Scope& GetRequiredScope(const Element& el)
{
- const Scope* const s = el.Compound();
- if(!s) {
- ParseError("expected compound scope",&el);
- }
+ const Scope* const s = el.Compound();
+ if(!s) {
+ ParseError("expected compound scope",&el);
+ }
- return *s;
+ return *s;
}
@@ -1149,25 +1232,25 @@ const Scope& GetRequiredScope(const Element& el)
// 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);
- }
+ const TokenList& t = el.Tokens();
+ if(index >= t.size()) {
+ ParseError(Formatter::format( "missing token at index " ) << index,&el);
+ }
- return *t[index];
+ return *t[index];
}
// ------------------------------------------------------------------------------------------------
// wrapper around ParseTokenAsID() with ParseError handling
-uint64_t ParseTokenAsID(const Token& t)
+uint64_t ParseTokenAsID(const Token& t)
{
- const char* err;
- const uint64_t i = ParseTokenAsID(t,err);
- if(err) {
- ParseError(err,t);
- }
- return i;
+ const char* err;
+ const uint64_t i = ParseTokenAsID(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
}
@@ -1175,12 +1258,12 @@ uint64_t ParseTokenAsID(const Token& t)
// 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;
+ const char* err;
+ const size_t i = ParseTokenAsDim(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
}
@@ -1188,12 +1271,12 @@ size_t ParseTokenAsDim(const Token& t)
// 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;
+ const char* err;
+ const float i = ParseTokenAsFloat(t,err);
+ if(err) {
+ ParseError(err,t);
+ }
+ return i;
}
@@ -1201,18 +1284,29 @@ float ParseTokenAsFloat(const Token& t)
// 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;
+ 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
-
diff --git a/src/3rdparty/assimp/code/FBXParser.h b/src/3rdparty/assimp/code/FBXParser.h
index e6fa25d22..6bc34272a 100644
--- a/src/3rdparty/assimp/code/FBXParser.h
+++ b/src/3rdparty/assimp/code/FBXParser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,13 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_PARSER_H
#define INCLUDED_AI_FBX_PARSER_H
-#include <vector>
+#include <stdint.h>
#include <map>
-#include <string>
-#include <utility>
-
-#include <boost/shared_ptr.hpp>
-
+#include <memory>
#include "LogAux.h"
#include "FBXCompileConfig.h"
@@ -59,18 +55,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- class Scope;
- class Parser;
- class Element;
+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;
+// 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;
+typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
-# define new_Scope new Scope
-# define new_Element new Element
+# define new_Scope new Scope
+# define new_Element new Element
/** FBX data entity that consists of a key:value tuple.
@@ -88,28 +84,28 @@ class Element
{
public:
- Element(const Token& key_token, Parser& parser);
- ~Element();
+ Element(const Token& key_token, Parser& parser);
+ ~Element();
public:
- const Scope* Compound() const {
- return compound.get();
- }
+ const Scope* Compound() const {
+ return compound.get();
+ }
- const Token& KeyToken() const {
- return key_token;
- }
+ const Token& KeyToken() const {
+ return key_token;
+ }
- const TokenList& Tokens() const {
- return tokens;
- }
+ const TokenList& Tokens() const {
+ return tokens;
+ }
private:
- const Token& key_token;
- TokenList tokens;
- boost::scoped_ptr<Scope> compound;
+ const Token& key_token;
+ TokenList tokens;
+ std::unique_ptr<Scope> compound;
};
@@ -121,7 +117,7 @@ private:
* @verbatim
* GlobalSettings: {
* Version: 1000
- * Properties70:
+ * Properties70:
* [...]
* }
* @endverbatim */
@@ -130,73 +126,69 @@ class Scope
public:
- Scope(Parser& parser, bool topLevel = false);
- ~Scope();
+ Scope(Parser& parser, bool topLevel = false);
+ ~Scope();
public:
- const Element* operator[] (const std::string& index) const {
- ElementMap::const_iterator it = elements.find(index);
- return it == elements.end() ? NULL : (*it).second;
- }
+ const Element* operator[] (const std::string& index) const {
+ ElementMap::const_iterator it = elements.find(index);
+ return it == elements.end() ? NULL : (*it).second;
+ }
- ElementCollection GetCollection(const std::string& index) const {
- return elements.equal_range(index);
- }
+ ElementCollection GetCollection(const std::string& index) const {
+ return elements.equal_range(index);
+ }
- const ElementMap& Elements() const {
- return elements;
- }
+ const ElementMap& Elements() const {
+ return elements;
+ }
private:
- ElementMap elements;
+ 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
+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();
-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();
- }
+public:
+ const Scope& GetRootScope() const {
+ return *root.get();
+ }
- bool IsBinary() const {
- return is_binary;
- }
+ bool IsBinary() const {
+ return is_binary;
+ }
private:
+ friend class Scope;
+ friend class Element;
- friend class Scope;
- friend class Element;
-
- TokenPtr AdvanceToNextToken();
+ TokenPtr AdvanceToNextToken();
- TokenPtr LastToken() const;
- TokenPtr CurrentToken() const;
+ TokenPtr LastToken() const;
+ TokenPtr CurrentToken() const;
-
private:
+ const TokenList& tokens;
- const TokenList& tokens;
-
- TokenPtr last, current;
- TokenList::const_iterator cursor;
- boost::scoped_ptr<Scope> root;
+ TokenPtr last, current;
+ TokenList::const_iterator cursor;
+ std::unique_ptr<Scope> root;
- const bool is_binary;
+ const bool is_binary;
};
@@ -206,6 +198,7 @@ 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);
@@ -214,6 +207,7 @@ 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 */
@@ -224,6 +218,7 @@ 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);
diff --git a/src/3rdparty/assimp/code/FBXProperties.cpp b/src/3rdparty/assimp/code/FBXProperties.cpp
index 48bdb4f40..23d072b18 100644
--- a/src/3rdparty/assimp/code/FBXProperties.cpp
+++ b/src/3rdparty/assimp/code/FBXProperties.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXProperties.cpp
* @brief Implementation of the FBX dynamic properties system
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -54,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
- using namespace Util;
+ using namespace Util;
// ------------------------------------------------------------------------------------------------
Property::Property()
@@ -72,43 +71,46 @@ 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,"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,"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,"KTime") || !strcmp(cs,"Float")) {
- return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
- }
- return NULL;
+ 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")) {
+ return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
+ }
+ return NULL;
}
@@ -116,13 +118,13 @@ Property* ReadTypedProperty(const Element& element)
// 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 "";
- }
+ ai_assert(element.KeyToken().StringContents() == "P");
+ const TokenList& tok = element.Tokens();
+ if(tok.size() < 4) {
+ return "";
+ }
- return ParseTokenAsString(*tok[0]);
+ return ParseTokenAsString(*tok[0]);
}
} //! anon
@@ -137,93 +139,93 @@ PropertyTable::PropertyTable()
// ------------------------------------------------------------------------------------------------
-PropertyTable::PropertyTable(const Element& element, boost::shared_ptr<const PropertyTable> templateProps)
+PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
: templateProps(templateProps)
, element(&element)
{
- const Scope& scope = GetRequiredScope(element);
- BOOST_FOREACH(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;
- }
+ 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()
{
- BOOST_FOREACH(PropertyMap::value_type& v, props) {
- delete v.second;
- }
+ 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;
+ 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;
+ DirectPropertyMap result;
- // Loop through all the lazy properties (which is all the properties)
- BOOST_FOREACH(const LazyPropertyMap::value_type& element, lazyProps) {
+ // 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;
+ // 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.
- boost::shared_ptr<Property> prop = boost::shared_ptr<Property>(ReadTypedProperty(*element.second));
-
- // Element could not be read. Skip it.
- if (!prop) 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));
- // Add to result
- result[element.first] = prop;
- }
+ // Element could not be read. Skip it.
+ if (!prop) continue;
- return result;
+ // Add to result
+ result[element.first] = prop;
+ }
+
+ return result;
}
diff --git a/src/3rdparty/assimp/code/FBXProperties.h b/src/3rdparty/assimp/code/FBXProperties.h
index 9219c3eea..60cdfe2c6 100644
--- a/src/3rdparty/assimp/code/FBXProperties.h
+++ b/src/3rdparty/assimp/code/FBXProperties.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,34 +23,35 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file FBXProperties.h
- * @brief FBX dynamic properties
+ * @brief FBX dynamic properties
*/
#ifndef INCLUDED_AI_FBX_PROPERTIES_H
#define INCLUDED_AI_FBX_PROPERTIES_H
#include <map>
-#include <string>
+#include "FBXCompileConfig.h"
+#include <memory>
namespace Assimp {
namespace FBX {
- class Element;
+ class Element;
/** Represents a dynamic property. Type info added by deriving classes,
@@ -64,19 +65,16 @@ namespace FBX {
class Property
{
protected:
-
- Property();
+ Property();
public:
-
- virtual ~Property();
+ virtual ~Property();
public:
-
- template <typename T>
- const T* As() const {
- return dynamic_cast<const T*>(this);
- }
+ template <typename T>
+ const T* As() const {
+ return dynamic_cast<const T*>(this);
+ }
};
@@ -84,108 +82,102 @@ template<typename T>
class TypedProperty : public Property
{
public:
-
- TypedProperty(const T& value)
- : value(value)
- {
- }
+ explicit TypedProperty(const T& value)
+ : value(value)
+ {
+ }
public:
-
- const T& Value() const {
- return value;
- }
+ const T& Value() const {
+ return value;
+ }
private:
- T value;
+ T value;
};
-typedef std::fbx_unordered_map<std::string,boost::shared_ptr<Property> > DirectPropertyMap;
+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)*/
+/**
+ * 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, boost::shared_ptr<const PropertyTable> templateProps);
- ~PropertyTable();
+ // in-memory property table with no source element
+ PropertyTable();
+ PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps);
+ ~PropertyTable();
public:
+ const Property* Get(const std::string& name) const;
- 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;
+ }
- // 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();
+ }
- const PropertyTable* TemplateProps() const {
- return templateProps.get();
- }
-
- DirectPropertyMap GetUnparsedProperties() const;
+ DirectPropertyMap GetUnparsedProperties() const;
private:
-
- LazyPropertyMap lazyProps;
- mutable PropertyMap props;
- const boost::shared_ptr<const PropertyTable> templateProps;
- const Element* const element;
+ 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,
- bool ignoreTemplate = false)
+inline T PropertyGet(const PropertyTable& in, const std::string& name,
+ const T& defaultValue)
{
- const Property* const prop = in.Get(name);
- if(!prop) {
- return defaultValue;
- }
-
- // strong typing, no need to be lenient
- const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
- if(!tprop) {
- return defaultValue;
- }
-
- return tprop->Value();
+ const Property* const prop = in.Get(name);
+ if(!prop) {
+ return defaultValue;
+ }
+
+ // strong typing, no need to be lenient
+ const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
+ if(!tprop) {
+ return defaultValue;
+ }
+
+ return tprop->Value();
}
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline T PropertyGet(const PropertyTable& in, const std::string& name,
- bool& result,
- bool ignoreTemplate = false)
+inline T PropertyGet(const PropertyTable& in, const std::string& name,
+ bool& result)
{
- const Property* const prop = in.Get(name);
- if(!prop) {
- result = false;
- return T();
- }
-
- // strong typing, no need to be lenient
- const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
- if(!tprop) {
- result = false;
- return T();
- }
-
- result = true;
- return tprop->Value();
+ const Property* const prop = in.Get(name);
+ if(!prop) {
+ result = false;
+ return T();
+ }
+
+ // strong typing, no need to be lenient
+ const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
+ if(!tprop) {
+ result = false;
+ return T();
+ }
+
+ result = true;
+ return tprop->Value();
}
} //! FBX
} //! Assimp
-#endif //
+#endif // INCLUDED_AI_FBX_PROPERTIES_H
diff --git a/src/3rdparty/assimp/code/FBXTokenizer.cpp b/src/3rdparty/assimp/code/FBXTokenizer.cpp
index 7aa81543a..7ede49f39 100644
--- a/src/3rdparty/assimp/code/FBXTokenizer.cpp
+++ b/src/3rdparty/assimp/code/FBXTokenizer.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXTokenizer.cpp
* @brief Implementation of the FBX broadphase lexer
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -52,26 +51,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h"
#include "FBXUtil.h"
+#include "Exceptional.h"
namespace Assimp {
namespace FBX {
// ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
- : sbegin(sbegin)
- , send(send)
- , type(type)
- , line(line)
- , column(column)
+ :
#ifdef DEBUG
- , contents(sbegin, static_cast<size_t>(send-sbegin))
+ 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);
+ ai_assert(sbegin);
+ ai_assert(send);
- // tokens must be of non-zero length
- ai_assert(static_cast<size_t>(send-sbegin) > 0);
+ // tokens must be of non-zero length
+ ai_assert(static_cast<size_t>(send-sbegin) > 0);
}
@@ -85,46 +86,47 @@ namespace {
// ------------------------------------------------------------------------------------------------
// signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
-void TokenizeError(const std::string& message, unsigned int line, unsigned int column)
+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));
+ throw DeadlyImportError(Util::AddLineAndColumn("FBX-Tokenize",message,line,column));
}
-// process a potential data token up to 'cur', adding it to 'output_tokens'.
+// 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)
+ 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;
+ 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;
}
}
@@ -132,112 +134,112 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
// ------------------------------------------------------------------------------------------------
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;
- }
- }
+ 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
diff --git a/src/3rdparty/assimp/code/FBXTokenizer.h b/src/3rdparty/assimp/code/FBXTokenizer.h
index 0a4339a50..f9f1fb871 100644
--- a/src/3rdparty/assimp/code/FBXTokenizer.h
+++ b/src/3rdparty/assimp/code/FBXTokenizer.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,9 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_FBX_TOKENIZER_H
#define INCLUDED_AI_FBX_TOKENIZER_H
-#include <boost/shared_ptr.hpp>
-
+#include <memory>
#include "FBXCompileConfig.h"
+#include <assimp/ai_assert.h>
+#include <vector>
+#include <string>
namespace Assimp {
namespace FBX {
@@ -55,24 +57,24 @@ namespace FBX {
* basic scope hierarchy. */
enum TokenType
{
- // {
- TokenType_OPEN_BRACKET = 0,
-
- // }
- TokenType_CLOSE_BRACKET,
+ // {
+ TokenType_OPEN_BRACKET = 0,
+
+ // }
+ TokenType_CLOSE_BRACKET,
- // '"blablubb"', '2', '*14' - very general token class,
- // further processing happens at a later stage.
- TokenType_DATA,
+ // '"blablubb"', '2', '*14' - very general token class,
+ // further processing happens at a later stage.
+ TokenType_DATA,
- //
- TokenType_BINARY_DATA,
+ //
+ TokenType_BINARY_DATA,
- // ,
- TokenType_COMMA,
+ // ,
+ TokenType_COMMA,
- // blubb:
- TokenType_KEY
+ // blubb:
+ TokenType_KEY
};
@@ -80,80 +82,80 @@ enum TokenType
* classified by the #TokenType enumerated types.
*
* Offers iterator protocol. Tokens are immutable. */
-class Token
+class Token
{
private:
- static const unsigned int BINARY_MARKER = static_cast<unsigned int>(-1);
+ 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 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, unsigned int offset);
+ /** construct a binary token */
+ Token(const char* sbegin, const char* send, TokenType type, unsigned int offset);
- ~Token();
+ ~Token();
public:
- std::string StringContents() const {
- return std::string(begin(),end());
- }
+ std::string StringContents() const {
+ return std::string(begin(),end());
+ }
public:
- bool IsBinary() const {
- return column == BINARY_MARKER;
- }
+ bool IsBinary() const {
+ return column == BINARY_MARKER;
+ }
- const char* begin() const {
- return sbegin;
- }
+ const char* begin() const {
+ return sbegin;
+ }
- const char* end() const {
- return send;
- }
+ const char* end() const {
+ return send;
+ }
- TokenType Type() const {
- return type;
- }
+ TokenType Type() const {
+ return type;
+ }
- unsigned int Offset() const {
- ai_assert(IsBinary());
- return offset;
- }
+ unsigned int Offset() const {
+ ai_assert(IsBinary());
+ return offset;
+ }
- unsigned int Line() const {
- ai_assert(!IsBinary());
- return line;
- }
+ unsigned int Line() const {
+ ai_assert(!IsBinary());
+ return line;
+ }
- unsigned int Column() const {
- ai_assert(!IsBinary());
- return column;
- }
+ 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;
+ // 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;
+ const char* const sbegin;
+ const char* const send;
+ const TokenType type;
- union {
- const unsigned int line;
- unsigned int offset;
- };
- const unsigned int column;
+ union {
+ const unsigned int line;
+ unsigned int offset;
+ };
+ const unsigned int column;
};
// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
diff --git a/src/3rdparty/assimp/code/FBXUtil.cpp b/src/3rdparty/assimp/code/FBXUtil.cpp
index aaf311d03..601d5e214 100644
--- a/src/3rdparty/assimp/code/FBXUtil.cpp
+++ b/src/3rdparty/assimp/code/FBXUtil.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file FBXUtil.cpp
* @brief Implementation of internal FBX utility functions
*/
-#include "AssimpPCH.h"
#include "FBXUtil.h"
#include "FBXTokenizer.h"
@@ -57,58 +56,58 @@ 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";
+ switch(t) {
+ case TokenType_OPEN_BRACKET:
+ return "TOK_OPEN_BRACKET";
- case TokenType_DATA:
- return "TOK_DATA";
+ case TokenType_CLOSE_BRACKET:
+ return "TOK_CLOSE_BRACKET";
- case TokenType_COMMA:
- return "TOK_COMMA";
+ case TokenType_DATA:
+ return "TOK_DATA";
- case TokenType_KEY:
- return "TOK_KEY";
+ case TokenType_COMMA:
+ return "TOK_COMMA";
- case TokenType_BINARY_DATA:
- return "TOK_BINARY_DATA";
- }
+ case TokenType_KEY:
+ return "TOK_KEY";
- ai_assert(false);
- return "";
+ case TokenType_BINARY_DATA:
+ return "TOK_BINARY_DATA";
+ }
+
+ ai_assert(false);
+ return "";
}
-
+
// ------------------------------------------------------------------------------------------------
std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset)
{
- return static_cast<std::string>( (Formatter::format(),prefix," (offset 0x",std::hex,offset,") ",text) );
+ 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) );
+ 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) );
+ 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) );
}
} // !Util
@@ -116,4 +115,3 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
} // !Assimp
#endif
-
diff --git a/src/3rdparty/assimp/code/FBXUtil.h b/src/3rdparty/assimp/code/FBXUtil.h
index a205b598d..bd41834b0 100644
--- a/src/3rdparty/assimp/code/FBXUtil.h
+++ b/src/3rdparty/assimp/code/FBXUtil.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -59,9 +59,9 @@ namespace Util {
template<typename T>
struct delete_fun
{
- void operator()(const volatile T* del) {
- delete del;
- }
+ void operator()(const volatile T* del) {
+ delete del;
+ }
};
/** Get a string representation for a #TokenType. */
@@ -74,7 +74,7 @@ const char* TokenTypeString(TokenType t);
* @param prefix Message prefix to be preprended to the location info.
* @param text Message text
* @param line Line index, 1-based
- * @param column Colum 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, unsigned int offset);
@@ -84,10 +84,10 @@ std::string AddOffset(const std::string& prefix, const std::string& text, unsign
* @param prefix Message prefix to be preprended to the location info.
* @param text Message text
* @param line Line index, 1-based
- * @param column Colum 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.
*
diff --git a/src/3rdparty/assimp/code/FileLogStream.h b/src/3rdparty/assimp/code/FileLogStream.h
index c3f648953..574a63ed6 100644
--- a/src/3rdparty/assimp/code/FileLogStream.h
+++ b/src/3rdparty/assimp/code/FileLogStream.h
@@ -1,61 +1,62 @@
#ifndef ASSIMP_FILELOGSTREAM_H_INC
#define ASSIMP_FILELOGSTREAM_H_INC
-#include "../include/assimp/LogStream.hpp"
-#include "../include/assimp/IOStream.hpp"
+#include <assimp/LogStream.hpp>
+#include <assimp/IOStream.hpp>
+#include "DefaultIOSystem.h"
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
-/** @class FileLogStream
- * @brief Logstream to write into a file.
+/** @class FileLogStream
+ * @brief Logstream to write into a file.
*/
class FileLogStream :
- public LogStream
+ public LogStream
{
public:
- FileLogStream( const char* file, IOSystem* io = NULL );
- ~FileLogStream();
- void write( const char* message );
+ FileLogStream( const char* file, IOSystem* io = NULL );
+ ~FileLogStream();
+ void write( const char* message );
private:
- IOStream *m_pStream;
+ IOStream *m_pStream;
};
// ----------------------------------------------------------------------------------
-// Constructor
+// Constructor
inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) :
- m_pStream(NULL)
+ m_pStream(NULL)
{
- if ( !file || 0 == *file )
- return;
+ 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" );
+ // 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
+// Destructor
inline FileLogStream::~FileLogStream()
{
- // The virtual d'tor should destroy the underlying file
- delete m_pStream;
+ // The virtual d'tor should destroy the underlying file
+ delete m_pStream;
}
// ----------------------------------------------------------------------------------
-// Write method
+// Write method
inline void FileLogStream::write( const char* message )
{
- if (m_pStream != NULL)
- {
- m_pStream->Write(message, sizeof(char), ::strlen(message));
- m_pStream->Flush();
- }
+ if (m_pStream != NULL)
+ {
+ m_pStream->Write(message, sizeof(char), ::strlen(message));
+ m_pStream->Flush();
+ }
}
// ----------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/FileSystemFilter.h b/src/3rdparty/assimp/code/FileSystemFilter.h
index 6f5d46065..3370589d6 100644
--- a/src/3rdparty/assimp/code/FileSystemFilter.h
+++ b/src/3rdparty/assimp/code/FileSystemFilter.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,257 +40,259 @@ 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 sucess rate of file opening ...
+ * in order to improve the success rate of file opening ...
*/
#ifndef AI_FILESYSTEMFILTER_H_INC
#define AI_FILESYSTEMFILTER_H_INC
#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/DefaultLogger.hpp"
#include "fast_atof.h"
#include "ParsingUtils.h"
-namespace Assimp {
+
+namespace Assimp {
inline bool IsHex(char s) {
- return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F');
+ return (s>='0' && s<='9') || (s>='a' && s<='f') || (s>='A' && s<='F');
}
// ---------------------------------------------------------------------------
-/** File system filter
+/** File system filter
*/
class FileSystemFilter : public IOSystem
{
public:
- /** Constructor. */
- FileSystemFilter(const std::string& file, IOSystem* old)
- : wrapped (old)
- , src_file (file)
- , sep(wrapped->getOsSeparator())
- {
- ai_assert(NULL != wrapped);
-
- // Determine base directory
- base = src_file;
- std::string::size_type ss2;
- if (std::string::npos != (ss2 = base.find_last_of("\\/"))) {
- base.erase(ss2,base.length()-ss2);
- }
- else {
- base = "";
- // return;
- }
-
- // make sure the directory is terminated properly
- char s;
-
- if (base.length() == 0) {
- base = ".";
- base += getOsSeparator();
- }
- else if ((s = *(base.end()-1)) != '\\' && s != '/') {
- base += getOsSeparator();
- }
-
- DefaultLogger::get()->info("Import root directory is \'" + base + "\'");
- }
-
- /** Destructor. */
- ~FileSystemFilter()
- {
- // haha
- }
-
- // -------------------------------------------------------------------
- /** Tests for the existence of a file at the given path. */
- bool Exists( const char* pFile) const
- {
- std::string tmp = pFile;
-
- // Currently this IOSystem is also used to open THE ONE FILE.
- if (tmp != src_file) {
- BuildPath(tmp);
- Cleanup(tmp);
- }
-
- return wrapped->Exists(tmp);
- }
-
- // -------------------------------------------------------------------
- /** Returns the directory separator. */
- char getOsSeparator() const
- {
- return sep;
- }
-
- // -------------------------------------------------------------------
- /** Open a new file with a given path. */
- IOStream* Open( const char* pFile, const char* pMode = "rb")
- {
- ai_assert(pFile);
- ai_assert(pMode);
-
- // First try the unchanged path
- IOStream* s = wrapped->Open(pFile,pMode);
-
- if (!s) {
- std::string tmp = pFile;
-
- // Try to convert between absolute and relative paths
- BuildPath(tmp);
- s = wrapped->Open(tmp,pMode);
-
- if (!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 = wrapped->Open(tmp,pMode);
- }
- }
-
- return s;
- }
-
- // -------------------------------------------------------------------
- /** Closes the given file and releases all resources associated with it. */
- void Close( IOStream* pFile)
- {
- return wrapped->Close(pFile);
- }
-
- // -------------------------------------------------------------------
- /** Compare two paths */
- bool ComparePaths (const char* one, const char* second) const
- {
- return wrapped->ComparePaths (one,second);
- }
+ /** Constructor. */
+ FileSystemFilter(const std::string& file, IOSystem* old)
+ : wrapped (old)
+ , src_file (file)
+ , sep(wrapped->getOsSeparator())
+ {
+ ai_assert(NULL != wrapped);
+
+ // Determine base directory
+ base = src_file;
+ std::string::size_type ss2;
+ if (std::string::npos != (ss2 = base.find_last_of("\\/"))) {
+ base.erase(ss2,base.length()-ss2);
+ }
+ else {
+ base = "";
+ // return;
+ }
+
+ // make sure the directory is terminated properly
+ char s;
+
+ if (base.length() == 0) {
+ base = ".";
+ base += getOsSeparator();
+ }
+ else if ((s = *(base.end()-1)) != '\\' && s != '/') {
+ base += getOsSeparator();
+ }
+
+ DefaultLogger::get()->info("Import root directory is \'" + base + "\'");
+ }
+
+ /** Destructor. */
+ ~FileSystemFilter()
+ {
+ // haha
+ }
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const
+ {
+ std::string tmp = pFile;
+
+ // Currently this IOSystem is also used to open THE ONE FILE.
+ if (tmp != src_file) {
+ BuildPath(tmp);
+ Cleanup(tmp);
+ }
+
+ return wrapped->Exists(tmp);
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const
+ {
+ return sep;
+ }
+
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open( const char* pFile, const char* pMode = "rb")
+ {
+ ai_assert(pFile);
+ ai_assert(pMode);
+
+ // First try the unchanged path
+ IOStream* s = wrapped->Open(pFile,pMode);
+
+ if (!s) {
+ std::string tmp = pFile;
+
+ // Try to convert between absolute and relative paths
+ BuildPath(tmp);
+ s = wrapped->Open(tmp,pMode);
+
+ if (!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 = wrapped->Open(tmp,pMode);
+ }
+ }
+
+ return s;
+ }
+
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile)
+ {
+ return wrapped->Close(pFile);
+ }
+
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths (const char* one, const char* second) const
+ {
+ return wrapped->ComparePaths (one,second);
+ }
private:
- // -------------------------------------------------------------------
- /** Build a valid path from a given relative or absolute path.
- */
- void BuildPath (std::string& in) const
- {
- // if we can already access the file, great.
- if (in.length() < 3 || wrapped->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 = base + in;
- if (wrapped->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 = base;
- tmp += sep;
-
- 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 (wrapped->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
- {
- char last = 0;
- if(in.empty()) {
- return;
- }
-
- // Remove a very common issue when we're parsing file names: spaces at the
- // beginning of the path.
- std::string::iterator it = in.begin();
- while (IsSpaceOrNewLine( *it ))++it;
- if (it != in.begin()) {
- in.erase(in.begin(),it+1);
- }
-
- const char sep = 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 = sep;
-
- // 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;
- }
- }
+ // -------------------------------------------------------------------
+ /** Build a valid path from a given relative or absolute path.
+ */
+ void BuildPath (std::string& in) const
+ {
+ // if we can already access the file, great.
+ if (in.length() < 3 || wrapped->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 = base + in;
+ if (wrapped->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 = base;
+ tmp += sep;
+
+ 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 (wrapped->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
+ {
+ char last = 0;
+ if(in.empty()) {
+ return;
+ }
+
+ // Remove a very common issue when we're parsing file names: spaces at the
+ // beginning of the path.
+ std::string::iterator it = in.begin();
+ while (IsSpaceOrNewLine( *it ))++it;
+ if (it != in.begin()) {
+ in.erase(in.begin(),it+1);
+ }
+
+ const char sep = 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 = sep;
+
+ // 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* wrapped;
- std::string src_file, base;
- char sep;
+ IOSystem* wrapped;
+ std::string src_file, base;
+ char sep;
};
} //!ns Assimp
diff --git a/src/3rdparty/assimp/code/FindDegenerates.cpp b/src/3rdparty/assimp/code/FindDegenerates.cpp
index 04ca92521..62750bfad 100644
--- a/src/3rdparty/assimp/code/FindDegenerates.cpp
+++ b/src/3rdparty/assimp/code/FindDegenerates.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,11 +43,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the FindDegenerates post-process step.
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "ProcessHelper.h"
#include "FindDegenerates.h"
+#include "Exceptional.h"
using namespace Assimp;
@@ -61,156 +62,156 @@ FindDegeneratesProcess::FindDegeneratesProcess()
// Destructor, private as well
FindDegeneratesProcess::~FindDegeneratesProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const
{
- return 0 != (pFlags & aiProcess_FindDegenerates);
+ return 0 != (pFlags & aiProcess_FindDegenerates);
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
void FindDegeneratesProcess::SetupProperties(const Importer* pImp)
{
- // Get the current value of AI_CONFIG_PP_FD_REMOVE
- configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
+ // Get the current value of AI_CONFIG_PP_FD_REMOVE
+ configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FindDegeneratesProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FindDegeneratesProcess begin");
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
- ExecuteOnMesh( pScene->mMeshes[i]);
- }
- DefaultLogger::get()->debug("FindDegeneratesProcess finished");
+ DefaultLogger::get()->debug("FindDegeneratesProcess begin");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
+ ExecuteOnMesh( pScene->mMeshes[i]);
+ }
+ DefaultLogger::get()->debug("FindDegeneratesProcess finished");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported mesh
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
{
- mesh->mPrimitiveTypes = 0;
-
- std::vector<bool> remove_me;
- if (configRemoveDegenerates)
- remove_me.resize(mesh->mNumFaces,false);
-
- unsigned int deg = 0, limit;
- for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
- {
- aiFace& face = mesh->mFaces[a];
- bool first = true;
-
- // check whether the face contains degenerated entries
- for (unsigned int i = 0; i < face.mNumIndices; ++i)
- {
- // Polygons with more than 4 points are allowed to have double points, that is
- // simulating polygons with holes just with concave polygons. However,
- // double points may not come directly after another.
- limit = face.mNumIndices;
- if (face.mNumIndices > 4)
- limit = std::min(limit,i+2);
-
- for (unsigned int t = i+1; t < limit; ++t)
- {
- if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
- {
- // we have found a matching vertex position
- // remove the corresponding index from the array
- --face.mNumIndices;--limit;
- for (unsigned int m = t; m < face.mNumIndices; ++m)
- {
- face.mIndices[m] = face.mIndices[m+1];
- }
- --t;
-
- // NOTE: we set the removed vertex index to an unique value
- // to make sure the developer gets notified when his
- // application attemps to access this data.
- face.mIndices[face.mNumIndices] = 0xdeadbeef;
-
- if(first)
- {
- ++deg;
- first = false;
- }
-
- if (configRemoveDegenerates) {
- remove_me[a] = true;
- goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
- }
- }
- }
- }
-
- // We need to update the primitive flags array of the mesh.
- switch (face.mNumIndices)
- {
- case 1u:
- mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
- break;
- case 2u:
- mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
- break;
- case 3u:
- mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- break;
- default:
- mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- break;
- };
+ mesh->mPrimitiveTypes = 0;
+
+ std::vector<bool> remove_me;
+ if (configRemoveDegenerates)
+ remove_me.resize(mesh->mNumFaces,false);
+
+ unsigned int deg = 0, limit;
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
+ {
+ aiFace& face = mesh->mFaces[a];
+ bool first = true;
+
+ // check whether the face contains degenerated entries
+ for (unsigned int i = 0; i < face.mNumIndices; ++i)
+ {
+ // Polygons with more than 4 points are allowed to have double points, that is
+ // simulating polygons with holes just with concave polygons. However,
+ // double points may not come directly after another.
+ limit = face.mNumIndices;
+ if (face.mNumIndices > 4)
+ limit = std::min(limit,i+2);
+
+ for (unsigned int t = i+1; t < limit; ++t)
+ {
+ if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
+ {
+ // we have found a matching vertex position
+ // remove the corresponding index from the array
+ --face.mNumIndices;--limit;
+ for (unsigned int m = t; m < face.mNumIndices; ++m)
+ {
+ face.mIndices[m] = face.mIndices[m+1];
+ }
+ --t;
+
+ // NOTE: we set the removed vertex index to an unique value
+ // to make sure the developer gets notified when his
+ // application attemps to access this data.
+ face.mIndices[face.mNumIndices] = 0xdeadbeef;
+
+ if(first)
+ {
+ ++deg;
+ first = false;
+ }
+
+ if (configRemoveDegenerates) {
+ remove_me[a] = true;
+ goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
+ }
+ }
+ }
+ }
+
+ // We need to update the primitive flags array of the mesh.
+ switch (face.mNumIndices)
+ {
+ case 1u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3u:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ };
evil_jump_outside:
- continue;
- }
-
- // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
- if (configRemoveDegenerates && deg) {
- unsigned int n = 0;
- for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
- {
- aiFace& face_src = mesh->mFaces[a];
- if (!remove_me[a]) {
- aiFace& face_dest = mesh->mFaces[n++];
-
- // Do a manual copy, keep the index array
- face_dest.mNumIndices = face_src.mNumIndices;
- face_dest.mIndices = face_src.mIndices;
-
- if (&face_src != &face_dest) {
- // clear source
- face_src.mNumIndices = 0;
- face_src.mIndices = NULL;
- }
- }
- else {
- // Otherwise delete it if we don't need this face
- delete[] face_src.mIndices;
- face_src.mIndices = NULL;
- face_src.mNumIndices = 0;
- }
- }
- // Just leave the rest of the array unreferenced, we don't care for now
- mesh->mNumFaces = n;
- if (!mesh->mNumFaces) {
- // WTF!?
- // OK ... for completeness and because I'm not yet tired,
- // let's write code that willl hopefully never be called
- // (famous last words)
-
- // OK ... bad idea.
- throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
- }
- }
-
- if (deg && !DefaultLogger::isNullLogger())
- {
- char s[64];
- ASSIMP_itoa10(s,deg);
- DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
- }
+ continue;
+ }
+
+ // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
+ if (configRemoveDegenerates && deg) {
+ unsigned int n = 0;
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
+ {
+ aiFace& face_src = mesh->mFaces[a];
+ if (!remove_me[a]) {
+ aiFace& face_dest = mesh->mFaces[n++];
+
+ // Do a manual copy, keep the index array
+ face_dest.mNumIndices = face_src.mNumIndices;
+ face_dest.mIndices = face_src.mIndices;
+
+ if (&face_src != &face_dest) {
+ // clear source
+ face_src.mNumIndices = 0;
+ face_src.mIndices = NULL;
+ }
+ }
+ else {
+ // Otherwise delete it if we don't need this face
+ delete[] face_src.mIndices;
+ face_src.mIndices = NULL;
+ face_src.mNumIndices = 0;
+ }
+ }
+ // Just leave the rest of the array unreferenced, we don't care for now
+ mesh->mNumFaces = n;
+ if (!mesh->mNumFaces) {
+ // WTF!?
+ // OK ... for completeness and because I'm not yet tired,
+ // let's write code that willl hopefully never be called
+ // (famous last words)
+
+ // OK ... bad idea.
+ throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
+ }
+ }
+
+ if (deg && !DefaultLogger::isNullLogger())
+ {
+ char s[64];
+ ASSIMP_itoa10(s,deg);
+ DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
+ }
}
diff --git a/src/3rdparty/assimp/code/FindDegenerates.h b/src/3rdparty/assimp/code/FindDegenerates.h
index 35703a49b..7b945ea3a 100644
--- a/src/3rdparty/assimp/code/FindDegenerates.h
+++ b/src/3rdparty/assimp/code/FindDegenerates.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,10 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_FINDDEGENERATESPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
class FindDegeneratesProcessTest;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
@@ -57,48 +57,48 @@ class ASSIMP_API FindDegeneratesProcess : public BaseProcess
{
public:
- FindDegeneratesProcess();
- ~FindDegeneratesProcess();
+ FindDegeneratesProcess();
+ ~FindDegeneratesProcess();
public:
-
- // -------------------------------------------------------------------
- // Check whether step is active
- bool IsActive( unsigned int pFlags) const;
-
- // -------------------------------------------------------------------
- // Execute step on a given scene
- void Execute( aiScene* pScene);
-
- // -------------------------------------------------------------------
- // Setup import settings
- void SetupProperties(const Importer* pImp);
-
- // -------------------------------------------------------------------
- // Execute step on a given mesh
- void ExecuteOnMesh( aiMesh* mesh);
-
-
- // -------------------------------------------------------------------
- /** @brief Enable the instant removal of degenerated primitives
- * @param d hm ... difficult to guess what this means, hu!?
- */
- void EnableInstantRemoval(bool d) {
- configRemoveDegenerates = d;
- }
-
- // -------------------------------------------------------------------
- /** @brief Check whether instant removal is currently enabled
- * @return ...
- */
- bool IsInstantRemoval() const {
- return configRemoveDegenerates;
- }
+
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ // Execute step on a given mesh
+ void ExecuteOnMesh( aiMesh* mesh);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Enable the instant removal of degenerated primitives
+ * @param d hm ... difficult to guess what this means, hu!?
+ */
+ void EnableInstantRemoval(bool d) {
+ configRemoveDegenerates = d;
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Check whether instant removal is currently enabled
+ * @return ...
+ */
+ bool IsInstantRemoval() const {
+ return configRemoveDegenerates;
+ }
private:
- //! Configuration option: remove degenerates faces immediately
- bool configRemoveDegenerates;
+ //! Configuration option: remove degenerates faces immediately
+ bool configRemoveDegenerates;
};
}
diff --git a/src/3rdparty/assimp/code/FindInstancesProcess.cpp b/src/3rdparty/assimp/code/FindInstancesProcess.cpp
index c857bb21d..479f6561e 100644
--- a/src/3rdparty/assimp/code/FindInstancesProcess.cpp
+++ b/src/3rdparty/assimp/code/FindInstancesProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,15 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the aiProcess_FindInstances postprocessing step
*/
-#include "AssimpPCH.h"
+
#include "FindInstancesProcess.h"
+#include <memory>
+#include <stdio.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindInstancesProcess::FindInstancesProcess()
-: configSpeedFlag (false)
+: configSpeedFlag (false)
{}
// ------------------------------------------------------------------------------------------------
@@ -63,215 +65,213 @@ FindInstancesProcess::~FindInstancesProcess()
// Returns whether the processing step is present in the given flag field.
bool FindInstancesProcess::IsActive( unsigned int pFlags) const
{
- // FindInstances makes absolutely no sense together with PreTransformVertices
- // fixme: spawn error message somewhere else?
- return 0 != (pFlags & aiProcess_FindInstances) && 0 == (pFlags & aiProcess_PreTransformVertices);
+ // FindInstances makes absolutely no sense together with PreTransformVertices
+ // fixme: spawn error message somewhere else?
+ return 0 != (pFlags & aiProcess_FindInstances) && 0 == (pFlags & aiProcess_PreTransformVertices);
}
// ------------------------------------------------------------------------------------------------
// Setup properties for the step
void FindInstancesProcess::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_FAVOUR_SPEED
- configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+ // AI_CONFIG_FAVOUR_SPEED
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
}
// ------------------------------------------------------------------------------------------------
// Compare the bones of two meshes
bool CompareBones(const aiMesh* orig, const aiMesh* inst)
{
- for (unsigned int i = 0; i < orig->mNumBones;++i) {
- aiBone* aha = orig->mBones[i];
- aiBone* oha = inst->mBones[i];
-
- if (aha->mNumWeights != oha->mNumWeights ||
- aha->mOffsetMatrix != oha->mOffsetMatrix ||
- aha->mNumWeights != oha->mNumWeights) {
- return false;
- }
-
- // compare weight per weight ---
- for (unsigned int n = 0; n < aha->mNumWeights;++n) {
- if (aha->mWeights[n].mVertexId != oha->mWeights[n].mVertexId ||
- (aha->mWeights[n].mWeight - oha->mWeights[n].mWeight) < 10e-3f) {
- return false;
- }
- }
- }
- return true;
+ for (unsigned int i = 0; i < orig->mNumBones;++i) {
+ aiBone* aha = orig->mBones[i];
+ aiBone* oha = inst->mBones[i];
+
+ if (aha->mNumWeights != oha->mNumWeights ||
+ aha->mOffsetMatrix != oha->mOffsetMatrix) {
+ return false;
+ }
+
+ // compare weight per weight ---
+ for (unsigned int n = 0; n < aha->mNumWeights;++n) {
+ if (aha->mWeights[n].mVertexId != oha->mWeights[n].mVertexId ||
+ (aha->mWeights[n].mWeight - oha->mWeights[n].mWeight) < 10e-3f) {
+ return false;
+ }
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Update mesh indices in the node graph
void UpdateMeshIndices(aiNode* node, unsigned int* lookup)
{
- for (unsigned int n = 0; n < node->mNumMeshes;++n)
- node->mMeshes[n] = lookup[node->mMeshes[n]];
+ for (unsigned int n = 0; n < node->mNumMeshes;++n)
+ node->mMeshes[n] = lookup[node->mMeshes[n]];
- for (unsigned int n = 0; n < node->mNumChildren;++n)
- UpdateMeshIndices(node->mChildren[n],lookup);
+ for (unsigned int n = 0; n < node->mNumChildren;++n)
+ UpdateMeshIndices(node->mChildren[n],lookup);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FindInstancesProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FindInstancesProcess begin");
- if (pScene->mNumMeshes) {
-
- // use a pseudo hash for all meshes in the scene to quickly find
- // the ones which are possibly equal. This step is executed early
- // in the pipeline, so we could, depending on the file format,
- // have several thousand small meshes. That's too much for a brute
- // everyone-against-everyone check involving up to 10 comparisons
- // each.
- boost::scoped_array<uint64_t> hashes (new uint64_t[pScene->mNumMeshes]);
- boost::scoped_array<unsigned int> remapping (new unsigned int[pScene->mNumMeshes]);
-
- unsigned int numMeshesOut = 0;
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
-
- aiMesh* inst = pScene->mMeshes[i];
- hashes[i] = GetMeshHash(inst);
-
- for (int a = i-1; a >= 0; --a) {
- if (hashes[i] == hashes[a])
- {
- aiMesh* orig = pScene->mMeshes[a];
- if (!orig)
- continue;
-
- // check for hash collision .. we needn't check
- // the vertex format, it *must* match due to the
- // (brilliant) construction of the hash
- if (orig->mNumBones != inst->mNumBones ||
- orig->mNumFaces != inst->mNumFaces ||
- orig->mNumVertices != inst->mNumVertices ||
- orig->mMaterialIndex != inst->mMaterialIndex ||
- orig->mPrimitiveTypes != inst->mPrimitiveTypes)
- continue;
-
- // up to now the meshes are equal. find an appropriate
- // epsilon to compare position differences against
- float epsilon = ComputePositionEpsilon(inst);
- epsilon *= epsilon;
-
- // now compare vertex positions, normals,
- // tangents and bitangents using this epsilon.
- if (orig->HasPositions()) {
- if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))
- continue;
- }
- if (orig->HasNormals()) {
- if(!CompareArrays(orig->mNormals,inst->mNormals,orig->mNumVertices,epsilon))
- continue;
- }
- if (orig->HasTangentsAndBitangents()) {
- if (!CompareArrays(orig->mTangents,inst->mTangents,orig->mNumVertices,epsilon) ||
- !CompareArrays(orig->mBitangents,inst->mBitangents,orig->mNumVertices,epsilon))
- continue;
- }
-
- // use a constant epsilon for colors and UV coordinates
- static const float uvEpsilon = 10e-4f;
-
- {
- unsigned int i, end = orig->GetNumUVChannels();
- for(i = 0; i < end; ++i) {
- if (!orig->mTextureCoords[i]) {
- continue;
- }
- if(!CompareArrays(orig->mTextureCoords[i],inst->mTextureCoords[i],orig->mNumVertices,uvEpsilon)) {
- break;
- }
- }
- if (i != end) {
- continue;
- }
- }
- {
- unsigned int i, end = orig->GetNumColorChannels();
- for(i = 0; i < end; ++i) {
- if (!orig->mColors[i]) {
- continue;
- }
- if(!CompareArrays(orig->mColors[i],inst->mColors[i],orig->mNumVertices,uvEpsilon)) {
- break;
- }
- }
- if (i != end) {
- continue;
- }
- }
-
- // These two checks are actually quite expensive and almost *never* required.
- // Almost. That's why they're still here. But there's no reason to do them
- // in speed-targeted imports.
- if (!configSpeedFlag) {
-
- // It seems to be strange, but we really need to check whether the
- // bones are identical too. Although it's extremely unprobable
- // that they're not if control reaches here, we need to deal
- // with unprobable cases, too. It could still be that there are
- // equal shapes which are deformed differently.
- if (!CompareBones(orig,inst))
- continue;
-
- // For completeness ... compare even the index buffers for equality
- // face order & winding order doesn't care. Input data is in verbose format.
- boost::scoped_array<unsigned int> ftbl_orig(new unsigned int[orig->mNumVertices]);
- boost::scoped_array<unsigned int> ftbl_inst(new unsigned int[orig->mNumVertices]);
-
- for (unsigned int tt = 0; tt < orig->mNumFaces;++tt) {
- aiFace& f = orig->mFaces[tt];
- for (unsigned int nn = 0; nn < f.mNumIndices;++nn)
- ftbl_orig[f.mIndices[nn]] = tt;
-
- aiFace& f2 = inst->mFaces[tt];
- for (unsigned int nn = 0; nn < f2.mNumIndices;++nn)
- ftbl_inst[f2.mIndices[nn]] = tt;
- }
- if (0 != ::memcmp(ftbl_inst.get(),ftbl_orig.get(),orig->mNumVertices*sizeof(unsigned int)))
- continue;
- }
-
- // We're still here. Or in other words: 'inst' is an instance of 'orig'.
- // Place a marker in our list that we can easily update mesh indices.
- remapping[i] = remapping[a];
-
- // Delete the instanced mesh, we don't need it anymore
- delete inst;
- pScene->mMeshes[i] = NULL;
- break;
- }
- }
-
- // If we didn't find a match for the current mesh: keep it
- if (pScene->mMeshes[i]) {
- remapping[i] = numMeshesOut++;
- }
- }
- ai_assert(0 != numMeshesOut);
- if (numMeshesOut != pScene->mNumMeshes) {
-
- // Collapse the meshes array by removing all NULL entries
- for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
- if (pScene->mMeshes[i])
- pScene->mMeshes[real++] = pScene->mMeshes[i];
- }
-
- // And update the nodegraph with our nice lookup table
- UpdateMeshIndices(pScene->mRootNode,remapping.get());
-
- // write to log
- if (!DefaultLogger::isNullLogger()) {
-
- char buffer[512];
- ::sprintf(buffer,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut);
- DefaultLogger::get()->info(buffer);
- }
- pScene->mNumMeshes = numMeshesOut;
- }
- else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found");
- }
+ DefaultLogger::get()->debug("FindInstancesProcess begin");
+ if (pScene->mNumMeshes) {
+
+ // use a pseudo hash for all meshes in the scene to quickly find
+ // the ones which are possibly equal. This step is executed early
+ // in the pipeline, so we could, depending on the file format,
+ // have several thousand small meshes. That's too much for a brute
+ // everyone-against-everyone check involving up to 10 comparisons
+ // each.
+ std::unique_ptr<uint64_t[]> hashes (new uint64_t[pScene->mNumMeshes]);
+ std::unique_ptr<unsigned int[]> remapping (new unsigned int[pScene->mNumMeshes]);
+
+ unsigned int numMeshesOut = 0;
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+
+ aiMesh* inst = pScene->mMeshes[i];
+ hashes[i] = GetMeshHash(inst);
+
+ for (int a = i-1; a >= 0; --a) {
+ if (hashes[i] == hashes[a])
+ {
+ aiMesh* orig = pScene->mMeshes[a];
+ if (!orig)
+ continue;
+
+ // check for hash collision .. we needn't check
+ // the vertex format, it *must* match due to the
+ // (brilliant) construction of the hash
+ if (orig->mNumBones != inst->mNumBones ||
+ orig->mNumFaces != inst->mNumFaces ||
+ orig->mNumVertices != inst->mNumVertices ||
+ orig->mMaterialIndex != inst->mMaterialIndex ||
+ orig->mPrimitiveTypes != inst->mPrimitiveTypes)
+ continue;
+
+ // up to now the meshes are equal. find an appropriate
+ // epsilon to compare position differences against
+ float epsilon = ComputePositionEpsilon(inst);
+ epsilon *= epsilon;
+
+ // now compare vertex positions, normals,
+ // tangents and bitangents using this epsilon.
+ if (orig->HasPositions()) {
+ if(!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon))
+ continue;
+ }
+ if (orig->HasNormals()) {
+ if(!CompareArrays(orig->mNormals,inst->mNormals,orig->mNumVertices,epsilon))
+ continue;
+ }
+ if (orig->HasTangentsAndBitangents()) {
+ if (!CompareArrays(orig->mTangents,inst->mTangents,orig->mNumVertices,epsilon) ||
+ !CompareArrays(orig->mBitangents,inst->mBitangents,orig->mNumVertices,epsilon))
+ continue;
+ }
+
+ // use a constant epsilon for colors and UV coordinates
+ static const float uvEpsilon = 10e-4f;
+ {
+ unsigned int i, end = orig->GetNumUVChannels();
+ for(i = 0; i < end; ++i) {
+ if (!orig->mTextureCoords[i]) {
+ continue;
+ }
+ if(!CompareArrays(orig->mTextureCoords[i],inst->mTextureCoords[i],orig->mNumVertices,uvEpsilon)) {
+ break;
+ }
+ }
+ if (i != end) {
+ continue;
+ }
+ }
+ {
+ unsigned int i, end = orig->GetNumColorChannels();
+ for(i = 0; i < end; ++i) {
+ if (!orig->mColors[i]) {
+ continue;
+ }
+ if(!CompareArrays(orig->mColors[i],inst->mColors[i],orig->mNumVertices,uvEpsilon)) {
+ break;
+ }
+ }
+ if (i != end) {
+ continue;
+ }
+ }
+
+ // These two checks are actually quite expensive and almost *never* required.
+ // Almost. That's why they're still here. But there's no reason to do them
+ // in speed-targeted imports.
+ if (!configSpeedFlag) {
+
+ // It seems to be strange, but we really need to check whether the
+ // bones are identical too. Although it's extremely unprobable
+ // that they're not if control reaches here, we need to deal
+ // with unprobable cases, too. It could still be that there are
+ // equal shapes which are deformed differently.
+ if (!CompareBones(orig,inst))
+ continue;
+
+ // For completeness ... compare even the index buffers for equality
+ // face order & winding order doesn't care. Input data is in verbose format.
+ std::unique_ptr<unsigned int[]> ftbl_orig(new unsigned int[orig->mNumVertices]);
+ std::unique_ptr<unsigned int[]> ftbl_inst(new unsigned int[orig->mNumVertices]);
+
+ for (unsigned int tt = 0; tt < orig->mNumFaces;++tt) {
+ aiFace& f = orig->mFaces[tt];
+ for (unsigned int nn = 0; nn < f.mNumIndices;++nn)
+ ftbl_orig[f.mIndices[nn]] = tt;
+
+ aiFace& f2 = inst->mFaces[tt];
+ for (unsigned int nn = 0; nn < f2.mNumIndices;++nn)
+ ftbl_inst[f2.mIndices[nn]] = tt;
+ }
+ if (0 != ::memcmp(ftbl_inst.get(),ftbl_orig.get(),orig->mNumVertices*sizeof(unsigned int)))
+ continue;
+ }
+
+ // We're still here. Or in other words: 'inst' is an instance of 'orig'.
+ // Place a marker in our list that we can easily update mesh indices.
+ remapping[i] = remapping[a];
+
+ // Delete the instanced mesh, we don't need it anymore
+ delete inst;
+ pScene->mMeshes[i] = NULL;
+ break;
+ }
+ }
+
+ // If we didn't find a match for the current mesh: keep it
+ if (pScene->mMeshes[i]) {
+ remapping[i] = numMeshesOut++;
+ }
+ }
+ ai_assert(0 != numMeshesOut);
+ if (numMeshesOut != pScene->mNumMeshes) {
+
+ // Collapse the meshes array by removing all NULL entries
+ for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) {
+ if (pScene->mMeshes[i])
+ pScene->mMeshes[real++] = pScene->mMeshes[i];
+ }
+
+ // And update the node graph with our nice lookup table
+ UpdateMeshIndices(pScene->mRootNode,remapping.get());
+
+ // write to log
+ if (!DefaultLogger::isNullLogger()) {
+
+ char buffer[512];
+ ::ai_snprintf(buffer,512,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut);
+ DefaultLogger::get()->info(buffer);
+ }
+ pScene->mNumMeshes = numMeshesOut;
+ }
+ else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found");
+ }
}
diff --git a/src/3rdparty/assimp/code/FindInstancesProcess.h b/src/3rdparty/assimp/code/FindInstancesProcess.h
index eecdad272..14876045c 100644
--- a/src/3rdparty/assimp/code/FindInstancesProcess.h
+++ b/src/3rdparty/assimp/code/FindInstancesProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ProcessHelper.h"
class FindInstancesProcessTest;
-namespace Assimp {
+namespace Assimp {
// -------------------------------------------------------------------------------
/** @brief Get a pseudo(!)-hash representing a mesh.
@@ -56,20 +56,20 @@ namespace Assimp {
* The hash is built from number of vertices, faces, primitive types,
* .... but *not* from the real mesh data. The funcction is not a perfect hash.
* @param in Input mesh
- * @return Hash.
+ * @return Hash.
*/
-inline uint64_t GetMeshHash(aiMesh* in)
+inline uint64_t GetMeshHash(aiMesh* in)
{
- ai_assert(NULL != in);
+ ai_assert(NULL != in);
- // ... get an unique value representing the vertex format of the mesh
- const unsigned int fhash = GetMeshVFormatUnique(in);
+ // ... get an unique value representing the vertex format of the mesh
+ const unsigned int fhash = GetMeshVFormatUnique(in);
- // and bake it with number of vertices/faces/bones/matidx/ptypes
- return ((uint64_t)fhash << 32u) | ((
- (in->mNumBones << 16u) ^ (in->mNumVertices) ^
- (in->mNumFaces<<4u) ^ (in->mMaterialIndex<<15) ^
- (in->mPrimitiveTypes<<28)) & 0xffffffff );
+ // and bake it with number of vertices/faces/bones/matidx/ptypes
+ return ((uint64_t)fhash << 32u) | ((
+ (in->mNumBones << 16u) ^ (in->mNumVertices) ^
+ (in->mNumFaces<<4u) ^ (in->mMaterialIndex<<15) ^
+ (in->mPrimitiveTypes<<28)) & 0xffffffff );
}
// -------------------------------------------------------------------------------
@@ -81,25 +81,25 @@ inline uint64_t GetMeshHash(aiMesh* in)
* @param e Epsilon
* @return true if the arrays are identical
*/
-inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
- unsigned int size, float e)
+inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second,
+ unsigned int size, float e)
{
- for (const aiVector3D* end = first+size; first != end; ++first,++second) {
- if ( (*first - *second).SquareLength() >= e)
- return false;
- }
- return true;
+ for (const aiVector3D* end = first+size; first != end; ++first,++second) {
+ if ( (*first - *second).SquareLength() >= e)
+ return false;
+ }
+ return true;
}
// and the same for colors ...
-inline bool CompareArrays(const aiColor4D* first, const aiColor4D* second,
- unsigned int size, float e)
+inline bool CompareArrays(const aiColor4D* first, const aiColor4D* second,
+ unsigned int size, float e)
{
- for (const aiColor4D* end = first+size; first != end; ++first,++second) {
- if ( GetColorDifference(*first,*second) >= e)
- return false;
- }
- return true;
+ for (const aiColor4D* end = first+size; first != end; ++first,++second) {
+ if ( GetColorDifference(*first,*second) >= e)
+ return false;
+ }
+ return true;
}
// ---------------------------------------------------------------------------
@@ -109,25 +109,25 @@ class FindInstancesProcess : public BaseProcess
{
public:
- FindInstancesProcess();
- ~FindInstancesProcess();
+ FindInstancesProcess();
+ ~FindInstancesProcess();
public:
- // -------------------------------------------------------------------
- // Check whether step is active in given flags combination
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ // Check whether step is active in given flags combination
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- // Execute step on a given scene
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
- // -------------------------------------------------------------------
- // Setup properties prior to executing the process
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ // Setup properties prior to executing the process
+ void SetupProperties(const Importer* pImp);
private:
- bool configSpeedFlag;
+ bool configSpeedFlag;
}; // ! end class FindInstancesProcess
} // ! end namespace Assimp
diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
index ba478109f..bb87f8dd8 100644
--- a/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -42,177 +42,181 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Defines a post processing step to search an importer's output
for data that is obviously invalid */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
// internal headers
#include "FindInvalidDataProcess.h"
#include "ProcessHelper.h"
+#include "Macros.h"
+#include "Exceptional.h"
+#include "qnan.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
FindInvalidDataProcess::FindInvalidDataProcess()
+ : configEpsilon(0.0f)
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FindInvalidDataProcess::~FindInvalidDataProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const
{
- return 0 != (pFlags & aiProcess_FindInvalidData);
+ return 0 != (pFlags & aiProcess_FindInvalidData);
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
void FindInvalidDataProcess::SetupProperties(const Importer* pImp)
{
- // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY
- configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f));
+ // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY
+ configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f));
}
// ------------------------------------------------------------------------------------------------
// Update mesh references in the node graph
void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMapping)
{
- if (node->mNumMeshes) {
- unsigned int out = 0;
- for (unsigned int a = 0; a < node->mNumMeshes;++a) {
-
- unsigned int ref = node->mMeshes[a];
- if (UINT_MAX != (ref = meshMapping[ref])) {
- node->mMeshes[out++] = ref;
- }
- }
- // just let the members that are unused, that's much cheaper
- // than a full array realloc'n'copy party ...
- if(!(node->mNumMeshes = out)) {
-
- delete[] node->mMeshes;
- node->mMeshes = NULL;
- }
- }
- // recursively update all children
- for (unsigned int i = 0; i < node->mNumChildren;++i) {
- UpdateMeshReferences(node->mChildren[i],meshMapping);
- }
+ if (node->mNumMeshes) {
+ unsigned int out = 0;
+ for (unsigned int a = 0; a < node->mNumMeshes;++a) {
+
+ unsigned int ref = node->mMeshes[a];
+ if (UINT_MAX != (ref = meshMapping[ref])) {
+ node->mMeshes[out++] = ref;
+ }
+ }
+ // just let the members that are unused, that's much cheaper
+ // than a full array realloc'n'copy party ...
+ if(!(node->mNumMeshes = out)) {
+
+ delete[] node->mMeshes;
+ node->mMeshes = NULL;
+ }
+ }
+ // recursively update all children
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ UpdateMeshReferences(node->mChildren[i],meshMapping);
+ }
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FindInvalidDataProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FindInvalidDataProcess begin");
-
- bool out = false;
- std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
- unsigned int real = 0;
-
- // Process meshes
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
-
- int result;
- if ((result = ProcessMesh( pScene->mMeshes[a]))) {
- out = true;
-
- if (2 == result) {
- // remove this mesh
- delete pScene->mMeshes[a];
- AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
-
- meshMapping[a] = UINT_MAX;
- continue;
- }
- }
- pScene->mMeshes[real] = pScene->mMeshes[a];
- meshMapping[a] = real++;
- }
-
- // Process animations
- for (unsigned int a = 0; a < pScene->mNumAnimations;++a) {
- ProcessAnimation( pScene->mAnimations[a]);
- }
-
-
- if (out) {
- if ( real != pScene->mNumMeshes) {
- if (!real) {
- throw DeadlyImportError("No meshes remaining");
- }
-
- // we need to remove some meshes.
- // therefore we'll also need to remove all references
- // to them from the scenegraph
- UpdateMeshReferences(pScene->mRootNode,meshMapping);
- pScene->mNumMeshes = real;
- }
-
- DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ...");
- }
- else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK.");
+ DefaultLogger::get()->debug("FindInvalidDataProcess begin");
+
+ bool out = false;
+ std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
+ unsigned int real = 0;
+
+ // Process meshes
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+
+ int result;
+ if ((result = ProcessMesh( pScene->mMeshes[a]))) {
+ out = true;
+
+ if (2 == result) {
+ // remove this mesh
+ delete pScene->mMeshes[a];
+ AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
+
+ meshMapping[a] = UINT_MAX;
+ continue;
+ }
+ }
+ pScene->mMeshes[real] = pScene->mMeshes[a];
+ meshMapping[a] = real++;
+ }
+
+ // Process animations
+ for (unsigned int a = 0; a < pScene->mNumAnimations;++a) {
+ ProcessAnimation( pScene->mAnimations[a]);
+ }
+
+
+ if (out) {
+ if ( real != pScene->mNumMeshes) {
+ if (!real) {
+ throw DeadlyImportError("No meshes remaining");
+ }
+
+ // we need to remove some meshes.
+ // therefore we'll also need to remove all references
+ // to them from the scenegraph
+ UpdateMeshReferences(pScene->mRootNode,meshMapping);
+ pScene->mNumMeshes = real;
+ }
+
+ DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ...");
+ }
+ else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK.");
}
// ------------------------------------------------------------------------------------------------
template <typename T>
inline const char* ValidateArrayContents(const T* arr, unsigned int size,
- const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
+ const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
{
- return NULL;
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
template <>
inline const char* ValidateArrayContents<aiVector3D>(const aiVector3D* arr, unsigned int size,
- const std::vector<bool>& dirtyMask, bool mayBeIdentical , bool mayBeZero )
+ const std::vector<bool>& dirtyMask, bool mayBeIdentical , bool mayBeZero )
{
- bool b = false;
- unsigned int cnt = 0;
- for (unsigned int i = 0; i < size;++i) {
-
- if (dirtyMask.size() && dirtyMask[i]) {
- continue;
- }
- ++cnt;
-
- const aiVector3D& v = arr[i];
- if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) {
- return "INF/NAN was found in a vector component";
- }
- if (!mayBeZero && !v.x && !v.y && !v.z ) {
- return "Found zero-length vector";
- }
- if (i && v != arr[i-1])b = true;
- }
- if (cnt > 1 && !b && !mayBeIdentical) {
- return "All vectors are identical";
- }
- return NULL;
+ bool b = false;
+ unsigned int cnt = 0;
+ for (unsigned int i = 0; i < size;++i) {
+
+ if (dirtyMask.size() && dirtyMask[i]) {
+ continue;
+ }
+ ++cnt;
+
+ const aiVector3D& v = arr[i];
+ if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) {
+ return "INF/NAN was found in a vector component";
+ }
+ if (!mayBeZero && !v.x && !v.y && !v.z ) {
+ return "Found zero-length vector";
+ }
+ if (i && v != arr[i-1])b = true;
+ }
+ if (cnt > 1 && !b && !mayBeIdentical) {
+ return "All vectors are identical";
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
template <typename T>
inline bool ProcessArray(T*& in, unsigned int num,const char* name,
- const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
+ const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
{
- const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
- if (err) {
- DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err);
-
- delete[] in;
- in = NULL;
- return true;
- }
- return false;
+ const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
+ if (err) {
+ DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err);
+
+ delete[] in;
+ in = NULL;
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
@@ -221,198 +225,198 @@ AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon);
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) {
- return std::fabs(n-s)>epsilon;
+ return std::fabs(n-s)>epsilon;
}
// ------------------------------------------------------------------------------------------------
template <>
-bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, float epsilon) {
- return
- EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
- EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
- EpsilonCompare(n.mValue.z,s.mValue.z,epsilon);
+bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, float epsilon) {
+ return
+ EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
+ EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
+ EpsilonCompare(n.mValue.z,s.mValue.z,epsilon);
}
// ------------------------------------------------------------------------------------------------
template <>
-bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float epsilon) {
- return
- EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
- EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
- EpsilonCompare(n.mValue.z,s.mValue.z,epsilon) &&
- EpsilonCompare(n.mValue.w,s.mValue.w,epsilon);
+bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float epsilon) {
+ return
+ EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
+ EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
+ EpsilonCompare(n.mValue.z,s.mValue.z,epsilon) &&
+ EpsilonCompare(n.mValue.w,s.mValue.w,epsilon);
}
// ------------------------------------------------------------------------------------------------
template <typename T>
inline bool AllIdentical(T* in, unsigned int num, float epsilon)
{
- if (num <= 1) {
- return true;
- }
-
- if (epsilon > 0.f) {
- for (unsigned int i = 0; i < num-1;++i) {
-
- if (!EpsilonCompare(in[i],in[i+1],epsilon)) {
- return false;
- }
- }
- }
- else {
- for (unsigned int i = 0; i < num-1;++i) {
-
- if (in[i] != in[i+1]) {
- return false;
- }
- }
- }
- return true;
+ if (num <= 1) {
+ return true;
+ }
+
+ if (epsilon > 0.f) {
+ for (unsigned int i = 0; i < num-1;++i) {
+
+ if (!EpsilonCompare(in[i],in[i+1],epsilon)) {
+ return false;
+ }
+ }
+ }
+ else {
+ for (unsigned int i = 0; i < num-1;++i) {
+
+ if (in[i] != in[i+1]) {
+ return false;
+ }
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Search an animation for invalid content
void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim)
{
- // Process all animation channels
- for (unsigned int a = 0; a < anim->mNumChannels;++a) {
- ProcessAnimationChannel( anim->mChannels[a]);
- }
+ // Process all animation channels
+ for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+ ProcessAnimationChannel( anim->mChannels[a]);
+ }
}
// ------------------------------------------------------------------------------------------------
void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
{
- int i = 0;
-
- // ScenePreprocessor's work ...
- ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys));
-
- // Check whether all values in a tracks are identical - in this case
- // we can remove al keys except one.
- // POSITIONS
- if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon))
- {
- aiVectorKey v = anim->mPositionKeys[0];
-
- // Reallocate ... we need just ONE element, it makes no sense to reuse the array
- delete[] anim->mPositionKeys;
- anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
- anim->mPositionKeys[0] = v;
- i = 1;
- }
-
- // ROTATIONS
- if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon))
- {
- aiQuatKey v = anim->mRotationKeys[0];
-
- // Reallocate ... we need just ONE element, it makes no sense to reuse the array
- delete[] anim->mRotationKeys;
- anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
- anim->mRotationKeys[0] = v;
- i = 1;
- }
-
- // SCALINGS
- if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon))
- {
- aiVectorKey v = anim->mScalingKeys[0];
-
- // Reallocate ... we need just ONE element, it makes no sense to reuse the array
- delete[] anim->mScalingKeys;
- anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
- anim->mScalingKeys[0] = v;
- i = 1;
- }
- if (1 == i)
- DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
+ int i = 0;
+
+ // ScenePreprocessor's work ...
+ ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys));
+
+ // Check whether all values in a tracks are identical - in this case
+ // we can remove al keys except one.
+ // POSITIONS
+ if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon))
+ {
+ aiVectorKey v = anim->mPositionKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mPositionKeys;
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
+ anim->mPositionKeys[0] = v;
+ i = 1;
+ }
+
+ // ROTATIONS
+ if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon))
+ {
+ aiQuatKey v = anim->mRotationKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mRotationKeys;
+ anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
+ anim->mRotationKeys[0] = v;
+ i = 1;
+ }
+
+ // SCALINGS
+ if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon))
+ {
+ aiVectorKey v = anim->mScalingKeys[0];
+
+ // Reallocate ... we need just ONE element, it makes no sense to reuse the array
+ delete[] anim->mScalingKeys;
+ anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
+ anim->mScalingKeys[0] = v;
+ i = 1;
+ }
+ if (1 == i)
+ DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
}
// ------------------------------------------------------------------------------------------------
// Search a mesh for invalid contents
int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
{
- bool ret = false;
- std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false));
-
- // Ignore elements that are not referenced by vertices.
- // (they are, for example, caused by the FindDegenerates step)
- for (unsigned int m = 0; m < pMesh->mNumFaces;++m) {
- const aiFace& f = pMesh->mFaces[m];
-
- for (unsigned int i = 0; i < f.mNumIndices;++i) {
- dirtyMask[f.mIndices[i]] = false;
- }
- }
-
- // Process vertex positions
- if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) {
- DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
- return 2;
- }
-
- // process texture coordinates
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i) {
- if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask)) {
-
- // delete all subsequent texture coordinate sets.
- for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
- delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL;
- }
- ret = true;
- }
- }
-
- // -- we don't validate vertex colors, it's difficult to say whether
- // they are invalid or not.
-
- // Normals and tangents are undefined for point and line faces.
- if (pMesh->mNormals || pMesh->mTangents) {
-
- if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
- aiPrimitiveType_LINE & pMesh->mPrimitiveTypes)
- {
- if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
- aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
- {
- // We need to update the lookup-table
- for (unsigned int m = 0; m < pMesh->mNumFaces;++m)
- {
- const aiFace& f = pMesh->mFaces[m];
-
- if (f.mNumIndices < 3) {
- dirtyMask[f.mIndices[0]] = true;
-
- if (f.mNumIndices == 2) {
- dirtyMask[f.mIndices[1]] = true;
- }
- }
- }
- }
- // Normals, tangents and bitangents are undefined for
- // the whole mesh (and should not even be there)
- else return ret;
- }
-
- // Process mesh normals
- if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
- "normals",dirtyMask,true,false))
- ret = true;
-
- // Process mesh tangents
- if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask)) {
- delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
- ret = true;
- }
-
- // Process mesh bitangents
- if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask)) {
- delete[] pMesh->mTangents; pMesh->mTangents = NULL;
- ret = true;
- }
- }
- return ret ? 1 : 0;
+ bool ret = false;
+ std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false));
+
+ // Ignore elements that are not referenced by vertices.
+ // (they are, for example, caused by the FindDegenerates step)
+ for (unsigned int m = 0; m < pMesh->mNumFaces;++m) {
+ const aiFace& f = pMesh->mFaces[m];
+
+ for (unsigned int i = 0; i < f.mNumIndices;++i) {
+ dirtyMask[f.mIndices[i]] = false;
+ }
+ }
+
+ // Process vertex positions
+ if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) {
+ DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
+ return 2;
+ }
+
+ // process texture coordinates
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i) {
+ if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask)) {
+
+ // delete all subsequent texture coordinate sets.
+ for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
+ delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL;
+ }
+ ret = true;
+ }
+ }
+
+ // -- we don't validate vertex colors, it's difficult to say whether
+ // they are invalid or not.
+
+ // Normals and tangents are undefined for point and line faces.
+ if (pMesh->mNormals || pMesh->mTangents) {
+
+ if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
+ aiPrimitiveType_LINE & pMesh->mPrimitiveTypes)
+ {
+ if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
+ aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
+ {
+ // We need to update the lookup-table
+ for (unsigned int m = 0; m < pMesh->mNumFaces;++m)
+ {
+ const aiFace& f = pMesh->mFaces[m];
+
+ if (f.mNumIndices < 3) {
+ dirtyMask[f.mIndices[0]] = true;
+
+ if (f.mNumIndices == 2) {
+ dirtyMask[f.mIndices[1]] = true;
+ }
+ }
+ }
+ }
+ // Normals, tangents and bitangents are undefined for
+ // the whole mesh (and should not even be there)
+ else return ret;
+ }
+
+ // Process mesh normals
+ if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
+ "normals",dirtyMask,true,false))
+ ret = true;
+
+ // Process mesh tangents
+ if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask)) {
+ delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
+ ret = true;
+ }
+
+ // Process mesh bitangents
+ if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask)) {
+ delete[] pMesh->mTangents; pMesh->mTangents = NULL;
+ ret = true;
+ }
+ }
+ return ret ? 1 : 0;
}
diff --git a/src/3rdparty/assimp/code/FindInvalidDataProcess.h b/src/3rdparty/assimp/code/FindInvalidDataProcess.h
index 6d3c812fe..371569380 100644
--- a/src/3rdparty/assimp/code/FindInvalidDataProcess.h
+++ b/src/3rdparty/assimp/code/FindInvalidDataProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,11 +44,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_FINDINVALIDDATA_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+#include <assimp/anim.h>
struct aiMesh;
class FindInvalidDataProcessTest;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** The FindInvalidData post-processing step. It searches the mesh data
@@ -60,43 +61,43 @@ class ASSIMP_API FindInvalidDataProcess : public BaseProcess
{
public:
- FindInvalidDataProcess();
- ~FindInvalidDataProcess();
+ FindInvalidDataProcess();
+ ~FindInvalidDataProcess();
public:
- // -------------------------------------------------------------------
- //
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ //
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- // Setup import settings
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
- // -------------------------------------------------------------------
- // Run the step
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ // Run the step
+ void Execute( aiScene* pScene);
public:
- // -------------------------------------------------------------------
- /** Executes the postprocessing step on the given mesh
- * @param pMesh The mesh to process.
- * @return 0 - nothing, 1 - removed sth, 2 - please delete me */
- int ProcessMesh( aiMesh* pMesh);
+ // -------------------------------------------------------------------
+ /** Executes the postprocessing step on the given mesh
+ * @param pMesh The mesh to process.
+ * @return 0 - nothing, 1 - removed sth, 2 - please delete me */
+ int ProcessMesh( aiMesh* pMesh);
- // -------------------------------------------------------------------
- /** Executes the postprocessing step on the given animation
- * @param anim The animation to process. */
- void ProcessAnimation (aiAnimation* anim);
+ // -------------------------------------------------------------------
+ /** Executes the postprocessing step on the given animation
+ * @param anim The animation to process. */
+ void ProcessAnimation (aiAnimation* anim);
- // -------------------------------------------------------------------
- /** Executes the postprocessing step on the given anim channel
- * @param anim The animation channel to process.*/
- void ProcessAnimationChannel (aiNodeAnim* anim);
+ // -------------------------------------------------------------------
+ /** Executes the postprocessing step on the given anim channel
+ * @param anim The animation channel to process.*/
+ void ProcessAnimationChannel (aiNodeAnim* anim);
private:
- float configEpsilon;
+ float configEpsilon;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/FixNormalsStep.cpp b/src/3rdparty/assimp/code/FixNormalsStep.cpp
index 9b8522295..9249b13e9 100644
--- a/src/3rdparty/assimp/code/FixNormalsStep.cpp
+++ b/src/3rdparty/assimp/code/FixNormalsStep.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,10 +43,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* all normals in meshes with infacing normals.
*/
-#include "AssimpPCH.h"
-
// internal headers
#include "FixNormalsStep.h"
+#include "StringUtils.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <stdio.h>
+
using namespace Assimp;
@@ -55,122 +59,122 @@ using namespace Assimp;
// Constructor to be privately used by Importer
FixInfacingNormalsProcess::FixInfacingNormalsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
FixInfacingNormalsProcess::~FixInfacingNormalsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_FixInfacingNormals) != 0;
+ return (pFlags & aiProcess_FixInfacingNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void FixInfacingNormalsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("FixInfacingNormalsProcess begin");
+ DefaultLogger::get()->debug("FixInfacingNormalsProcess begin");
- bool bHas = false;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
- if (bHas)
- DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues.");
- else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene.");
+ if (bHas)
+ DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues.");
+ else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene.");
}
// ------------------------------------------------------------------------------------------------
// Apply the step to the mesh
bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
{
- ai_assert(NULL != pcMesh);
+ ai_assert(NULL != pcMesh);
- // Nothing to do if there are no model normals
- if (!pcMesh->HasNormals())return false;
+ // Nothing to do if there are no model normals
+ if (!pcMesh->HasNormals())return false;
- // Compute the bounding box of both the model vertices + normals and
- // the umodified model vertices. Then check whether the first BB
- // is smaller than the second. In this case we can assume that the
- // normals need to be flipped, although there are a few special cases ..
- // convex, concave, planar models ...
+ // Compute the bounding box of both the model vertices + normals and
+ // the umodified model vertices. Then check whether the first BB
+ // is smaller than the second. In this case we can assume that the
+ // normals need to be flipped, although there are a few special cases ..
+ // convex, concave, planar models ...
- aiVector3D vMin0 (1e10f,1e10f,1e10f);
- aiVector3D vMin1 (1e10f,1e10f,1e10f);
- aiVector3D vMax0 (-1e10f,-1e10f,-1e10f);
- aiVector3D vMax1 (-1e10f,-1e10f,-1e10f);
+ aiVector3D vMin0 (1e10f,1e10f,1e10f);
+ aiVector3D vMin1 (1e10f,1e10f,1e10f);
+ aiVector3D vMax0 (-1e10f,-1e10f,-1e10f);
+ aiVector3D vMax1 (-1e10f,-1e10f,-1e10f);
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- {
- vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x);
- vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y);
- vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z);
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ {
+ vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x);
+ vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y);
+ vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z);
- vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x);
- vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y);
- vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z);
+ vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x);
+ vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y);
+ vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z);
- const aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i];
+ const aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i];
- vMin0.x = std::min(vMin0.x,vWithNormal.x);
- vMin0.y = std::min(vMin0.y,vWithNormal.y);
- vMin0.z = std::min(vMin0.z,vWithNormal.z);
+ vMin0.x = std::min(vMin0.x,vWithNormal.x);
+ vMin0.y = std::min(vMin0.y,vWithNormal.y);
+ vMin0.z = std::min(vMin0.z,vWithNormal.z);
- vMax0.x = std::max(vMax0.x,vWithNormal.x);
- vMax0.y = std::max(vMax0.y,vWithNormal.y);
- vMax0.z = std::max(vMax0.z,vWithNormal.z);
- }
+ vMax0.x = std::max(vMax0.x,vWithNormal.x);
+ vMax0.y = std::max(vMax0.y,vWithNormal.y);
+ vMax0.z = std::max(vMax0.z,vWithNormal.z);
+ }
- const float fDelta0_x = (vMax0.x - vMin0.x);
- const float fDelta0_y = (vMax0.y - vMin0.y);
- const float fDelta0_z = (vMax0.z - vMin0.z);
+ const float fDelta0_x = (vMax0.x - vMin0.x);
+ const float fDelta0_y = (vMax0.y - vMin0.y);
+ const float fDelta0_z = (vMax0.z - vMin0.z);
- const float fDelta1_x = (vMax1.x - vMin1.x);
- const float fDelta1_y = (vMax1.y - vMin1.y);
- const float fDelta1_z = (vMax1.z - vMin1.z);
+ const float fDelta1_x = (vMax1.x - vMin1.x);
+ const float fDelta1_y = (vMax1.y - vMin1.y);
+ const float fDelta1_z = (vMax1.z - vMin1.z);
- // Check whether the boxes are overlapping
- if ((fDelta0_x > 0.0f) != (fDelta1_x > 0.0f))return false;
- if ((fDelta0_y > 0.0f) != (fDelta1_y > 0.0f))return false;
- if ((fDelta0_z > 0.0f) != (fDelta1_z > 0.0f))return false;
+ // Check whether the boxes are overlapping
+ if ((fDelta0_x > 0.0f) != (fDelta1_x > 0.0f))return false;
+ if ((fDelta0_y > 0.0f) != (fDelta1_y > 0.0f))return false;
+ if ((fDelta0_z > 0.0f) != (fDelta1_z > 0.0f))return false;
- // Check whether this is a planar surface
- const float fDelta1_yz = fDelta1_y * fDelta1_z;
+ // Check whether this is a planar surface
+ const float fDelta1_yz = fDelta1_y * fDelta1_z;
if (fDelta1_x < 0.05f * sqrtf( fDelta1_yz ))return false;
if (fDelta1_y < 0.05f * sqrtf( fDelta1_z * fDelta1_x ))return false;
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
- // now compare the volumes of the bounding boxes
- if (::fabsf(fDelta0_x * fDelta1_yz) <
- ::fabsf(fDelta1_x * fDelta1_y * fDelta1_z))
- {
- if (!DefaultLogger::isNullLogger())
- {
- char buffer[128]; // should be sufficiently large
- ::sprintf(buffer,"Mesh %i: Normals are facing inwards (or the mesh is planar)",index);
- DefaultLogger::get()->info(buffer);
- }
-
- // Invert normals
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- pcMesh->mNormals[i] *= -1.0f;
-
- // ... and flip faces
- for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
- {
- aiFace& face = pcMesh->mFaces[i];
- for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
- std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
- }
- return true;
- }
- return false;
+ // now compare the volumes of the bounding boxes
+ if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) <
+ std::fabs(fDelta1_x * fDelta1_yz))
+ {
+ if (!DefaultLogger::isNullLogger())
+ {
+ char buffer[128]; // should be sufficiently large
+ ai_snprintf(buffer,128,"Mesh %u: Normals are facing inwards (or the mesh is planar)",index);
+ DefaultLogger::get()->info(buffer);
+ }
+
+ // Invert normals
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ pcMesh->mNormals[i] *= -1.0f;
+
+ // ... and flip faces
+ for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
+ {
+ aiFace& face = pcMesh->mFaces[i];
+ for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
+ std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
+ }
+ return true;
+ }
+ return false;
}
diff --git a/src/3rdparty/assimp/code/FixNormalsStep.h b/src/3rdparty/assimp/code/FixNormalsStep.h
index fa1fc3deb..5dea5d868 100644
--- a/src/3rdparty/assimp/code/FixNormalsStep.h
+++ b/src/3rdparty/assimp/code/FixNormalsStep.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -58,33 +58,33 @@ namespace Assimp
class FixInfacingNormalsProcess : public BaseProcess
{
public:
-
- FixInfacingNormalsProcess();
- ~FixInfacingNormalsProcess();
+
+ FixInfacingNormalsProcess();
+ ~FixInfacingNormalsProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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:
- // -------------------------------------------------------------------
- /** Executes the step on the given mesh
- * @param pMesh The mesh to process.
- */
- bool ProcessMesh( aiMesh* pMesh, unsigned int index);
+ // -------------------------------------------------------------------
+ /** Executes the step on the given mesh
+ * @param pMesh The mesh to process.
+ */
+ bool ProcessMesh( aiMesh* pMesh, unsigned int index);
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp b/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
index 573d93299..9218d9db8 100644
--- a/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
+++ b/src/3rdparty/assimp/code/GenFaceNormalsProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,8 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* normals for all imported faces.
*/
-#include "AssimpPCH.h"
+
#include "GenFaceNormalsProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include "Exceptional.h"
+#include "qnan.h"
using namespace Assimp;
@@ -53,86 +58,86 @@ using namespace Assimp;
// Constructor to be privately used by Importer
GenFaceNormalsProcess::GenFaceNormalsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
GenFaceNormalsProcess::~GenFaceNormalsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_GenNormals) != 0;
+ return (pFlags & aiProcess_GenNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenFaceNormalsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
-
- if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
- throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
- }
-
- bool bHas = false;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
- if(this->GenMeshFaceNormals( pScene->mMeshes[a])) {
- bHas = true;
- }
- }
- if (bHas) {
- DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
- "Face normals have been calculated");
- }
- else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
- "Normals are already there");
+ DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+ }
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ if(this->GenMeshFaceNormals( pScene->mMeshes[a])) {
+ bHas = true;
+ }
+ }
+ if (bHas) {
+ DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
+ "Face normals have been calculated");
+ }
+ else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
+ "Normals are already there");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
{
- if (NULL != pMesh->mNormals) {
- 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))) {
- DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
- return false;
- }
-
- // allocate an array to hold the output normals
- pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
- const float qnan = get_qnan();
-
- // iterate through all faces and compute per-face normals but store them per-vertex.
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
- const aiFace& face = pMesh->mFaces[a];
- if (face.mNumIndices < 3) {
- // either a point or a line -> no well-defined normal vector
- for (unsigned int i = 0;i < face.mNumIndices;++i) {
- pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
- }
- continue;
- }
-
- const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
- const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
- const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
- const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
-
- for (unsigned int i = 0;i < face.mNumIndices;++i) {
- pMesh->mNormals[face.mIndices[i]] = vNor;
- }
- }
- return true;
+ if (NULL != pMesh->mNormals) {
+ 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))) {
+ DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
+ return false;
+ }
+
+ // allocate an array to hold the output normals
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ const float qnan = get_qnan();
+
+ // iterate through all faces and compute per-face normals but store them per-vertex.
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ const aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices < 3) {
+ // either a point or a line -> no well-defined normal vector
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
+ }
+ continue;
+ }
+
+ const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
+ const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
+ const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
+ const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
+
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = vNor;
+ }
+ }
+ return true;
}
diff --git a/src/3rdparty/assimp/code/GenFaceNormalsProcess.h b/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
index 150a81a71..f56570078 100644
--- a/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
+++ b/src/3rdparty/assimp/code/GenFaceNormalsProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_GENFACENORMALPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
namespace Assimp
{
@@ -55,28 +55,28 @@ class ASSIMP_API_WINONLY GenFaceNormalsProcess : public BaseProcess
{
public:
- GenFaceNormalsProcess();
- ~GenFaceNormalsProcess();
+ GenFaceNormalsProcess();
+ ~GenFaceNormalsProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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);
private:
- bool GenMeshFaceNormals (aiMesh* pcMesh);
+ bool GenMeshFaceNormals (aiMesh* pcMesh);
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
index 231b6557d..165c3f8fb 100644
--- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,192 +43,193 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* normals for all imported faces.
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "GenVertexNormalsProcess.h"
#include "ProcessHelper.h"
+#include "Exceptional.h"
+#include "qnan.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
GenVertexNormalsProcess::GenVertexNormalsProcess()
-{
- this->configMaxAngle = AI_DEG_TO_RAD(175.f);
+: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) {
+ // empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-GenVertexNormalsProcess::~GenVertexNormalsProcess()
-{
- // nothing to do here
+GenVertexNormalsProcess::~GenVertexNormalsProcess() {
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_GenSmoothNormals) != 0;
+ return (pFlags & aiProcess_GenSmoothNormals) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
{
- // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
- configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,175.f);
- configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,175.0f),0.0f));
+ // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
+ configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,175.f);
+ configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,175.0f),0.0f));
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
-
- if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
- throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
-
- bool bHas = false;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- {
- if(GenMeshVertexNormals( pScene->mMeshes[a],a))
- bHas = true;
- }
-
- if (bHas) {
- DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
- "Vertex normals have been calculated");
- }
- else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
- "Normals are already there");
+ DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
+ throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if(GenMeshVertexNormals( pScene->mMeshes[a],a))
+ bHas = true;
+ }
+
+ if (bHas) {
+ DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
+ "Vertex normals have been calculated");
+ }
+ else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
+ "Normals are already there");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
{
- if (NULL != pMesh->mNormals)
- 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)))
- {
- DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
- return false;
- }
-
- // Allocate the array to hold the output normals
- const float qnan = std::numeric_limits<float>::quiet_NaN();
- pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
-
- // Compute per-face normals but store them per-vertex
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
- {
- const aiFace& face = pMesh->mFaces[a];
- if (face.mNumIndices < 3)
- {
- // either a point or a line -> no normal vector
- for (unsigned int i = 0;i < face.mNumIndices;++i) {
- pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
- }
-
- continue;
- }
-
- const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
- const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
- const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
- const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
-
- for (unsigned int i = 0;i < face.mNumIndices;++i) {
- pMesh->mNormals[face.mIndices[i]] = vNor;
- }
- }
-
- // Set up a SpatialSort to quickly find all vertices close to a given position
- // check whether we can reuse the SpatialSort of a previous step.
- SpatialSort* vertexFinder = NULL;
- SpatialSort _vertexFinder;
- float posEpsilon = 1e-5f;
- 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;
- aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
-
- if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
- // There is no angle limit. Thus all vertices with positions close
- // to each other will receive the same vertex normal. This allows us
- // to optimize the whole algorithm a little bit ...
- std::vector<bool> abHad(pMesh->mNumVertices,false);
- for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
- if (abHad[i]) {
- continue;
- }
-
- // Get all vertices that share this one ...
- vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
-
- aiVector3D pcNor;
- for (unsigned int a = 0; a < verticesFound.size(); ++a) {
- const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
- if (is_not_qnan(v.x))pcNor += v;
- }
- pcNor.Normalize();
-
- // Write the smoothed normal back to all affected normals
- for (unsigned int a = 0; a < verticesFound.size(); ++a)
- {
- unsigned int vidx = verticesFound[a];
- pcNew[vidx] = pcNor;
- abHad[vidx] = true;
- }
- }
- }
- // Slower code path if a smooth angle is set. There are many ways to achieve
- // the effect, this one is the most straightforward one.
- else {
+ if (NULL != pMesh->mNormals)
+ 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)))
+ {
+ DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
+ return false;
+ }
+
+ // Allocate the array to hold the output normals
+ const float qnan = std::numeric_limits<float>::quiet_NaN();
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+
+ // Compute per-face normals but store them per-vertex
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ const aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices < 3)
+ {
+ // either a point or a line -> no normal vector
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
+ }
+
+ continue;
+ }
+
+ const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
+ const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
+ const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
+ const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
+
+ for (unsigned int i = 0;i < face.mNumIndices;++i) {
+ pMesh->mNormals[face.mIndices[i]] = vNor;
+ }
+ }
+
+ // Set up a SpatialSort to quickly find all vertices close to a given position
+ // check whether we can reuse the SpatialSort of a previous step.
+ SpatialSort* vertexFinder = NULL;
+ SpatialSort _vertexFinder;
+ float posEpsilon = 1e-5f;
+ 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;
+ aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
+
+ if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
+ // There is no angle limit. Thus all vertices with positions close
+ // to each other will receive the same vertex normal. This allows us
+ // to optimize the whole algorithm a little bit ...
+ std::vector<bool> abHad(pMesh->mNumVertices,false);
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ if (abHad[i]) {
+ continue;
+ }
+
+ // Get all vertices that share this one ...
+ vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
+
+ aiVector3D pcNor;
+ for (unsigned int a = 0; a < verticesFound.size(); ++a) {
+ const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
+ if (is_not_qnan(v.x))pcNor += v;
+ }
+ pcNor.NormalizeSafe();
+
+ // Write the smoothed normal back to all affected normals
+ for (unsigned int a = 0; a < verticesFound.size(); ++a)
+ {
+ unsigned int vidx = verticesFound[a];
+ pcNew[vidx] = pcNor;
+ abHad[vidx] = true;
+ }
+ }
+ }
+ // Slower code path if a smooth angle is set. There are many ways to achieve
+ // the effect, this one is the most straightforward one.
+ else {
const float fLimit = std::cos(configMaxAngle);
- for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
- // Get all vertices that share this one ...
- vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
-
- aiVector3D vr = pMesh->mNormals[i];
- float vrlen = vr.Length();
-
- aiVector3D pcNor;
- for (unsigned int a = 0; a < verticesFound.size(); ++a) {
- aiVector3D v = pMesh->mNormals[verticesFound[a]];
-
- // check whether the angle between the two normals is not too large
- // HACK: if v.x is qnan the dot product will become qnan, too
- // therefore the comparison against fLimit should be false
- // in every case.
- if (v * vr >= fLimit * vrlen * v.Length())
- pcNor += v;
- }
- pcNew[i] = pcNor.Normalize();
- }
- }
-
- delete[] pMesh->mNormals;
- pMesh->mNormals = pcNew;
-
- return true;
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ // Get all vertices that share this one ...
+ vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
+
+ aiVector3D vr = pMesh->mNormals[i];
+ float vrlen = vr.Length();
+
+ aiVector3D pcNor;
+ for (unsigned int a = 0; a < verticesFound.size(); ++a) {
+ aiVector3D v = pMesh->mNormals[verticesFound[a]];
+
+ // check whether the angle between the two normals is not too large
+ // HACK: if v.x is qnan the dot product will become qnan, too
+ // therefore the comparison against fLimit should be false
+ // in every case.
+ if (v * vr >= fLimit * vrlen * v.Length())
+ pcNor += v;
+ }
+ pcNew[i] = pcNor.NormalizeSafe();
+ }
+ }
+
+ delete[] pMesh->mNormals;
+ pMesh->mNormals = pcNew;
+
+ return true;
}
diff --git a/src/3rdparty/assimp/code/GenVertexNormalsProcess.h b/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
index 99f8d869b..5d8b61ead 100644
--- a/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
+++ b/src/3rdparty/assimp/code/GenVertexNormalsProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,28 +23,28 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to compute vertex normals
+/** @file Defines a post processing step to compute vertex normals
for all loaded vertizes */
#ifndef AI_GENVERTEXNORMALPROCESS_H_INC
#define AI_GENVERTEXNORMALPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
class GenNormalsTest;
@@ -53,58 +53,58 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** The GenFaceNormalsProcess computes vertex normals for all vertizes
*/
-class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess
+class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
{
public:
- GenVertexNormalsProcess();
- ~GenVertexNormalsProcess();
+ GenVertexNormalsProcess();
+ ~GenVertexNormalsProcess();
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);
-
- // -------------------------------------------------------------------
- /** 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);
-
-
- // setter for configMaxAngle
- inline void SetMaxSmoothAngle(float f)
- {
- configMaxAngle =f;
- }
+ // -------------------------------------------------------------------
+ /** 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);
+
+ // -------------------------------------------------------------------
+ /** 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);
+
+
+ // setter for configMaxAngle
+ inline void SetMaxSmoothAngle(float f)
+ {
+ configMaxAngle =f;
+ }
public:
- // -------------------------------------------------------------------
- /** Computes normals for a specific mesh
- * @param pcMesh Mesh
- * @param meshIndex Index of the mesh
- * @return true if vertex normals have been computed
- */
- bool GenMeshVertexNormals (aiMesh* pcMesh, unsigned int meshIndex);
+ // -------------------------------------------------------------------
+ /** Computes normals for a specific mesh
+ * @param pcMesh Mesh
+ * @param meshIndex Index of the mesh
+ * @return true if vertex normals have been computed
+ */
+ bool GenMeshVertexNormals (aiMesh* pcMesh, unsigned int meshIndex);
private:
- /** Configuration option: maximum smoothing angle, in radians*/
- float configMaxAngle;
+ /** Configuration option: maximum smoothing angle, in radians*/
+ float configMaxAngle;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/GenericProperty.h b/src/3rdparty/assimp/code/GenericProperty.h
index 2b8d5c502..507bfb693 100644
--- a/src/3rdparty/assimp/code/GenericProperty.h
+++ b/src/3rdparty/assimp/code/GenericProperty.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,72 +41,85 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_GENERIC_PROPERTY_H_INCLUDED
#define AI_GENERIC_PROPERTY_H_INCLUDED
-#include "./../include/assimp/Importer.hpp"
+#include <assimp/Importer.hpp>
+#include <assimp/ai_assert.h>
#include "Hash.h"
+#include <map>
+
// ------------------------------------------------------------------------------------------------
template <class T>
-inline void SetGenericProperty(std::map< unsigned int, T >& list,
- const char* szName, const T& value, bool* bWasExisting = NULL)
+inline bool SetGenericProperty(std::map< unsigned int, T >& list,
+ const char* szName, const T& value)
{
- ai_assert(NULL != szName);
- const uint32_t hash = SuperFastHash(szName);
-
- typename std::map<unsigned int, T>::iterator it = list.find(hash);
- if (it == list.end()) {
- if (bWasExisting)
- *bWasExisting = false;
- list.insert(std::pair<unsigned int, T>( hash, value ));
- return;
- }
- (*it).second = value;
- if (bWasExisting)
- *bWasExisting = true;
+ ai_assert(NULL != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::iterator it = list.find(hash);
+ if (it == list.end()) {
+ list.insert(std::pair<unsigned int, T>( hash, value ));
+ return false;
+ }
+ (*it).second = value;
+ return true;
}
// ------------------------------------------------------------------------------------------------
template <class T>
-inline const T& GetGenericProperty(const std::map< unsigned int, T >& list,
- const char* szName, const T& errorReturn)
+inline const T& GetGenericProperty(const std::map< unsigned int, T >& list,
+ const char* szName, const T& errorReturn)
{
- ai_assert(NULL != szName);
- const uint32_t hash = SuperFastHash(szName);
-
- typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
- if (it == list.end())
- return errorReturn;
-
- return (*it).second;
+ ai_assert(NULL != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+ if (it == list.end())
+ return errorReturn;
+
+ return (*it).second;
}
// ------------------------------------------------------------------------------------------------
// Special version for pointer types - they will be deleted when replaced with another value
// passing NULL removes the whole property
template <class T>
-inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
- const char* szName, T* value, bool* bWasExisting = NULL)
+inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
+ const char* szName, T* value, bool* bWasExisting = NULL)
{
- ai_assert(NULL != szName);
- const uint32_t hash = SuperFastHash(szName);
-
- typename std::map<unsigned int, T*>::iterator it = list.find(hash);
- if (it == list.end()) {
- if (bWasExisting)
- *bWasExisting = false;
-
- list.insert(std::pair<unsigned int,T*>( hash, value ));
- return;
- }
- if ((*it).second != value) {
- delete (*it).second;
- (*it).second = value;
- }
- if (!value) {
- list.erase(it);
- }
- if (bWasExisting)
- *bWasExisting = true;
+ ai_assert(NULL != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T*>::iterator it = list.find(hash);
+ if (it == list.end()) {
+ if (bWasExisting)
+ *bWasExisting = false;
+
+ list.insert(std::pair<unsigned int,T*>( hash, value ));
+ return;
+ }
+ if ((*it).second != value) {
+ delete (*it).second;
+ (*it).second = value;
+ }
+ if (!value) {
+ list.erase(it);
+ }
+ if (bWasExisting)
+ *bWasExisting = true;
}
+// ------------------------------------------------------------------------------------------------
+template <class T>
+inline const bool HasGenericProperty(const std::map< unsigned int, T >& list,
+ const char* szName)
+{
+ ai_assert(NULL != szName);
+ const uint32_t hash = SuperFastHash(szName);
+
+ typename std::map<unsigned int, T>::const_iterator it = list.find(hash);
+ if (it == list.end()) return false;
+
+ return true;
+}
#endif // !! AI_GENERIC_PROPERTY_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/HMPFileData.h b/src/3rdparty/assimp/code/HMPFileData.h
index d8748dac5..cff3b6b18 100644
--- a/src/3rdparty/assimp/code/HMPFileData.h
+++ b/src/3rdparty/assimp/code/HMPFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,20 +41,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! @file Data structures for the 3D Game Studio Heightmap format (HMP)
//!
-namespace Assimp {
-namespace HMP {
+namespace Assimp {
+namespace HMP {
#include "./../include/assimp/Compiler/pushpack1.h"
+#include <stdint.h>
// to make it easier for us, we test the magic word against both "endianesses"
-#define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4")
-#define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH")
+#define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4")
+#define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH")
-#define AI_HMP_MAGIC_NUMBER_BE_5 AI_MAKE_MAGIC("HMP5")
-#define AI_HMP_MAGIC_NUMBER_LE_5 AI_MAKE_MAGIC("5PMH")
+#define AI_HMP_MAGIC_NUMBER_BE_5 AI_MAKE_MAGIC("HMP5")
+#define AI_HMP_MAGIC_NUMBER_LE_5 AI_MAKE_MAGIC("5PMH")
-#define AI_HMP_MAGIC_NUMBER_BE_7 AI_MAKE_MAGIC("HMP7")
-#define AI_HMP_MAGIC_NUMBER_LE_7 AI_MAKE_MAGIC("7PMH")
+#define AI_HMP_MAGIC_NUMBER_BE_7 AI_MAKE_MAGIC("HMP7")
+#define AI_HMP_MAGIC_NUMBER_LE_7 AI_MAKE_MAGIC("7PMH")
// ---------------------------------------------------------------------------
/** Data structure for the header of a HMP5 file.
@@ -62,70 +63,70 @@ namespace HMP {
*/
struct Header_HMP5
{
- int8_t ident[4]; // "HMP5"
- int32_t version;
-
- // ignored
- float scale[3];
- float scale_origin[3];
- float boundingradius;
-
- //! Size of one triangle in x direction
- float ftrisize_x;
- //! Size of one triangle in y direction
- float ftrisize_y;
- //! Number of vertices in x direction
- float fnumverts_x;
-
- //! Number of skins in the file
- int32_t numskins;
-
- // can ignore this?
- int32_t skinwidth;
- int32_t skinheight;
-
- //!Number of vertices in the file
- int32_t numverts;
-
- // ignored and zero
- int32_t numtris;
-
- //! only one supported ...
- int32_t numframes;
-
- //! Always 0 ...
- int32_t num_stverts;
- int32_t flags;
- float size;
+ int8_t ident[4]; // "HMP5"
+ int32_t version;
+
+ // ignored
+ float scale[3];
+ float scale_origin[3];
+ float boundingradius;
+
+ //! Size of one triangle in x direction
+ float ftrisize_x;
+ //! Size of one triangle in y direction
+ float ftrisize_y;
+ //! Number of vertices in x direction
+ float fnumverts_x;
+
+ //! Number of skins in the file
+ int32_t numskins;
+
+ // can ignore this?
+ int32_t skinwidth;
+ int32_t skinheight;
+
+ //!Number of vertices in the file
+ int32_t numverts;
+
+ // ignored and zero
+ int32_t numtris;
+
+ //! only one supported ...
+ int32_t numframes;
+
+ //! Always 0 ...
+ int32_t num_stverts;
+ int32_t flags;
+ float size;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** Data structure for a terrain vertex in a HMP4 file
+/** Data structure for a terrain vertex in a HMP4 file
*/
struct Vertex_HMP4
{
- uint16_t p_pos[3];
- uint8_t normals162index;
- uint8_t pad;
+ uint16_t p_pos[3];
+ uint8_t normals162index;
+ uint8_t pad;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** Data structure for a terrain vertex in a HMP5 file
+/** Data structure for a terrain vertex in a HMP5 file
*/
struct Vertex_HMP5
{
- uint16_t z;
- uint8_t normals162index;
- uint8_t pad;
+ uint16_t z;
+ uint8_t normals162index;
+ uint8_t pad;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** Data structure for a terrain vertex in a HMP7 file
+/** Data structure for a terrain vertex in a HMP7 file
*/
struct Vertex_HMP7
{
- uint16_t z;
- int8_t normal_x,normal_y;
+ uint16_t z;
+ int8_t normal_x,normal_y;
} PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h"
diff --git a/src/3rdparty/assimp/code/HMPLoader.cpp b/src/3rdparty/assimp/code/HMPLoader.cpp
index 1e6b19bdc..560852691 100644
--- a/src/3rdparty/assimp/code/HMPLoader.cpp
+++ b/src/3rdparty/assimp/code/HMPLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,485 +25,489 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the MDL importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
// internal headers
#include "HMPLoader.h"
#include "MD2FileData.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
using namespace Assimp;
static const aiImporterDesc desc = {
- "3D GameStudio Heightmap (HMP) Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "hmp"
+ "3D GameStudio Heightmap (HMP) Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "hmp"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
HMPImporter::HMPImporter()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
HMPImporter::~HMPImporter()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "hmp" )
- return true;
-
- // if check for extension is not enough, check for the magic tokens
- if (!extension.length() || cs) {
- uint32_t tokens[3];
- tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
- tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
- tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
- return CheckMagicToken(pIOHandler,pFile,tokens,3,0);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "hmp" )
+ return true;
+
+ // if check for extension is not enough, check for the magic tokens
+ if (!extension.length() || cs) {
+ uint32_t tokens[3];
+ tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
+ tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
+ tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
+ return CheckMagicToken(pIOHandler,pFile,tokens,3,0);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get list of all file extensions that are handled by this loader
const aiImporterDesc* HMPImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void HMPImporter::InternReadFile( const std::string& pFile,
- aiScene* _pScene, IOSystem* _pIOHandler)
+// Imports the given file into the given scene structure.
+void HMPImporter::InternReadFile( const std::string& pFile,
+ aiScene* _pScene, IOSystem* _pIOHandler)
{
- pScene = _pScene;
- pIOHandler = _pIOHandler;
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
-
- // Check whether the HMP file is large enough to contain
- // at least the file header
- const size_t fileSize = file->FileSize();
- if( fileSize < 50)
- throw DeadlyImportError( "HMP File is too small.");
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector<uint8_t> buffer(fileSize);
- mBuffer = &buffer[0];
- file->Read( (void*)mBuffer, 1, fileSize);
- iFileSize = (unsigned int)fileSize;
-
- // Determine the file subtype and call the appropriate member function
- const uint32_t iMagic = *((uint32_t*)this->mBuffer);
-
- // HMP4 format
- if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
- AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
- {
- DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
- InternReadFile_HMP4();
- }
- // HMP5 format
- else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
- AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
- {
- DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
- InternReadFile_HMP5();
- }
- // HMP7 format
- else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
- AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
- {
- DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
- InternReadFile_HMP7();
- }
- else
- {
- // Print the magic word to the logger
- char szBuffer[5];
- szBuffer[0] = ((char*)&iMagic)[0];
- szBuffer[1] = ((char*)&iMagic)[1];
- szBuffer[2] = ((char*)&iMagic)[2];
- szBuffer[3] = ((char*)&iMagic)[3];
- szBuffer[4] = '\0';
-
- // We're definitely unable to load this file
- throw DeadlyImportError( "Unknown HMP subformat " + pFile +
- ". Magic word (" + szBuffer + ") is not known");
- }
-
- // Set the AI_SCENE_FLAGS_TERRAIN bit
- pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
-
- // File buffer destructs automatically now
+ pScene = _pScene;
+ pIOHandler = _pIOHandler;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
+
+ // Check whether the HMP file is large enough to contain
+ // at least the file header
+ const size_t fileSize = file->FileSize();
+ if( fileSize < 50)
+ throw DeadlyImportError( "HMP File is too small.");
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector<uint8_t> buffer(fileSize);
+ mBuffer = &buffer[0];
+ file->Read( (void*)mBuffer, 1, fileSize);
+ iFileSize = (unsigned int)fileSize;
+
+ // Determine the file subtype and call the appropriate member function
+ const uint32_t iMagic = *((uint32_t*)this->mBuffer);
+
+ // HMP4 format
+ if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
+ AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
+ {
+ DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
+ InternReadFile_HMP4();
+ }
+ // HMP5 format
+ else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
+ AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
+ {
+ DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
+ InternReadFile_HMP5();
+ }
+ // HMP7 format
+ else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
+ AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
+ {
+ DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
+ InternReadFile_HMP7();
+ }
+ else
+ {
+ // Print the magic word to the logger
+ char szBuffer[5];
+ szBuffer[0] = ((char*)&iMagic)[0];
+ szBuffer[1] = ((char*)&iMagic)[1];
+ szBuffer[2] = ((char*)&iMagic)[2];
+ szBuffer[3] = ((char*)&iMagic)[3];
+ szBuffer[4] = '\0';
+
+ // We're definitely unable to load this file
+ throw DeadlyImportError( "Unknown HMP subformat " + pFile +
+ ". Magic word (" + szBuffer + ") is not known");
+ }
+
+ // Set the AI_SCENE_FLAGS_TERRAIN bit
+ pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
+
+ // File buffer destructs automatically now
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::ValidateHeader_HMP457( )
{
- const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
-
- if (120 > iFileSize)
- {
- throw DeadlyImportError("HMP file is too small (header size is "
- "120 bytes, this file is smaller)");
- }
-
- if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
- throw DeadlyImportError("Size of triangles in either x or y direction is zero");
-
- if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f)
- throw DeadlyImportError("Number of triangles in either x or y direction is zero");
-
- if(!pcHeader->numframes)
- throw DeadlyImportError("There are no frames. At least one should be there");
+ const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
+
+ if (120 > iFileSize)
+ {
+ throw DeadlyImportError("HMP file is too small (header size is "
+ "120 bytes, this file is smaller)");
+ }
+
+ if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
+ throw DeadlyImportError("Size of triangles in either x or y direction is zero");
+
+ if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f)
+ throw DeadlyImportError("Number of triangles in either x or y direction is zero");
+
+ if(!pcHeader->numframes)
+ throw DeadlyImportError("There are no frames. At least one should be there");
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP4( )
{
- throw DeadlyImportError("HMP4 is currently not supported");
+ throw DeadlyImportError("HMP4 is currently not supported");
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP5( )
{
- // read the file header and skip everything to byte 84
- const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer;
- const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
- ValidateHeader_HMP457();
-
- // generate an output mesh
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
-
- pcMesh->mMaterialIndex = 0;
- pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
- pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
-
- const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
- const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
-
- // generate/load a material for the terrain
- CreateMaterial(szCurrent,&szCurrent);
-
- // goto offset 120, I don't know why ...
- // (fixme) is this the frame header? I assume yes since it starts with 2.
- szCurrent += 36;
- SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
-
- // now load all vertices from the file
- aiVector3D* pcVertOut = pcMesh->mVertices;
- aiVector3D* pcNorOut = pcMesh->mNormals;
- const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent;
- for (unsigned int y = 0; y < height;++y)
- {
- for (unsigned int x = 0; x < width;++x)
- {
- pcVertOut->x = x * pcHeader->ftrisize_x;
- pcVertOut->y = y * pcHeader->ftrisize_y;
- pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
- MD2::LookupNormalIndex(src->normals162index, *pcNorOut );
- ++pcVertOut;++pcNorOut;++src;
- }
- }
-
- // generate texture coordinates if necessary
- if (pcHeader->numskins)
- GenerateTextureCoords(width,height);
-
- // now build a list of faces
- CreateOutputFaceList(width,height);
-
- // there is no nodegraph in HMP files. Simply assign the one mesh
- // (no, not the one ring) to the root node
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("terrain_root");
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
+ // read the file header and skip everything to byte 84
+ const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer;
+ const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
+ ValidateHeader_HMP457();
+
+ // generate an output mesh
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
+
+ pcMesh->mMaterialIndex = 0;
+ pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
+ pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
+
+ const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
+ const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
+
+ // generate/load a material for the terrain
+ CreateMaterial(szCurrent,&szCurrent);
+
+ // goto offset 120, I don't know why ...
+ // (fixme) is this the frame header? I assume yes since it starts with 2.
+ szCurrent += 36;
+ SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
+
+ // now load all vertices from the file
+ aiVector3D* pcVertOut = pcMesh->mVertices;
+ aiVector3D* pcNorOut = pcMesh->mNormals;
+ const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent;
+ for (unsigned int y = 0; y < height;++y)
+ {
+ for (unsigned int x = 0; x < width;++x)
+ {
+ pcVertOut->x = x * pcHeader->ftrisize_x;
+ pcVertOut->y = y * pcHeader->ftrisize_y;
+ pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
+ MD2::LookupNormalIndex(src->normals162index, *pcNorOut );
+ ++pcVertOut;++pcNorOut;++src;
+ }
+ }
+
+ // generate texture coordinates if necessary
+ if (pcHeader->numskins)
+ GenerateTextureCoords(width,height);
+
+ // now build a list of faces
+ CreateOutputFaceList(width,height);
+
+ // there is no nodegraph in HMP files. Simply assign the one mesh
+ // (no, not the one ring) to the root node
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("terrain_root");
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::InternReadFile_HMP7( )
{
- // read the file header and skip everything to byte 84
- const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
- const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
- ValidateHeader_HMP457();
-
- // generate an output mesh
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
-
- pcMesh->mMaterialIndex = 0;
- pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
- pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
-
- const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
- const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
-
- // generate/load a material for the terrain
- CreateMaterial(szCurrent,&szCurrent);
-
- // goto offset 120, I don't know why ...
- // (fixme) is this the frame header? I assume yes since it starts with 2.
- szCurrent += 36;
-
- SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
-
- // now load all vertices from the file
- aiVector3D* pcVertOut = pcMesh->mVertices;
- aiVector3D* pcNorOut = pcMesh->mNormals;
- const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
- for (unsigned int y = 0; y < height;++y)
- {
- for (unsigned int x = 0; x < width;++x)
- {
- pcVertOut->x = x * pcHeader->ftrisize_x;
- pcVertOut->y = y * pcHeader->ftrisize_y;
-
- // FIXME: What exctly is the correct scaling factor to use?
- // possibly pcHeader->scale_origin[2] in combination with a
- // signed interpretation of src->z?
- pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
-
- pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
- pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
- pcNorOut->z = 1.0f;
- pcNorOut->Normalize();
-
- ++pcVertOut;++pcNorOut;++src;
- }
- }
-
- // generate texture coordinates if necessary
- if (pcHeader->numskins)GenerateTextureCoords(width,height);
-
- // now build a list of faces
- CreateOutputFaceList(width,height);
-
- // there is no nodegraph in HMP files. Simply assign the one mesh
- // (no, not the One Ring) to the root node
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("terrain_root");
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
+ // read the file header and skip everything to byte 84
+ const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
+ const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
+ ValidateHeader_HMP457();
+
+ // generate an output mesh
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
+
+ pcMesh->mMaterialIndex = 0;
+ pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
+ pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
+
+ const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
+ const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
+
+ // generate/load a material for the terrain
+ CreateMaterial(szCurrent,&szCurrent);
+
+ // goto offset 120, I don't know why ...
+ // (fixme) is this the frame header? I assume yes since it starts with 2.
+ szCurrent += 36;
+
+ SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
+
+ // now load all vertices from the file
+ aiVector3D* pcVertOut = pcMesh->mVertices;
+ aiVector3D* pcNorOut = pcMesh->mNormals;
+ const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
+ for (unsigned int y = 0; y < height;++y)
+ {
+ for (unsigned int x = 0; x < width;++x)
+ {
+ pcVertOut->x = x * pcHeader->ftrisize_x;
+ pcVertOut->y = y * pcHeader->ftrisize_y;
+
+ // FIXME: What exctly is the correct scaling factor to use?
+ // possibly pcHeader->scale_origin[2] in combination with a
+ // signed interpretation of src->z?
+ pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
+
+ pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
+ pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
+ pcNorOut->z = 1.0f;
+ pcNorOut->Normalize();
+
+ ++pcVertOut;++pcNorOut;++src;
+ }
+ }
+
+ // generate texture coordinates if necessary
+ if (pcHeader->numskins)GenerateTextureCoords(width,height);
+
+ // now build a list of faces
+ CreateOutputFaceList(width,height);
+
+ // there is no nodegraph in HMP files. Simply assign the one mesh
+ // (no, not the One Ring) to the root node
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("terrain_root");
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::CreateMaterial(const unsigned char* szCurrent,
- const unsigned char** szCurrentOut)
+ const unsigned char** szCurrentOut)
{
- aiMesh* const pcMesh = pScene->mMeshes[0];
- const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
-
- // we don't need to generate texture coordinates if
- // we have no textures in the file ...
- if (pcHeader->numskins)
- {
- pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
- pcMesh->mNumUVComponents[0] = 2;
-
- // now read the first skin and skip all others
- ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
- }
- else
- {
- // generate a default material
- const int iMode = (int)aiShadingMode_Gouraud;
- aiMaterial* pcHelper = new aiMaterial();
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- aiString szName;
- szName.Set(AI_DEFAULT_MATERIAL_NAME);
- pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
-
- // add the material to the scene
- pScene->mNumMaterials = 1;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = pcHelper;
- }
- *szCurrentOut = szCurrent;
+ aiMesh* const pcMesh = pScene->mMeshes[0];
+ const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
+
+ // we don't need to generate texture coordinates if
+ // we have no textures in the file ...
+ if (pcHeader->numskins)
+ {
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
+ pcMesh->mNumUVComponents[0] = 2;
+
+ // now read the first skin and skip all others
+ ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
+ }
+ else
+ {
+ // generate a default material
+ const int iMode = (int)aiShadingMode_Gouraud;
+ aiMaterial* pcHelper = new aiMaterial();
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.6f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString szName;
+ szName.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+
+ // add the material to the scene
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = pcHelper;
+ }
+ *szCurrentOut = szCurrent;
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
{
- aiMesh* const pcMesh = this->pScene->mMeshes[0];
-
- // Allocate enough storage
- pcMesh->mNumFaces = (width-1) * (height-1);
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- pcMesh->mNumVertices = pcMesh->mNumFaces*4;
- aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices];
-
- aiFace* pcFaceOut(pcMesh->mFaces);
- aiVector3D* pcVertOut = pcVertices;
- aiVector3D* pcNorOut = pcNormals;
-
- aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
- aiVector3D* pcUVOut(pcUVs);
-
- // Build the terrain square
- unsigned int iCurrent = 0;
- for (unsigned int y = 0; y < height-1;++y) {
- for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) {
- pcFaceOut->mNumIndices = 4;
- pcFaceOut->mIndices = new unsigned int[4];
-
- *pcVertOut++ = pcMesh->mVertices[y*width+x];
- *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
- *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
- *pcVertOut++ = pcMesh->mVertices[y*width+x+1];
-
-
- *pcNorOut++ = pcMesh->mNormals[y*width+x];
- *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
- *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
- *pcNorOut++ = pcMesh->mNormals[y*width+x+1];
-
- if (pcMesh->mTextureCoords[0])
- {
- *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
- *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
- *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
- *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
- }
-
- for (unsigned int i = 0; i < 4;++i)
- pcFaceOut->mIndices[i] = iCurrent++;
- }
- }
- delete[] pcMesh->mVertices;
- pcMesh->mVertices = pcVertices;
-
- delete[] pcMesh->mNormals;
- pcMesh->mNormals = pcNormals;
-
- if (pcMesh->mTextureCoords[0])
- {
- delete[] pcMesh->mTextureCoords[0];
- pcMesh->mTextureCoords[0] = pcUVs;
- }
+ aiMesh* const pcMesh = this->pScene->mMeshes[0];
+
+ // Allocate enough storage
+ pcMesh->mNumFaces = (width-1) * (height-1);
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ pcMesh->mNumVertices = pcMesh->mNumFaces*4;
+ aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ aiFace* pcFaceOut(pcMesh->mFaces);
+ aiVector3D* pcVertOut = pcVertices;
+ aiVector3D* pcNorOut = pcNormals;
+
+ aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
+ aiVector3D* pcUVOut(pcUVs);
+
+ // Build the terrain square
+ unsigned int iCurrent = 0;
+ for (unsigned int y = 0; y < height-1;++y) {
+ for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) {
+ pcFaceOut->mNumIndices = 4;
+ pcFaceOut->mIndices = new unsigned int[4];
+
+ *pcVertOut++ = pcMesh->mVertices[y*width+x];
+ *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
+ *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
+ *pcVertOut++ = pcMesh->mVertices[y*width+x+1];
+
+
+ *pcNorOut++ = pcMesh->mNormals[y*width+x];
+ *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
+ *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
+ *pcNorOut++ = pcMesh->mNormals[y*width+x+1];
+
+ if (pcMesh->mTextureCoords[0])
+ {
+ *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
+ *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
+ *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
+ *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
+ }
+
+ for (unsigned int i = 0; i < 4;++i)
+ pcFaceOut->mIndices[i] = iCurrent++;
+ }
+ }
+ delete[] pcMesh->mVertices;
+ pcMesh->mVertices = pcVertices;
+
+ delete[] pcMesh->mNormals;
+ pcMesh->mNormals = pcNormals;
+
+ if (pcMesh->mTextureCoords[0])
+ {
+ delete[] pcMesh->mTextureCoords[0];
+ pcMesh->mTextureCoords[0] = pcUVs;
+ }
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
- const unsigned char** szCursorOut)
+ const unsigned char** szCursorOut)
{
- ai_assert(0 != iNumSkins && NULL != szCursor);
-
- // read the type of the skin ...
- // sometimes we need to skip 12 bytes here, I don't know why ...
- uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
- if (0 == iType)
- {
- szCursor += sizeof(uint32_t) * 2;
- iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
- if (!iType)
- throw DeadlyImportError("Unable to read HMP7 skin chunk");
-
- }
- // read width and height
- uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
- uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
-
- // allocate an output material
- aiMaterial* pcMat = new aiMaterial();
-
- // read the skin, this works exactly as for MDL7
- ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
- pcMat,iType,iWidth,iHeight);
-
- // now we need to skip any other skins ...
- for (unsigned int i = 1; i< iNumSkins;++i)
- {
- iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
- iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
- iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
-
- SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight);
- SizeCheck(szCursor);
- }
-
- // setup the material ...
- pScene->mNumMaterials = 1;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = pcMat;
-
- *szCursorOut = szCursor;
+ ai_assert(0 != iNumSkins && NULL != szCursor);
+
+ // read the type of the skin ...
+ // sometimes we need to skip 12 bytes here, I don't know why ...
+ uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
+ if (0 == iType)
+ {
+ szCursor += sizeof(uint32_t) * 2;
+ iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
+ if (!iType)
+ throw DeadlyImportError("Unable to read HMP7 skin chunk");
+
+ }
+ // read width and height
+ uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+ uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+
+ // allocate an output material
+ aiMaterial* pcMat = new aiMaterial();
+
+ // read the skin, this works exactly as for MDL7
+ ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
+ pcMat,iType,iWidth,iHeight);
+
+ // now we need to skip any other skins ...
+ for (unsigned int i = 1; i< iNumSkins;++i)
+ {
+ iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+ iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+ iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+
+ SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight);
+ SizeCheck(szCursor);
+ }
+
+ // setup the material ...
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = pcMat;
+
+ *szCursorOut = szCursor;
}
-// ------------------------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------------------------
// Generate proepr texture coords
void HMPImporter::GenerateTextureCoords(
- const unsigned int width, const unsigned int height)
+ const unsigned int width, const unsigned int height)
{
- ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] &&
- NULL != pScene->mMeshes[0]->mTextureCoords[0]);
+ ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] &&
+ NULL != pScene->mMeshes[0]->mTextureCoords[0]);
- aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0];
+ aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0];
- const float fY = (1.0f / height) + (1.0f / height) / (height-1);
- const float fX = (1.0f / width) + (1.0f / width) / (width-1);
+ const float fY = (1.0f / height) + (1.0f / height) / (height-1);
+ const float fX = (1.0f / width) + (1.0f / width) / (width-1);
- for (unsigned int y = 0; y < height;++y) {
- for (unsigned int x = 0; x < width;++x,++uv) {
- uv->y = fY*y;
- uv->x = fX*x;
- uv->z = 0.0f;
- }
- }
+ for (unsigned int y = 0; y < height;++y) {
+ for (unsigned int x = 0; x < width;++x,++uv) {
+ uv->y = fY*y;
+ uv->x = fX*x;
+ uv->z = 0.0f;
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_HMP_IMPORTER
diff --git a/src/3rdparty/assimp/code/HMPLoader.h b/src/3rdparty/assimp/code/HMPLoader.h
index 99b796b2b..4dd0d9840 100644
--- a/src/3rdparty/assimp/code/HMPLoader.h
+++ b/src/3rdparty/assimp/code/HMPLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,9 +45,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_HMPLOADER_H_INCLUDED
// public ASSIMP headers
-#include "../include/assimp/types.h"
-#include "../include/assimp/texture.h"
-#include "../include/assimp/material.h"
+#include <assimp/types.h>
+#include <assimp/texture.h>
+#include <assimp/material.h>
// internal headers
#include "BaseImporter.h"
@@ -63,87 +63,87 @@ using namespace HMP;
class HMPImporter : public MDLImporter
{
public:
- HMPImporter();
- ~HMPImporter();
+ HMPImporter();
+ ~HMPImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Import a HMP4 file
- */
- void InternReadFile_HMP4( );
-
- // -------------------------------------------------------------------
- /** Import a HMP5 file
- */
- void InternReadFile_HMP5( );
-
- // -------------------------------------------------------------------
- /** Import a HMP7 file
- */
- void InternReadFile_HMP7( );
-
- // -------------------------------------------------------------------
- /** Validate a HMP 5,4,7 file header
- */
- void ValidateHeader_HMP457( );
-
- // -------------------------------------------------------------------
- /** Try to load one material from the file, if this fails create
- * a default material
- */
- void CreateMaterial(const unsigned char* szCurrent,
- const unsigned char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Build a list of output faces and vertices. The function
- * triangulates the height map read from the file
- * \param width Width of the height field
- * \param width Height of the height field
- */
- void CreateOutputFaceList(unsigned int width,unsigned int height);
-
- // -------------------------------------------------------------------
- /** Generate planar texture coordinates for a terrain
- * \param width Width of the terrain, in vertices
- * \param height Height of the terrain, in vertices
- */
- void GenerateTextureCoords(const unsigned int width,
- const unsigned int height);
-
- // -------------------------------------------------------------------
- /** Read the first skin from the file and skip all others ...
- * \param iNumSkins Number of skins in the file
- * \param szCursor Position of the first skin (offset 84)
- */
- void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
- const unsigned char** szCursorOut);
+ // -------------------------------------------------------------------
+ /** Import a HMP4 file
+ */
+ void InternReadFile_HMP4( );
+
+ // -------------------------------------------------------------------
+ /** Import a HMP5 file
+ */
+ void InternReadFile_HMP5( );
+
+ // -------------------------------------------------------------------
+ /** Import a HMP7 file
+ */
+ void InternReadFile_HMP7( );
+
+ // -------------------------------------------------------------------
+ /** Validate a HMP 5,4,7 file header
+ */
+ void ValidateHeader_HMP457( );
+
+ // -------------------------------------------------------------------
+ /** Try to load one material from the file, if this fails create
+ * a default material
+ */
+ void CreateMaterial(const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Build a list of output faces and vertices. The function
+ * triangulates the height map read from the file
+ * \param width Width of the height field
+ * \param width Height of the height field
+ */
+ void CreateOutputFaceList(unsigned int width,unsigned int height);
+
+ // -------------------------------------------------------------------
+ /** Generate planar texture coordinates for a terrain
+ * \param width Width of the terrain, in vertices
+ * \param height Height of the terrain, in vertices
+ */
+ void GenerateTextureCoords(const unsigned int width,
+ const unsigned int height);
+
+ // -------------------------------------------------------------------
+ /** Read the first skin from the file and skip all others ...
+ * \param iNumSkins Number of skins in the file
+ * \param szCursor Position of the first skin (offset 84)
+ */
+ void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
+ const unsigned char** szCursorOut);
private:
diff --git a/src/3rdparty/assimp/code/HalfLifeFileData.h b/src/3rdparty/assimp/code/HalfLifeFileData.h
index 37be9ec20..54fe83734 100644
--- a/src/3rdparty/assimp/code/HalfLifeFileData.h
+++ b/src/3rdparty/assimp/code/HalfLifeFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,97 +49,96 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MDLFILEHELPER2_H_INC
#define AI_MDLFILEHELPER2_H_INC
-#include "./../include/assimp/Compiler/pushpack1.h"
-
#include "MDLFileData.h"
+#include "./../include/assimp/Compiler/pushpack1.h"
-namespace Assimp {
-namespace MDL {
+namespace Assimp {
+namespace MDL {
// magic bytes used in Half Life 2 MDL models
-#define AI_MDL_MAGIC_NUMBER_BE_HL2a AI_MAKE_MAGIC("IDST")
-#define AI_MDL_MAGIC_NUMBER_LE_HL2a AI_MAKE_MAGIC("TSDI")
-#define AI_MDL_MAGIC_NUMBER_BE_HL2b AI_MAKE_MAGIC("IDSQ")
-#define AI_MDL_MAGIC_NUMBER_LE_HL2b AI_MAKE_MAGIC("QSDI")
+#define AI_MDL_MAGIC_NUMBER_BE_HL2a AI_MAKE_MAGIC("IDST")
+#define AI_MDL_MAGIC_NUMBER_LE_HL2a AI_MAKE_MAGIC("TSDI")
+#define AI_MDL_MAGIC_NUMBER_BE_HL2b AI_MAKE_MAGIC("IDSQ")
+#define AI_MDL_MAGIC_NUMBER_LE_HL2b AI_MAKE_MAGIC("QSDI")
// ---------------------------------------------------------------------------
/** \struct Header_HL2
* \brief Data structure for the HL2 main header
*/
// ---------------------------------------------------------------------------
-struct Header_HL2
+struct Header_HL2
{
- //! magic number: "IDST"/"IDSQ"
- char ident[4];
-
- //! Version number
- int32_t version;
-
- //! Original file name in pak ?
- char name[64];
-
- //! Length of file name/length of file?
- int32_t length;
-
- //! For viewer, ignored
- aiVector3D eyeposition;
- aiVector3D min;
- aiVector3D max;
-
- //! AABB of the model
- aiVector3D bbmin;
- aiVector3D bbmax;
-
- // File flags
- int32_t flags;
-
- //! NUmber of bones contained in the file
- int32_t numbones;
- int32_t boneindex;
-
- //! Number of bone controllers for bone animation
- int32_t numbonecontrollers;
- int32_t bonecontrollerindex;
-
- //! More bounding boxes ...
- int32_t numhitboxes;
- int32_t hitboxindex;
-
- //! Animation sequences in the file
- int32_t numseq;
- int32_t seqindex;
-
- //! Loaded sequences. Ignored
- int32_t numseqgroups;
- int32_t seqgroupindex;
-
- //! Raw texture data
- int32_t numtextures;
- int32_t textureindex;
- int32_t texturedataindex;
-
- //! Number of skins (=textures?)
- int32_t numskinref;
- int32_t numskinfamilies;
- int32_t skinindex;
-
- //! Number of parts
- int32_t numbodyparts;
- int32_t bodypartindex;
-
- //! attachable points for gameplay and physics
- int32_t numattachments;
- int32_t attachmentindex;
-
- //! Table of sound effects associated with the model
- int32_t soundtable;
- int32_t soundindex;
- int32_t soundgroups;
- int32_t soundgroupindex;
-
- //! Number of animation transitions
- int32_t numtransitions;
- int32_t transitionindex;
+ //! magic number: "IDST"/"IDSQ"
+ char ident[4];
+
+ //! Version number
+ int32_t version;
+
+ //! Original file name in pak ?
+ char name[64];
+
+ //! Length of file name/length of file?
+ int32_t length;
+
+ //! For viewer, ignored
+ aiVector3D eyeposition;
+ aiVector3D min;
+ aiVector3D max;
+
+ //! AABB of the model
+ aiVector3D bbmin;
+ aiVector3D bbmax;
+
+ // File flags
+ int32_t flags;
+
+ //! NUmber of bones contained in the file
+ int32_t numbones;
+ int32_t boneindex;
+
+ //! Number of bone controllers for bone animation
+ int32_t numbonecontrollers;
+ int32_t bonecontrollerindex;
+
+ //! More bounding boxes ...
+ int32_t numhitboxes;
+ int32_t hitboxindex;
+
+ //! Animation sequences in the file
+ int32_t numseq;
+ int32_t seqindex;
+
+ //! Loaded sequences. Ignored
+ int32_t numseqgroups;
+ int32_t seqgroupindex;
+
+ //! Raw texture data
+ int32_t numtextures;
+ int32_t textureindex;
+ int32_t texturedataindex;
+
+ //! Number of skins (=textures?)
+ int32_t numskinref;
+ int32_t numskinfamilies;
+ int32_t skinindex;
+
+ //! Number of parts
+ int32_t numbodyparts;
+ int32_t bodypartindex;
+
+ //! attachable points for gameplay and physics
+ int32_t numattachments;
+ int32_t attachmentindex;
+
+ //! Table of sound effects associated with the model
+ int32_t soundtable;
+ int32_t soundindex;
+ int32_t soundgroups;
+ int32_t soundgroupindex;
+
+ //! Number of animation transitions
+ int32_t numtransitions;
+ int32_t transitionindex;
} PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h"
diff --git a/src/3rdparty/assimp/code/Hash.h b/src/3rdparty/assimp/code/Hash.h
index d30538e8e..cd7ca6def 100644
--- a/src/3rdparty/assimp/code/Hash.h
+++ b/src/3rdparty/assimp/code/Hash.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,8 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_HASH_H_INCLUDED
#define AI_HASH_H_INCLUDED
+#include <stdint.h>
+#include <string.h>
+
// ------------------------------------------------------------------------------------------------
-// Hashing function taken from
+// Hashing function taken from
// http://www.azillionmonkeys.com/qed/hash.html
// (incremental version)
//
@@ -69,7 +72,7 @@ uint32_t tmp;
int rem;
if (!data) return 0;
- if (!len)len = (uint32_t)::strlen(data);
+ if (!len)len = (uint32_t)::strlen(data);
rem = len & 3;
len >>= 2;
diff --git a/src/3rdparty/assimp/code/IFCBoolean.cpp b/src/3rdparty/assimp/code/IFCBoolean.cpp
index 3581d2a9e..042515311 100644
--- a/src/3rdparty/assimp/code/IFCBoolean.cpp
+++ b/src/3rdparty/assimp/code/IFCBoolean.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2010, 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,219 +42,314 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implements a subset of Ifc boolean operations
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
#include "PolyTools.h"
#include "ProcessHelper.h"
+#include "Defines.h"
#include <iterator>
+#include <tuple>
+
namespace Assimp {
- namespace IFC {
-
-// ------------------------------------------------------------------------------------------------
-enum Intersect {
- Intersect_No,
- Intersect_LiesOnPlane,
- Intersect_Yes
-};
+ namespace IFC {
// ------------------------------------------------------------------------------------------------
-Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const IfcVector3& e0,
- const IfcVector3& e1,
- IfcVector3& out)
+// Calculates intersection between line segment and plane. To catch corner cases, specify which side you prefer.
+// The function then generates a hit only if the end is beyond a certain margin in that direction, filtering out
+// "very close to plane" ghost hits as long as start and end stay directly on or within the given plane side.
+bool IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const IfcVector3& e0,
+ const IfcVector3& e1, bool assumeStartOnWhiteSide, IfcVector3& out)
{
- const IfcVector3 pdelta = e0 - p, seg = e1-e0;
- const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
-
- if (std::fabs(dotOne) < 1e-6) {
- return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
- }
-
- const IfcFloat t = dotTwo/dotOne;
- // t must be in [0..1] if the intersection point is within the given segment
- if (t > 1.f || t < 0.f) {
- return Intersect_No;
- }
- out = e0+t*seg;
- return Intersect_Yes;
+ const IfcVector3 pdelta = e0 - p, seg = e1 - e0;
+ const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
+
+ // if segment ends on plane, do not report a hit. We stay on that side until a following segment starting at this
+ // point leaves the plane through the other side
+ if( std::abs(dotOne + dotTwo) < 1e-6 )
+ return false;
+
+ // if segment starts on the plane, report a hit only if the end lies on the *other* side
+ if( std::abs(dotTwo) < 1e-6 )
+ {
+ if( (assumeStartOnWhiteSide && dotOne + dotTwo < 1e-6) || (!assumeStartOnWhiteSide && dotOne + dotTwo > -1e-6) )
+ {
+ out = e0;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // ignore if segment is parallel to plane and far away from it on either side
+ // Warning: if there's a few thousand of such segments which slowly accumulate beyond the epsilon, no hit would be registered
+ if( std::abs(dotOne) < 1e-6 )
+ return false;
+
+ // t must be in [0..1] if the intersection point is within the given segment
+ const IfcFloat t = dotTwo / dotOne;
+ if( t > 1.0 || t < 0.0 )
+ return false;
+
+ out = e0 + t*seg;
+ return true;
}
// ------------------------------------------------------------------------------------------------
-void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv)
+void FilterPolygon(std::vector<IfcVector3>& resultpoly)
{
- ai_assert(hs != NULL);
-
- const IfcPlane* const plane = hs->BaseSurface->ToPtr<IfcPlane>();
- if(!plane) {
- IFCImporter::LogError("expected IfcPlane as base surface for the IfcHalfSpaceSolid");
- return;
- }
-
- // extract plane base position vector and normal vector
- IfcVector3 p,n(0.f,0.f,1.f);
- if (plane->Position->Axis) {
- ConvertDirection(n,plane->Position->Axis.Get());
- }
- ConvertCartesianPoint(p,plane->Position->Location);
-
- if(!IsTrue(hs->AgreementFlag)) {
- n *= -1.f;
- }
-
- // clip the current contents of `meshout` against the plane we obtained from the second operand
- const std::vector<IfcVector3>& in = first_operand.verts;
- std::vector<IfcVector3>& outvert = result.verts;
-
- std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin(),
- end = first_operand.vertcnt.end(), iit;
-
- outvert.reserve(in.size());
- result.vertcnt.reserve(first_operand.vertcnt.size());
-
- unsigned int vidx = 0;
- for(iit = begin; iit != end; vidx += *iit++) {
-
- unsigned int newcount = 0;
- for(unsigned int i = 0; i < *iit; ++i) {
- const IfcVector3& e0 = in[vidx+i], e1 = in[vidx+(i+1)%*iit];
-
- // does the next segment intersect the plane?
- IfcVector3 isectpos;
- const Intersect isect = IntersectSegmentPlane(p,n,e0,e1,isectpos);
- if (isect == Intersect_No || isect == Intersect_LiesOnPlane) {
- if ( (e0-p).Normalize()*n > 0 ) {
- outvert.push_back(e0);
- ++newcount;
- }
- }
- else if (isect == Intersect_Yes) {
- if ( (e0-p).Normalize()*n > 0 ) {
- // e0 is on the right side, so keep it
- outvert.push_back(e0);
- outvert.push_back(isectpos);
- newcount += 2;
- }
- else {
- // e0 is on the wrong side, so drop it and keep e1 instead
- outvert.push_back(isectpos);
- ++newcount;
- }
- }
- }
-
- if (!newcount) {
- continue;
- }
-
- IfcVector3 vmin,vmax;
- ArrayBounds(&*(outvert.end()-newcount),newcount,vmin,vmax);
-
- // filter our IfcFloat points - those may happen if a point lies
- // directly on the intersection line. However, due to IfcFloat
- // precision a bitwise comparison is not feasible to detect
- // this case.
- const IfcFloat epsilon = (vmax-vmin).SquareLength() / 1e6f;
- FuzzyVectorCompare fz(epsilon);
-
- std::vector<IfcVector3>::iterator e = std::unique( outvert.end()-newcount, outvert.end(), fz );
-
- if (e != outvert.end()) {
- newcount -= static_cast<unsigned int>(std::distance(e,outvert.end()));
- outvert.erase(e,outvert.end());
- }
- if (fz(*( outvert.end()-newcount),outvert.back())) {
- outvert.pop_back();
- --newcount;
- }
- if(newcount > 2) {
- result.vertcnt.push_back(newcount);
- }
- else while(newcount-->0) {
- result.verts.pop_back();
- }
-
- }
- IFCImporter::LogDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)");
+ if( resultpoly.size() < 3 )
+ {
+ resultpoly.clear();
+ return;
+ }
+
+ IfcVector3 vmin, vmax;
+ ArrayBounds(resultpoly.data(), resultpoly.size(), vmin, vmax);
+
+ // filter our IfcFloat points - those may happen if a point lies
+ // directly on the intersection line or directly on the clipping plane
+ const IfcFloat epsilon = (vmax - vmin).SquareLength() / 1e6f;
+ FuzzyVectorCompare fz(epsilon);
+ std::vector<IfcVector3>::iterator e = std::unique(resultpoly.begin(), resultpoly.end(), fz);
+
+ if( e != resultpoly.end() )
+ resultpoly.erase(e, resultpoly.end());
+
+ if( !resultpoly.empty() && fz(resultpoly.front(), resultpoly.back()) )
+ resultpoly.pop_back();
}
// ------------------------------------------------------------------------------------------------
-// Check if e0-e1 intersects a sub-segment of the given boundary line.
-// note: this functions works on 3D vectors, but performs its intersection checks solely in xy.
-bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, const std::vector<IfcVector3>& boundary,
- std::vector<size_t>& intersected_boundary_segments,
- std::vector<IfcVector3>& intersected_boundary_points,
- bool half_open = false,
- bool* e0_hits_border = NULL)
+void WritePolygon(std::vector<IfcVector3>& resultpoly, TempMesh& result)
{
- ai_assert(intersected_boundary_segments.empty());
- ai_assert(intersected_boundary_points.empty());
-
- if(e0_hits_border) {
- *e0_hits_border = false;
- }
-
- const IfcVector3& e = e1 - e0;
-
- for (size_t i = 0, bcount = boundary.size(); i < bcount; ++i) {
- // boundary segment i: b0-b1
- const IfcVector3& b0 = boundary[i];
- const IfcVector3& b1 = boundary[(i+1) % bcount];
+ FilterPolygon(resultpoly);
- const IfcVector3& b = b1 - b0;
-
- // segment-segment intersection
- // solve b0 + b*s = e0 + e*t for (s,t)
- const IfcFloat det = (-b.x * e.y + e.x * b.y);
- if(std::fabs(det) < 1e-6) {
- // no solutions (parallel lines)
- continue;
- }
+ if( resultpoly.size() > 2 )
+ {
+ result.verts.insert(result.verts.end(), resultpoly.begin(), resultpoly.end());
+ result.vertcnt.push_back(resultpoly.size());
+ }
+}
- const IfcFloat x = b0.x - e0.x;
- const IfcFloat y = b0.y - e0.y;
- const IfcFloat s = (x*e.y - e.x*y)/det;
- const IfcFloat t = (x*b.y - b.x*y)/det;
+// ------------------------------------------------------------------------------------------------
+void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& /*conv*/)
+{
+ ai_assert(hs != NULL);
+
+ const IfcPlane* const plane = hs->BaseSurface->ToPtr<IfcPlane>();
+ if(!plane) {
+ IFCImporter::LogError("expected IfcPlane as base surface for the IfcHalfSpaceSolid");
+ return;
+ }
+
+ // extract plane base position vector and normal vector
+ IfcVector3 p,n(0.f,0.f,1.f);
+ if (plane->Position->Axis) {
+ ConvertDirection(n,plane->Position->Axis.Get());
+ }
+ ConvertCartesianPoint(p,plane->Position->Location);
+
+ if(!IsTrue(hs->AgreementFlag)) {
+ n *= -1.f;
+ }
+
+ // clip the current contents of `meshout` against the plane we obtained from the second operand
+ const std::vector<IfcVector3>& in = first_operand.verts;
+ std::vector<IfcVector3>& outvert = result.verts;
+
+ std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin(),
+ end = first_operand.vertcnt.end(), iit;
+
+ outvert.reserve(in.size());
+ result.vertcnt.reserve(first_operand.vertcnt.size());
+
+ unsigned int vidx = 0;
+ for(iit = begin; iit != end; vidx += *iit++) {
+
+ unsigned int newcount = 0;
+ bool isAtWhiteSide = (in[vidx] - p) * n > -1e-6;
+ for( unsigned int i = 0; i < *iit; ++i ) {
+ const IfcVector3& e0 = in[vidx + i], e1 = in[vidx + (i + 1) % *iit];
+
+ // does the next segment intersect the plane?
+ IfcVector3 isectpos;
+ if( IntersectSegmentPlane(p, n, e0, e1, isAtWhiteSide, isectpos) ) {
+ if( isAtWhiteSide ) {
+ // e0 is on the right side, so keep it
+ outvert.push_back(e0);
+ outvert.push_back(isectpos);
+ newcount += 2;
+ }
+ else {
+ // e0 is on the wrong side, so drop it and keep e1 instead
+ outvert.push_back(isectpos);
+ ++newcount;
+ }
+ isAtWhiteSide = !isAtWhiteSide;
+ }
+ else
+ {
+ if( isAtWhiteSide ) {
+ outvert.push_back(e0);
+ ++newcount;
+ }
+ }
+ }
+
+ if (!newcount) {
+ continue;
+ }
+
+ IfcVector3 vmin,vmax;
+ ArrayBounds(&*(outvert.end()-newcount),newcount,vmin,vmax);
+
+ // filter our IfcFloat points - those may happen if a point lies
+ // directly on the intersection line. However, due to IfcFloat
+ // precision a bitwise comparison is not feasible to detect
+ // this case.
+ const IfcFloat epsilon = (vmax-vmin).SquareLength() / 1e6f;
+ FuzzyVectorCompare fz(epsilon);
+
+ std::vector<IfcVector3>::iterator e = std::unique( outvert.end()-newcount, outvert.end(), fz );
+
+ if (e != outvert.end()) {
+ newcount -= static_cast<unsigned int>(std::distance(e,outvert.end()));
+ outvert.erase(e,outvert.end());
+ }
+ if (fz(*( outvert.end()-newcount),outvert.back())) {
+ outvert.pop_back();
+ --newcount;
+ }
+ if(newcount > 2) {
+ result.vertcnt.push_back(newcount);
+ }
+ else while(newcount-->0) {
+ result.verts.pop_back();
+ }
+
+ }
+ IFCImporter::LogDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)");
+}
+// ------------------------------------------------------------------------------------------------
+// Check if e0-e1 intersects a sub-segment of the given boundary line.
+// note: this functions works on 3D vectors, but performs its intersection checks solely in xy.
+// New version takes the supposed inside/outside state as a parameter and treats corner cases as if
+// the line stays on that side. This should make corner cases more stable.
+// Two million assumptions! Boundary should have all z at 0.0, will be treated as closed, should not have
+// segments with length <1e-6, self-intersecting might break the corner case handling... just don't go there, ok?
+bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const std::vector<IfcVector3>& boundary,
+ const bool isStartAssumedInside, std::vector<std::pair<size_t, IfcVector3> >& intersect_results,
+ const bool halfOpen = false)
+{
+ ai_assert(intersect_results.empty());
+
+ // determine winding order - necessary to detect segments going "inwards" or "outwards" from a point directly on the border
+ // positive sum of angles means clockwise order when looking down the -Z axis
+ IfcFloat windingOrder = 0.0;
+ for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
+ IfcVector3 b01 = boundary[(i + 1) % bcount] - boundary[i];
+ IfcVector3 b12 = boundary[(i + 2) % bcount] - boundary[(i + 1) % bcount];
+ IfcVector3 b1_side = IfcVector3(b01.y, -b01.x, 0.0); // rotated 90° clockwise in Z plane
+ // Warning: rough estimate only. A concave poly with lots of small segments each featuring a small counter rotation
+ // could fool the accumulation. Correct implementation would be sum( acos( b01 * b2) * sign( b12 * b1_side))
+ windingOrder += (b1_side.x*b12.x + b1_side.y*b12.y);
+ }
+ windingOrder = windingOrder > 0.0 ? 1.0 : -1.0;
+
+ const IfcVector3 e = e1 - e0;
+
+ for( size_t i = 0, bcount = boundary.size(); i < bcount; ++i ) {
+ // boundary segment i: b0-b1
+ const IfcVector3& b0 = boundary[i];
+ const IfcVector3& b1 = boundary[(i + 1) % bcount];
+ IfcVector3 b = b1 - b0;
+ IfcFloat b_sqlen_inv = 1.0 / b.SquareLength();
+
+ // segment-segment intersection
+ // solve b0 + b*s = e0 + e*t for (s,t)
+ const IfcFloat det = (-b.x * e.y + e.x * b.y);
+ if( std::abs(det) < 1e-6 ) {
+ // no solutions (parallel lines)
+ continue;
+ }
+
+ const IfcFloat x = b0.x - e0.x;
+ const IfcFloat y = b0.y - e0.y;
+ const IfcFloat s = (x*e.y - e.x*y) / det; // scale along boundary edge
+ const IfcFloat t = (x*b.y - b.x*y) / det; // scale along given segment
+ const IfcVector3 p = e0 + e*t;
#ifdef ASSIMP_BUILD_DEBUG
- const IfcVector3 check = b0 + b*s - (e0 + e*t);
- ai_assert((IfcVector2(check.x,check.y)).SquareLength() < 1e-5);
+ const IfcVector3 check = b0 + b*s - p;
+ ai_assert((IfcVector2(check.x, check.y)).SquareLength() < 1e-5);
#endif
- // for a valid intersection, s-t should be in range [0,1].
- // note that for t (i.e. the segment point) we only use a
- // half-sided epsilon because the next segment should catch
- // this case.
- const IfcFloat epsilon = 1e-6;
- if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) {
-
- if (e0_hits_border && !*e0_hits_border) {
- *e0_hits_border = std::fabs(t) < 1e-5f;
- }
-
- const IfcVector3& p = e0 + e*t;
-
- // only insert the point into the list if it is sufficiently
- // far away from the previous intersection point. This way,
- // we avoid duplicate detection if the intersection is
- // directly on the vertex between two segments.
- if (!intersected_boundary_points.empty() && intersected_boundary_segments.back()==i-1 ) {
- const IfcVector3 diff = intersected_boundary_points.back() - p;
- if(IfcVector2(diff.x, diff.y).SquareLength() < 1e-7) {
- continue;
- }
- }
- intersected_boundary_segments.push_back(i);
- intersected_boundary_points.push_back(p);
- }
- }
-
- return !intersected_boundary_segments.empty();
+ // also calculate the distance of e0 and e1 to the segment. We need to detect the "starts directly on segment"
+ // and "ends directly at segment" cases
+ bool startsAtSegment, endsAtSegment;
+ {
+ // calculate closest point to each end on the segment, clamp that point to the segment's length, then check
+ // distance to that point. This approach is like testing if e0 is inside a capped cylinder.
+ IfcFloat et0 = (b.x*(e0.x - b0.x) + b.y*(e0.y - b0.y)) * b_sqlen_inv;
+ IfcVector3 closestPosToE0OnBoundary = b0 + std::max(IfcFloat(0.0), std::min(IfcFloat(1.0), et0)) * b;
+ startsAtSegment = (closestPosToE0OnBoundary - IfcVector3(e0.x, e0.y, 0.0)).SquareLength() < 1e-12;
+ IfcFloat et1 = (b.x*(e1.x - b0.x) + b.y*(e1.y - b0.y)) * b_sqlen_inv;
+ IfcVector3 closestPosToE1OnBoundary = b0 + std::max(IfcFloat(0.0), std::min(IfcFloat(1.0), et1)) * b;
+ endsAtSegment = (closestPosToE1OnBoundary - IfcVector3(e1.x, e1.y, 0.0)).SquareLength() < 1e-12;
+ }
+
+ // Line segment ends at boundary -> ignore any hit, it will be handled by possibly following segments
+ if( endsAtSegment && !halfOpen )
+ continue;
+
+ // Line segment starts at boundary -> generate a hit only if following that line would change the INSIDE/OUTSIDE
+ // state. This should catch the case where a connected set of segments has a point directly on the boundary,
+ // one segment not hitting it because it ends there and the next segment not hitting it because it starts there
+ // Should NOT generate a hit if the segment only touches the boundary but turns around and stays inside.
+ if( startsAtSegment )
+ {
+ IfcVector3 inside_dir = IfcVector3(b.y, -b.x, 0.0) * windingOrder;
+ bool isGoingInside = (inside_dir * e) > 0.0;
+ if( isGoingInside == isStartAssumedInside )
+ continue;
+
+ // only insert the point into the list if it is sufficiently far away from the previous intersection point.
+ // This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
+ if( !intersect_results.empty() && intersect_results.back().first == i - 1 )
+ {
+ const IfcVector3 diff = intersect_results.back().second - e0;
+ if( IfcVector2(diff.x, diff.y).SquareLength() < 1e-10 )
+ continue;
+ }
+ intersect_results.push_back(std::make_pair(i, e0));
+ continue;
+ }
+
+ // for a valid intersection, s and t should be in range [0,1]. Including a bit of epsilon on s, potential double
+ // hits on two consecutive boundary segments are filtered
+ if( s >= -1e-6 * b_sqlen_inv && s <= 1.0 + 1e-6*b_sqlen_inv && t >= 0.0 && (t <= 1.0 || halfOpen) )
+ {
+ // only insert the point into the list if it is sufficiently far away from the previous intersection point.
+ // This way, we avoid duplicate detection if the intersection is directly on the vertex between two segments.
+ if( !intersect_results.empty() && intersect_results.back().first == i - 1 )
+ {
+ const IfcVector3 diff = intersect_results.back().second - p;
+ if( IfcVector2(diff.x, diff.y).SquareLength() < 1e-10 )
+ continue;
+ }
+ intersect_results.push_back(std::make_pair(i, p));
+ }
+ }
+
+ return !intersect_results.empty();
}
@@ -262,468 +357,476 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
// note: this functions works on 3D vectors, but performs its intersection checks solely in xy.
bool PointInPoly(const IfcVector3& p, const std::vector<IfcVector3>& boundary)
{
- // even-odd algorithm: take a random vector that extends from p to infinite
- // and counts how many times it intersects edges of the boundary.
- // because checking for segment intersections is prone to numeric inaccuracies
- // or double detections (i.e. when hitting multiple adjacent segments at their
- // shared vertices) we do it thrice with different rays and vote on it.
-
- // the even-odd algorithm doesn't work for points which lie directly on
- // the border of the polygon. If any of our attempts produces this result,
- // we return false immediately.
-
- std::vector<size_t> intersected_boundary_segments;
- std::vector<IfcVector3> intersected_boundary_points;
- size_t votes = 0;
-
- bool is_border;
- IntersectsBoundaryProfile(p, p + IfcVector3(1.0,0,0), boundary,
- intersected_boundary_segments,
- intersected_boundary_points, true, &is_border);
-
- if(is_border) {
- return false;
- }
-
- votes += intersected_boundary_segments.size() % 2;
+ // even-odd algorithm: take a random vector that extends from p to infinite
+ // and counts how many times it intersects edges of the boundary.
+ // because checking for segment intersections is prone to numeric inaccuracies
+ // or double detections (i.e. when hitting multiple adjacent segments at their
+ // shared vertices) we do it thrice with different rays and vote on it.
- intersected_boundary_segments.clear();
- intersected_boundary_points.clear();
+ // the even-odd algorithm doesn't work for points which lie directly on
+ // the border of the polygon. If any of our attempts produces this result,
+ // we return false immediately.
- IntersectsBoundaryProfile(p, p + IfcVector3(0,1.0,0), boundary,
- intersected_boundary_segments,
- intersected_boundary_points, true, &is_border);
+ std::vector<std::pair<size_t, IfcVector3> > intersected_boundary;
+ size_t votes = 0;
- if(is_border) {
- return false;
- }
+ IntersectsBoundaryProfile(p, p + IfcVector3(1.0, 0, 0), boundary, true, intersected_boundary, true);
+ votes += intersected_boundary.size() % 2;
- votes += intersected_boundary_segments.size() % 2;
+ intersected_boundary.clear();
+ IntersectsBoundaryProfile(p, p + IfcVector3(0, 1.0, 0), boundary, true, intersected_boundary, true);
+ votes += intersected_boundary.size() % 2;
- intersected_boundary_segments.clear();
- intersected_boundary_points.clear();
+ intersected_boundary.clear();
+ IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true);
+ votes += intersected_boundary.size() % 2;
- IntersectsBoundaryProfile(p, p + IfcVector3(0.6,-0.6,0.0), boundary,
- intersected_boundary_segments,
- intersected_boundary_points, true, &is_border);
-
- if(is_border) {
- return false;
- }
-
- votes += intersected_boundary_segments.size() % 2;
- //ai_assert(votes == 3 || votes == 0);
- return votes > 1;
+// ai_assert(votes == 3 || votes == 0);
+ return votes > 1;
}
// ------------------------------------------------------------------------------------------------
-void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBoundedHalfSpace* hs, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv)
+void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBoundedHalfSpace* hs, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& conv)
{
- ai_assert(hs != NULL);
-
- const IfcPlane* const plane = hs->BaseSurface->ToPtr<IfcPlane>();
- if(!plane) {
- IFCImporter::LogError("expected IfcPlane as base surface for the IfcHalfSpaceSolid");
- return;
- }
-
- // extract plane base position vector and normal vector
- IfcVector3 p,n(0.f,0.f,1.f);
- if (plane->Position->Axis) {
- ConvertDirection(n,plane->Position->Axis.Get());
- }
- ConvertCartesianPoint(p,plane->Position->Location);
-
- if(!IsTrue(hs->AgreementFlag)) {
- n *= -1.f;
- }
-
- n.Normalize();
-
- // obtain the polygonal bounding volume
- boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
- if(!ProcessCurve(hs->PolygonalBoundary, *profile.get(), conv)) {
- IFCImporter::LogError("expected valid polyline for boundary of boolean halfspace");
- return;
- }
-
- IfcMatrix4 proj_inv;
- ConvertAxisPlacement(proj_inv,hs->Position);
-
- // and map everything into a plane coordinate space so all intersection
- // tests can be done in 2D space.
- IfcMatrix4 proj = proj_inv;
- proj.Inverse();
-
- // clip the current contents of `meshout` against the plane we obtained from the second operand
- const std::vector<IfcVector3>& in = first_operand.verts;
- std::vector<IfcVector3>& outvert = result.verts;
-
- std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin(),
- end = first_operand.vertcnt.end(), iit;
-
- outvert.reserve(in.size());
- result.vertcnt.reserve(first_operand.vertcnt.size());
-
- std::vector<size_t> intersected_boundary_segments;
- std::vector<IfcVector3> intersected_boundary_points;
-
- // TODO: the following algorithm doesn't handle all cases.
- unsigned int vidx = 0;
- for(iit = begin; iit != end; vidx += *iit++) {
- if (!*iit) {
- continue;
- }
-
- unsigned int newcount = 0;
- bool was_outside_boundary = !PointInPoly(proj * in[vidx], profile->verts);
-
- // used any more?
- //size_t last_intersected_boundary_segment;
- IfcVector3 last_intersected_boundary_point;
-
- bool extra_point_flag = false;
- IfcVector3 extra_point;
-
- IfcVector3 enter_volume;
- bool entered_volume_flag = false;
-
- for(unsigned int i = 0; i < *iit; ++i) {
- // current segment: [i,i+1 mod size] or [*extra_point,i] if extra_point_flag is set
- const IfcVector3& e0 = extra_point_flag ? extra_point : in[vidx+i];
- const IfcVector3& e1 = extra_point_flag ? in[vidx+i] : in[vidx+(i+1)%*iit];
-
- // does the current segment intersect the polygonal boundary?
- const IfcVector3& e0_plane = proj * e0;
- const IfcVector3& e1_plane = proj * e1;
-
- intersected_boundary_segments.clear();
- intersected_boundary_points.clear();
-
- const bool is_outside_boundary = !PointInPoly(e1_plane, profile->verts);
- const bool is_boundary_intersection = is_outside_boundary != was_outside_boundary;
-
- IntersectsBoundaryProfile(e0_plane, e1_plane, profile->verts,
- intersected_boundary_segments,
- intersected_boundary_points);
-
- ai_assert(!is_boundary_intersection || !intersected_boundary_segments.empty());
-
- // does the current segment intersect the plane?
- // (no extra check if this is an extra point)
- IfcVector3 isectpos;
- const Intersect isect = extra_point_flag ? Intersect_No : IntersectSegmentPlane(p,n,e0,e1,isectpos);
-
-#ifdef ASSIMP_BUILD_DEBUG
- if (isect == Intersect_Yes) {
- const IfcFloat f = std::fabs((isectpos - p)*n);
- ai_assert(f < 1e-5);
- }
-#endif
-
- const bool is_white_side = (e0-p)*n >= -1e-6;
-
- // e0 on good side of plane? (i.e. we should keep all geometry on this side)
- if (is_white_side) {
- // but is there an intersection in e0-e1 and is e1 in the clipping
- // boundary? In this case, generate a line that only goes to the
- // intersection point.
- if (isect == Intersect_Yes && !is_outside_boundary) {
- outvert.push_back(e0);
- ++newcount;
-
- outvert.push_back(isectpos);
- ++newcount;
-
- /*
- // this is, however, only a line that goes to the plane, but not
- // necessarily to the point where the bounding volume on the
- // black side of the plane is hit. So basically, we need another
- // check for [isectpos-e1], which should yield an intersection
- // point.
- extra_point_flag = true;
- extra_point = isectpos;
-
- was_outside_boundary = true;
- continue; */
-
- // [isectpos, enter_volume] potentially needs extra points.
- // For this, we determine the intersection point with the
- // bounding volume and project it onto the plane.
- /*
- const IfcVector3& enter_volume_proj = proj * enter_volume;
- const IfcVector3& enter_isectpos = proj * isectpos;
-
- intersected_boundary_segments.clear();
- intersected_boundary_points.clear();
-
- IntersectsBoundaryProfile(enter_volume_proj, enter_isectpos, profile->verts,
- intersected_boundary_segments,
- intersected_boundary_points);
-
- if(!intersected_boundary_segments.empty()) {
-
- vec = vec + ((p - vec) * n) * n;
- }
- */
-
- //entered_volume_flag = true;
- }
- else {
- outvert.push_back(e0);
- ++newcount;
- }
- }
- // e0 on bad side of plane, e1 on good (i.e. we should remove geometry on this side,
- // but only if it is within the bounding volume).
- else if (isect == Intersect_Yes) {
- // is e0 within the clipping volume? Insert the intersection point
- // of [e0,e1] and the plane instead of e0.
- if(was_outside_boundary) {
- outvert.push_back(e0);
- }
- else {
- if(entered_volume_flag) {
- const IfcVector3& fix_point = enter_volume + ((p - enter_volume) * n) * n;
- outvert.push_back(fix_point);
- ++newcount;
- }
-
- outvert.push_back(isectpos);
- }
- entered_volume_flag = false;
- ++newcount;
- }
- else { // no intersection with plane or parallel; e0,e1 are on the bad side
-
- // did we just pass the boundary line to the poly bounding?
- if (is_boundary_intersection) {
-
- // and are now outside the clipping boundary?
- if (is_outside_boundary) {
- // in this case, get the point where the clipping boundary
- // was entered first. Then, get the point where the clipping
- // boundary volume was left! These two points with the plane
- // normal form another plane that intersects the clipping
- // volume. There are two ways to get from the first to the
- // second point along the intersection curve, try to pick the
- // one that lies within the current polygon.
-
- // TODO this approach doesn't handle all cases
-
- // ...
-
- IfcFloat d = 1e20;
- IfcVector3 vclosest;
- BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
- const IfcFloat dn = (v-e1_plane).SquareLength();
- if (dn < d) {
- d = dn;
- vclosest = v;
- }
- }
-
- vclosest = proj_inv * vclosest;
- if(entered_volume_flag) {
- const IfcVector3& fix_point = vclosest + ((p - vclosest) * n) * n;
- outvert.push_back(fix_point);
- ++newcount;
-
- entered_volume_flag = false;
- }
-
- outvert.push_back(vclosest);
- ++newcount;
-
- //outvert.push_back(e1);
- //++newcount;
- }
- else {
- entered_volume_flag = true;
-
- // we just entered the clipping boundary. Record the point
- // and the segment where we entered and also generate this point.
- //last_intersected_boundary_segment = intersected_boundary_segments.front();
- //last_intersected_boundary_point = intersected_boundary_points.front();
-
- outvert.push_back(e0);
- ++newcount;
-
- IfcFloat d = 1e20;
- IfcVector3 vclosest;
- BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
- const IfcFloat dn = (v-e0_plane).SquareLength();
- if (dn < d) {
- d = dn;
- vclosest = v;
- }
- }
-
- enter_volume = proj_inv * vclosest;
- outvert.push_back(enter_volume);
- ++newcount;
- }
- }
- // if not, we just keep the vertex
- else if (is_outside_boundary) {
- outvert.push_back(e0);
- ++newcount;
-
- entered_volume_flag = false;
- }
- }
-
- was_outside_boundary = is_outside_boundary;
- extra_point_flag = false;
- }
-
- if (!newcount) {
- continue;
- }
-
- IfcVector3 vmin,vmax;
- ArrayBounds(&*(outvert.end()-newcount),newcount,vmin,vmax);
-
- // filter our IfcFloat points - those may happen if a point lies
- // directly on the intersection line. However, due to IfcFloat
- // precision a bitwise comparison is not feasible to detect
- // this case.
- const IfcFloat epsilon = (vmax-vmin).SquareLength() / 1e6f;
- FuzzyVectorCompare fz(epsilon);
-
- std::vector<IfcVector3>::iterator e = std::unique( outvert.end()-newcount, outvert.end(), fz );
-
- if (e != outvert.end()) {
- newcount -= static_cast<unsigned int>(std::distance(e,outvert.end()));
- outvert.erase(e,outvert.end());
- }
- if (fz(*( outvert.end()-newcount),outvert.back())) {
- outvert.pop_back();
- --newcount;
- }
- if(newcount > 2) {
- result.vertcnt.push_back(newcount);
- }
- else while(newcount-->0) {
- result.verts.pop_back();
- }
-
- }
- IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
+ ai_assert(hs != NULL);
+
+ const IfcPlane* const plane = hs->BaseSurface->ToPtr<IfcPlane>();
+ if(!plane) {
+ IFCImporter::LogError("expected IfcPlane as base surface for the IfcHalfSpaceSolid");
+ return;
+ }
+
+ // extract plane base position vector and normal vector
+ IfcVector3 p,n(0.f,0.f,1.f);
+ if (plane->Position->Axis) {
+ ConvertDirection(n,plane->Position->Axis.Get());
+ }
+ ConvertCartesianPoint(p,plane->Position->Location);
+
+ if(!IsTrue(hs->AgreementFlag)) {
+ n *= -1.f;
+ }
+
+ n.Normalize();
+
+ // obtain the polygonal bounding volume
+ std::shared_ptr<TempMesh> profile = std::shared_ptr<TempMesh>(new TempMesh());
+ if(!ProcessCurve(hs->PolygonalBoundary, *profile.get(), conv)) {
+ IFCImporter::LogError("expected valid polyline for boundary of boolean halfspace");
+ return;
+ }
+
+ // determine winding order by calculating the normal.
+ IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(profile->verts.data(), profile->verts.size());
+
+ IfcMatrix4 proj_inv;
+ ConvertAxisPlacement(proj_inv,hs->Position);
+
+ // and map everything into a plane coordinate space so all intersection
+ // tests can be done in 2D space.
+ IfcMatrix4 proj = proj_inv;
+ proj.Inverse();
+
+ // clip the current contents of `meshout` against the plane we obtained from the second operand
+ const std::vector<IfcVector3>& in = first_operand.verts;
+ std::vector<IfcVector3>& outvert = result.verts;
+ std::vector<unsigned int>& outvertcnt = result.vertcnt;
+
+ outvert.reserve(in.size());
+ outvertcnt.reserve(first_operand.vertcnt.size());
+
+ unsigned int vidx = 0;
+ std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin();
+ std::vector<unsigned int>::const_iterator end = first_operand.vertcnt.end();
+ std::vector<unsigned int>::const_iterator iit;
+ for( iit = begin; iit != end; vidx += *iit++ )
+ {
+ // Our new approach: we cut the poly along the plane, then we intersect the part on the black side of the plane
+ // against the bounding polygon. All the white parts, and the black part outside the boundary polygon, are kept.
+ std::vector<IfcVector3> whiteside, blackside;
+
+ {
+ const IfcVector3* srcVertices = &in[vidx];
+ const size_t srcVtxCount = *iit;
+ if( srcVtxCount == 0 )
+ continue;
+
+ IfcVector3 polyNormal = TempMesh::ComputePolygonNormal(srcVertices, srcVtxCount, true);
+
+ // if the poly is parallel to the plane, put it completely on the black or white side
+ if( std::abs(polyNormal * n) > 0.9999 )
+ {
+ bool isOnWhiteSide = (srcVertices[0] - p) * n > -1e-6;
+ std::vector<IfcVector3>& targetSide = isOnWhiteSide ? whiteside : blackside;
+ targetSide.insert(targetSide.end(), srcVertices, srcVertices + srcVtxCount);
+ }
+ else
+ {
+ // otherwise start building one polygon for each side. Whenever the current line segment intersects the plane
+ // we put a point there as an end of the current segment. Then we switch to the other side, put a point there, too,
+ // as a beginning of the current segment, and simply continue accumulating vertices.
+ bool isCurrentlyOnWhiteSide = ((srcVertices[0]) - p) * n > -1e-6;
+ for( size_t a = 0; a < srcVtxCount; ++a )
+ {
+ IfcVector3 e0 = srcVertices[a];
+ IfcVector3 e1 = srcVertices[(a + 1) % srcVtxCount];
+ IfcVector3 ei;
+
+ // put starting point to the current mesh
+ std::vector<IfcVector3>& trgt = isCurrentlyOnWhiteSide ? whiteside : blackside;
+ trgt.push_back(srcVertices[a]);
+
+ // if there's an intersection, put an end vertex there, switch to the other side's mesh,
+ // and add a starting vertex there, too
+ bool isPlaneHit = IntersectSegmentPlane(p, n, e0, e1, isCurrentlyOnWhiteSide, ei);
+ if( isPlaneHit )
+ {
+ if( trgt.empty() || (trgt.back() - ei).SquareLength() > 1e-12 )
+ trgt.push_back(ei);
+ isCurrentlyOnWhiteSide = !isCurrentlyOnWhiteSide;
+ std::vector<IfcVector3>& newtrgt = isCurrentlyOnWhiteSide ? whiteside : blackside;
+ newtrgt.push_back(ei);
+ }
+ }
+ }
+ }
+
+ // the part on the white side can be written into the target mesh right away
+ WritePolygon(whiteside, result);
+
+ // The black part is the piece we need to get rid of, but only the part of it within the boundary polygon.
+ // So we now need to construct all the polygons that result from BlackSidePoly minus BoundaryPoly.
+ FilterPolygon(blackside);
+
+ // Complicated, II. We run along the polygon. a) When we're inside the boundary, we run on until we hit an
+ // intersection, which means we're leaving it. We then start a new out poly there. b) When we're outside the
+ // boundary, we start collecting vertices until we hit an intersection, then we run along the boundary until we hit
+ // an intersection, then we switch back to the poly and run on on this one again, and so on until we got a closed
+ // loop. Then we continue with the path we left to catch potential additional polys on the other side of the
+ // boundary as described in a)
+ if( !blackside.empty() )
+ {
+ // poly edge index, intersection point, edge index in boundary poly
+ std::vector<std::tuple<size_t, IfcVector3, size_t> > intersections;
+ bool startedInside = PointInPoly(proj * blackside.front(), profile->verts);
+ bool isCurrentlyInside = startedInside;
+
+ std::vector<std::pair<size_t, IfcVector3> > intersected_boundary;
+
+ for( size_t a = 0; a < blackside.size(); ++a )
+ {
+ const IfcVector3 e0 = proj * blackside[a];
+ const IfcVector3 e1 = proj * blackside[(a + 1) % blackside.size()];
+
+ intersected_boundary.clear();
+ IntersectsBoundaryProfile(e0, e1, profile->verts, isCurrentlyInside, intersected_boundary);
+ // sort the hits by distance from e0 to get the correct in/out/in sequence. Manually :-( I miss you, C++11.
+ if( intersected_boundary.size() > 1 )
+ {
+ bool keepSorting = true;
+ while( keepSorting )
+ {
+ keepSorting = false;
+ for( size_t b = 0; b < intersected_boundary.size() - 1; ++b )
+ {
+ if( (intersected_boundary[b + 1].second - e0).SquareLength() < (intersected_boundary[b].second - e0).SquareLength() )
+ {
+ keepSorting = true;
+ std::swap(intersected_boundary[b + 1], intersected_boundary[b]);
+ }
+ }
+ }
+ }
+ // now add them to the list of intersections
+ for( size_t b = 0; b < intersected_boundary.size(); ++b )
+ intersections.push_back(std::make_tuple(a, proj_inv * intersected_boundary[b].second, intersected_boundary[b].first));
+
+ // and calculate our new inside/outside state
+ if( intersected_boundary.size() & 1 )
+ isCurrentlyInside = !isCurrentlyInside;
+ }
+
+ // we got a list of in-out-combinations of intersections. That should be an even number of intersections, or
+ // we're fucked.
+ if( (intersections.size() & 1) != 0 )
+ {
+ IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
+ continue;
+ }
+
+ if( intersections.size() > 1 )
+ {
+ // If we started outside, the first intersection is a out->in intersection. Cycle them so that it
+ // starts with an intersection leaving the boundary
+ if( !startedInside )
+ for( size_t b = 0; b < intersections.size() - 1; ++b )
+ std::swap(intersections[b], intersections[(b + intersections.size() - 1) % intersections.size()]);
+
+ // Filter pairs of out->in->out that lie too close to each other.
+ for( size_t a = 0; intersections.size() > 0 && a < intersections.size() - 1; /**/ )
+ {
+ if( (std::get<1>(intersections[a]) - std::get<1>(intersections[(a + 1) % intersections.size()])).SquareLength() < 1e-10 )
+ intersections.erase(intersections.begin() + a, intersections.begin() + a + 2);
+ else
+ a++;
+ }
+ if( intersections.size() > 1 && (std::get<1>(intersections.back()) - std::get<1>(intersections.front())).SquareLength() < 1e-10 )
+ {
+ intersections.pop_back(); intersections.erase(intersections.begin());
+ }
+ }
+
+
+ // no intersections at all: either completely inside the boundary, so everything gets discarded, or completely outside.
+ // in the latter case we're implementional lost. I'm simply going to ignore this, so a large poly will not get any
+ // holes if the boundary is smaller and does not touch it anywhere.
+ if( intersections.empty() )
+ {
+ // starting point was outside -> everything is outside the boundary -> nothing is clipped -> add black side
+ // to result mesh unchanged
+ if( !startedInside )
+ {
+ outvertcnt.push_back(blackside.size());
+ outvert.insert(outvert.end(), blackside.begin(), blackside.end());
+ continue;
+ }
+ else
+ {
+ // starting point was inside the boundary -> everything is inside the boundary -> nothing is spared from the
+ // clipping -> nothing left to add to the result mesh
+ continue;
+ }
+ }
+
+ // determine the direction in which we're marching along the boundary polygon. If the src poly is faced upwards
+ // and the boundary is also winded this way, we need to march *backwards* on the boundary.
+ const IfcVector3 polyNormal = IfcMatrix3(proj) * TempMesh::ComputePolygonNormal(blackside.data(), blackside.size());
+ bool marchBackwardsOnBoundary = (profileNormal * polyNormal) >= 0.0;
+
+ // Build closed loops from these intersections. Starting from an intersection leaving the boundary we
+ // walk along the polygon to the next intersection (which should be an IS entering the boundary poly).
+ // From there we walk along the boundary until we hit another intersection leaving the boundary,
+ // walk along the poly to the next IS and so on until we're back at the starting point.
+ // We remove every intersection we "used up", so any remaining intersection is the start of a new loop.
+ while( !intersections.empty() )
+ {
+ std::vector<IfcVector3> resultpoly;
+ size_t currentIntersecIdx = 0;
+
+ while( true )
+ {
+ ai_assert(intersections.size() > currentIntersecIdx + 1);
+ std::tuple<size_t, IfcVector3, size_t> currintsec = intersections[currentIntersecIdx + 0];
+ std::tuple<size_t, IfcVector3, size_t> nextintsec = intersections[currentIntersecIdx + 1];
+ intersections.erase(intersections.begin() + currentIntersecIdx, intersections.begin() + currentIntersecIdx + 2);
+
+ // we start with an in->out intersection
+ resultpoly.push_back(std::get<1>(currintsec));
+ // climb along the polygon to the next intersection, which should be an out->in
+ size_t numPolyPoints = (std::get<0>(currintsec) > std::get<0>(nextintsec) ? blackside.size() : 0)
+ + std::get<0>(nextintsec) - std::get<0>(currintsec);
+ for( size_t a = 1; a <= numPolyPoints; ++a )
+ resultpoly.push_back(blackside[(std::get<0>(currintsec) + a) % blackside.size()]);
+ // put the out->in intersection
+ resultpoly.push_back(std::get<1>(nextintsec));
+
+ // generate segments along the boundary polygon that lie in the poly's plane until we hit another intersection
+ IfcVector3 startingPoint = proj * std::get<1>(nextintsec);
+ size_t currentBoundaryEdgeIdx = (std::get<2>(nextintsec) + (marchBackwardsOnBoundary ? 1 : 0)) % profile->verts.size();
+ size_t nextIntsecIdx = SIZE_MAX;
+ while( nextIntsecIdx == SIZE_MAX )
+ {
+ IfcFloat t = 1e10;
+
+ size_t nextBoundaryEdgeIdx = marchBackwardsOnBoundary ? (currentBoundaryEdgeIdx + profile->verts.size() - 1) : currentBoundaryEdgeIdx + 1;
+ nextBoundaryEdgeIdx %= profile->verts.size();
+ // vertices of the current boundary segments
+ IfcVector3 currBoundaryPoint = profile->verts[currentBoundaryEdgeIdx];
+ IfcVector3 nextBoundaryPoint = profile->verts[nextBoundaryEdgeIdx];
+ // project the two onto the polygon
+ if( std::abs(polyNormal.z) > 1e-5 )
+ {
+ currBoundaryPoint.z = startingPoint.z + (currBoundaryPoint.x - startingPoint.x) * polyNormal.x/polyNormal.z + (currBoundaryPoint.y - startingPoint.y) * polyNormal.y/polyNormal.z;
+ nextBoundaryPoint.z = startingPoint.z + (nextBoundaryPoint.x - startingPoint.x) * polyNormal.x/polyNormal.z + (nextBoundaryPoint.y - startingPoint.y) * polyNormal.y/polyNormal.z;
+ }
+
+ // build a direction that goes along the boundary border but lies in the poly plane
+ IfcVector3 boundaryPlaneNormal = ((nextBoundaryPoint - currBoundaryPoint) ^ profileNormal).Normalize();
+ IfcVector3 dirAtPolyPlane = (boundaryPlaneNormal ^ polyNormal).Normalize() * (marchBackwardsOnBoundary ? -1.0 : 1.0);
+ // if we can project the direction to the plane, we can calculate a maximum marching distance along that dir
+ // until we finish that boundary segment and continue on the next
+ if( std::abs(polyNormal.z) > 1e-5 )
+ {
+ t = std::min(t, (nextBoundaryPoint - startingPoint).Length());
+ }
+
+ // check if the direction hits the loop start - if yes, we got a poly to output
+ IfcVector3 dirToThatPoint = proj * resultpoly.front() - startingPoint;
+ IfcFloat tpt = dirToThatPoint * dirAtPolyPlane;
+ if( tpt > -1e-6 && tpt <= t && (dirToThatPoint - tpt * dirAtPolyPlane).SquareLength() < 1e-10 )
+ {
+ nextIntsecIdx = intersections.size(); // dirty hack to end marching along the boundary and signal the end of the loop
+ t = tpt;
+ }
+
+ // also check if the direction hits any in->out intersections earlier. If we hit one, we can switch back
+ // to marching along the poly border from that intersection point
+ for( size_t a = 0; a < intersections.size(); a += 2 )
+ {
+ dirToThatPoint = proj * std::get<1>(intersections[a]) - startingPoint;
+ tpt = dirToThatPoint * dirAtPolyPlane;
+ if( tpt > -1e-6 && tpt <= t && (dirToThatPoint - tpt * dirAtPolyPlane).SquareLength() < 1e-10 )
+ {
+ nextIntsecIdx = a; // switch back to poly and march on from this in->out intersection
+ t = tpt;
+ }
+ }
+
+ // if we keep marching on the boundary, put the segment end point to the result poly and well... keep marching
+ if( nextIntsecIdx == SIZE_MAX )
+ {
+ resultpoly.push_back(proj_inv * nextBoundaryPoint);
+ currentBoundaryEdgeIdx = nextBoundaryEdgeIdx;
+ startingPoint = nextBoundaryPoint;
+ }
+
+ // quick endless loop check
+ if( resultpoly.size() > blackside.size() + profile->verts.size() )
+ {
+ IFCImporter::LogError("Encountered endless loop while clipping polygon against poly-bounded half space.");
+ break;
+ }
+ }
+
+ // we're back on the poly - if this is the intersection we started from, we got a closed loop.
+ if( nextIntsecIdx >= intersections.size() )
+ {
+ break;
+ }
+
+ // otherwise it's another intersection. Continue marching from there.
+ currentIntersecIdx = nextIntsecIdx;
+ }
+
+ WritePolygon(resultpoly, result);
+ }
+ }
+ }
+ IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
}
// ------------------------------------------------------------------------------------------------
-void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv)
+void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& conv)
{
- ai_assert(as != NULL);
+ ai_assert(as != NULL);
- // This case is handled by reduction to an instance of the quadrify() algorithm.
- // Obviously, this won't work for arbitrarily complex cases. In fact, the first
- // operand should be near-planar. Luckily, this is usually the case in Ifc
- // buildings.
+ // This case is handled by reduction to an instance of the quadrify() algorithm.
+ // Obviously, this won't work for arbitrarily complex cases. In fact, the first
+ // operand should be near-planar. Luckily, this is usually the case in Ifc
+ // buildings.
- boost::shared_ptr<TempMesh> meshtmp = boost::shared_ptr<TempMesh>(new TempMesh());
- ProcessExtrudedAreaSolid(*as,*meshtmp,conv,false);
+ std::shared_ptr<TempMesh> meshtmp = std::shared_ptr<TempMesh>(new TempMesh());
+ ProcessExtrudedAreaSolid(*as,*meshtmp,conv,false);
- std::vector<TempOpening> openings(1, TempOpening(as,IfcVector3(0,0,0),meshtmp,boost::shared_ptr<TempMesh>()));
+ std::vector<TempOpening> openings(1, TempOpening(as,IfcVector3(0,0,0),meshtmp,std::shared_ptr<TempMesh>()));
- result = first_operand;
+ result = first_operand;
- TempMesh temp;
+ TempMesh temp;
- std::vector<IfcVector3>::const_iterator vit = first_operand.verts.begin();
- BOOST_FOREACH(unsigned int pcount, first_operand.vertcnt) {
- temp.Clear();
+ std::vector<IfcVector3>::const_iterator vit = first_operand.verts.begin();
+ for(unsigned int pcount : first_operand.vertcnt) {
+ temp.Clear();
- temp.verts.insert(temp.verts.end(), vit, vit + pcount);
- temp.vertcnt.push_back(pcount);
+ temp.verts.insert(temp.verts.end(), vit, vit + pcount);
+ temp.vertcnt.push_back(pcount);
- // The algorithms used to generate mesh geometry sometimes
- // spit out lines or other degenerates which must be
- // filtered to avoid running into assertions later on.
+ // The algorithms used to generate mesh geometry sometimes
+ // spit out lines or other degenerates which must be
+ // filtered to avoid running into assertions later on.
- // ComputePolygonNormal returns the Newell normal, so the
- // length of the normal is the area of the polygon.
- const IfcVector3& normal = temp.ComputeLastPolygonNormal(false);
- if (normal.SquareLength() < static_cast<IfcFloat>(1e-5)) {
- IFCImporter::LogWarn("skipping degenerate polygon (ProcessBooleanExtrudedAreaSolidDifference)");
- continue;
- }
+ // ComputePolygonNormal returns the Newell normal, so the
+ // length of the normal is the area of the polygon.
+ const IfcVector3& normal = temp.ComputeLastPolygonNormal(false);
+ if (normal.SquareLength() < static_cast<IfcFloat>(1e-5)) {
+ IFCImporter::LogWarn("skipping degenerate polygon (ProcessBooleanExtrudedAreaSolidDifference)");
+ continue;
+ }
- GenerateOpenings(openings, std::vector<IfcVector3>(1,IfcVector3(1,0,0)), temp, false, true);
- result.Append(temp);
+ GenerateOpenings(openings, std::vector<IfcVector3>(1,IfcVector3(1,0,0)), temp, false, true);
+ result.Append(temp);
- vit += pcount;
- }
+ vit += pcount;
+ }
- IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
+ IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
}
// ------------------------------------------------------------------------------------------------
void ProcessBoolean(const IfcBooleanResult& boolean, TempMesh& result, ConversionData& conv)
{
- // supported CSG operations:
- // DIFFERENCE
- if(const IfcBooleanResult* const clip = boolean.ToPtr<IfcBooleanResult>()) {
- if(clip->Operator != "DIFFERENCE") {
- IFCImporter::LogWarn("encountered unsupported boolean operator: " + (std::string)clip->Operator);
- return;
- }
-
- // supported cases (1st operand):
- // IfcBooleanResult -- call ProcessBoolean recursively
- // IfcSweptAreaSolid -- obtain polygonal geometry first
-
- // supported cases (2nd operand):
- // IfcHalfSpaceSolid -- easy, clip against plane
- // IfcExtrudedAreaSolid -- reduce to an instance of the quadrify() algorithm
-
-
- const IfcHalfSpaceSolid* const hs = clip->SecondOperand->ResolveSelectPtr<IfcHalfSpaceSolid>(conv.db);
- const IfcExtrudedAreaSolid* const as = clip->SecondOperand->ResolveSelectPtr<IfcExtrudedAreaSolid>(conv.db);
- if(!hs && !as) {
- IFCImporter::LogError("expected IfcHalfSpaceSolid or IfcExtrudedAreaSolid as second clipping operand");
- return;
- }
-
- TempMesh first_operand;
- if(const IfcBooleanResult* const op0 = clip->FirstOperand->ResolveSelectPtr<IfcBooleanResult>(conv.db)) {
- ProcessBoolean(*op0,first_operand,conv);
- }
- else if (const IfcSweptAreaSolid* const swept = clip->FirstOperand->ResolveSelectPtr<IfcSweptAreaSolid>(conv.db)) {
- ProcessSweptAreaSolid(*swept,first_operand,conv);
- }
- else {
- IFCImporter::LogError("expected IfcSweptAreaSolid or IfcBooleanResult as first clipping operand");
- return;
- }
-
- if(hs) {
-
- const IfcPolygonalBoundedHalfSpace* const hs_bounded = clip->SecondOperand->ResolveSelectPtr<IfcPolygonalBoundedHalfSpace>(conv.db);
- if (hs_bounded) {
- ProcessPolygonalBoundedBooleanHalfSpaceDifference(hs_bounded, result, first_operand, conv);
- }
- else {
- ProcessBooleanHalfSpaceDifference(hs, result, first_operand, conv);
- }
- }
- else {
- ProcessBooleanExtrudedAreaSolidDifference(as, result, first_operand, conv);
- }
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is " + boolean.GetClassName());
- }
+ // supported CSG operations:
+ // DIFFERENCE
+ if(const IfcBooleanResult* const clip = boolean.ToPtr<IfcBooleanResult>()) {
+ if(clip->Operator != "DIFFERENCE") {
+ IFCImporter::LogWarn("encountered unsupported boolean operator: " + (std::string)clip->Operator);
+ return;
+ }
+
+ // supported cases (1st operand):
+ // IfcBooleanResult -- call ProcessBoolean recursively
+ // IfcSweptAreaSolid -- obtain polygonal geometry first
+
+ // supported cases (2nd operand):
+ // IfcHalfSpaceSolid -- easy, clip against plane
+ // IfcExtrudedAreaSolid -- reduce to an instance of the quadrify() algorithm
+
+
+ const IfcHalfSpaceSolid* const hs = clip->SecondOperand->ResolveSelectPtr<IfcHalfSpaceSolid>(conv.db);
+ const IfcExtrudedAreaSolid* const as = clip->SecondOperand->ResolveSelectPtr<IfcExtrudedAreaSolid>(conv.db);
+ if(!hs && !as) {
+ IFCImporter::LogError("expected IfcHalfSpaceSolid or IfcExtrudedAreaSolid as second clipping operand");
+ return;
+ }
+
+ TempMesh first_operand;
+ if(const IfcBooleanResult* const op0 = clip->FirstOperand->ResolveSelectPtr<IfcBooleanResult>(conv.db)) {
+ ProcessBoolean(*op0,first_operand,conv);
+ }
+ else if (const IfcSweptAreaSolid* const swept = clip->FirstOperand->ResolveSelectPtr<IfcSweptAreaSolid>(conv.db)) {
+ ProcessSweptAreaSolid(*swept,first_operand,conv);
+ }
+ else {
+ IFCImporter::LogError("expected IfcSweptAreaSolid or IfcBooleanResult as first clipping operand");
+ return;
+ }
+
+ if(hs) {
+
+ const IfcPolygonalBoundedHalfSpace* const hs_bounded = clip->SecondOperand->ResolveSelectPtr<IfcPolygonalBoundedHalfSpace>(conv.db);
+ if (hs_bounded) {
+ ProcessPolygonalBoundedBooleanHalfSpaceDifference(hs_bounded, result, first_operand, conv);
+ }
+ else {
+ ProcessBooleanHalfSpaceDifference(hs, result, first_operand, conv);
+ }
+ }
+ else {
+ ProcessBooleanExtrudedAreaSolidDifference(as, result, first_operand, conv);
+ }
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is " + boolean.GetClassName());
+ }
}
} // ! IFC
} // ! Assimp
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/IFCCurve.cpp b/src/3rdparty/assimp/code/IFCCurve.cpp
index 1079c1e2b..97d9fd574 100644
--- a/src/3rdparty/assimp/code/IFCCurve.cpp
+++ b/src/3rdparty/assimp/code/IFCCurve.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,14 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Read profile and curves entities from IFC files
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
namespace Assimp {
- namespace IFC {
- namespace {
+ namespace IFC {
+ namespace {
// --------------------------------------------------------------------------------
@@ -60,47 +60,47 @@ class Conic : public Curve
public:
- // --------------------------------------------------
- Conic(const IfcConic& entity, ConversionData& conv)
- : Curve(entity,conv)
- {
- IfcMatrix4 trafo;
- ConvertAxisPlacement(trafo,*entity.Position,conv);
+ // --------------------------------------------------
+ Conic(const IfcConic& entity, ConversionData& conv)
+ : Curve(entity,conv)
+ {
+ IfcMatrix4 trafo;
+ ConvertAxisPlacement(trafo,*entity.Position,conv);
- // for convenience, extract the matrix rows
- location = IfcVector3(trafo.a4,trafo.b4,trafo.c4);
- p[0] = IfcVector3(trafo.a1,trafo.b1,trafo.c1);
- p[1] = IfcVector3(trafo.a2,trafo.b2,trafo.c2);
- p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
- }
+ // for convenience, extract the matrix rows
+ location = IfcVector3(trafo.a4,trafo.b4,trafo.c4);
+ p[0] = IfcVector3(trafo.a1,trafo.b1,trafo.c1);
+ p[1] = IfcVector3(trafo.a2,trafo.b2,trafo.c2);
+ p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3);
+ }
public:
- // --------------------------------------------------
- bool IsClosed() const {
- return true;
- }
-
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ // --------------------------------------------------
+ bool IsClosed() const {
+ return true;
+ }
+
+ // --------------------------------------------------
+ size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
- a *= conv.angle_scale;
- b *= conv.angle_scale;
+ a *= conv.angle_scale;
+ b *= conv.angle_scale;
a = std::fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
b = std::fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
- const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 );
+ const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 );
return static_cast<size_t>( std::ceil(std::abs( b-a)) / setting);
- }
+ }
- // --------------------------------------------------
- ParamRange GetParametricRange() const {
- return std::make_pair(static_cast<IfcFloat>( 0. ), static_cast<IfcFloat>( AI_MATH_TWO_PI / conv.angle_scale ));
- }
+ // --------------------------------------------------
+ ParamRange GetParametricRange() const {
+ return std::make_pair(static_cast<IfcFloat>( 0. ), static_cast<IfcFloat>( AI_MATH_TWO_PI / conv.angle_scale ));
+ }
protected:
- IfcVector3 location, p[3];
+ IfcVector3 location, p[3];
};
@@ -112,24 +112,24 @@ class Circle : public Conic
public:
- // --------------------------------------------------
- Circle(const IfcCircle& entity, ConversionData& conv)
- : Conic(entity,conv)
- , entity(entity)
- {
- }
+ // --------------------------------------------------
+ Circle(const IfcCircle& entity, ConversionData& conv)
+ : Conic(entity,conv)
+ , entity(entity)
+ {
+ }
public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- u = -conv.angle_scale * u;
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat u) const {
+ u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(std::sin(u))*p[1]);
- }
+ }
private:
- const IfcCircle& entity;
+ const IfcCircle& entity;
};
@@ -141,374 +141,364 @@ class Ellipse : public Conic
public:
- // --------------------------------------------------
- Ellipse(const IfcEllipse& entity, ConversionData& conv)
- : Conic(entity,conv)
- , entity(entity)
- {
- }
+ // --------------------------------------------------
+ Ellipse(const IfcEllipse& entity, ConversionData& conv)
+ : Conic(entity,conv)
+ , entity(entity)
+ {
+ }
public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- u = -conv.angle_scale * u;
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat u) const {
+ u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
- }
+ }
private:
- const IfcEllipse& entity;
+ const IfcEllipse& entity;
};
// --------------------------------------------------------------------------------
// Line
// --------------------------------------------------------------------------------
-class Line : public Curve
+class Line : public Curve
{
public:
- // --------------------------------------------------
- Line(const IfcLine& entity, ConversionData& conv)
- : Curve(entity,conv)
- , entity(entity)
- {
- ConvertCartesianPoint(p,entity.Pnt);
- ConvertVector(v,entity.Dir);
- }
+ // --------------------------------------------------
+ Line(const IfcLine& entity, ConversionData& conv)
+ : Curve(entity,conv)
+ {
+ ConvertCartesianPoint(p,entity.Pnt);
+ ConvertVector(v,entity.Dir);
+ }
public:
- // --------------------------------------------------
- bool IsClosed() const {
- return false;
- }
-
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- return p + u*v;
- }
-
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
- // two points are always sufficient for a line segment
- return a==b ? 1 : 2;
- }
-
-
- // --------------------------------------------------
- void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
- {
- ai_assert(InRange(a) && InRange(b));
-
- if (a == b) {
- out.verts.push_back(Eval(a));
- return;
- }
- out.verts.reserve(out.verts.size()+2);
- out.verts.push_back(Eval(a));
- out.verts.push_back(Eval(b));
- }
-
- // --------------------------------------------------
- ParamRange GetParametricRange() const {
- const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
-
- return std::make_pair(-inf,+inf);
- }
+ // --------------------------------------------------
+ bool IsClosed() const {
+ return false;
+ }
+
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat u) const {
+ return p + u*v;
+ }
+
+ // --------------------------------------------------
+ size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
+ // two points are always sufficient for a line segment
+ return a==b ? 1 : 2;
+ }
+
+
+ // --------------------------------------------------
+ void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
+ {
+ ai_assert(InRange(a) && InRange(b));
+
+ if (a == b) {
+ out.verts.push_back(Eval(a));
+ return;
+ }
+ out.verts.reserve(out.verts.size()+2);
+ out.verts.push_back(Eval(a));
+ out.verts.push_back(Eval(b));
+ }
+
+ // --------------------------------------------------
+ ParamRange GetParametricRange() const {
+ const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
+
+ return std::make_pair(-inf,+inf);
+ }
private:
- const IfcLine& entity;
- IfcVector3 p,v;
+ IfcVector3 p,v;
};
// --------------------------------------------------------------------------------
// CompositeCurve joins multiple smaller, bounded curves
// --------------------------------------------------------------------------------
-class CompositeCurve : public BoundedCurve
+class CompositeCurve : public BoundedCurve
{
- typedef std::pair< boost::shared_ptr< BoundedCurve >, bool > CurveEntry;
+ typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry;
public:
- // --------------------------------------------------
- CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
- : BoundedCurve(entity,conv)
- , entity(entity)
- , total()
- {
- curves.reserve(entity.Segments.size());
- BOOST_FOREACH(const IfcCompositeCurveSegment& curveSegment,entity.Segments) {
- // according to the specification, this must be a bounded curve
- boost::shared_ptr< Curve > cv(Curve::Convert(curveSegment.ParentCurve,conv));
- boost::shared_ptr< BoundedCurve > bc = boost::dynamic_pointer_cast<BoundedCurve>(cv);
-
- if (!bc) {
- IFCImporter::LogError("expected segment of composite curve to be a bounded curve");
- continue;
- }
-
- if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
- IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
- }
-
- curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
- total += bc->GetParametricRangeDelta();
- }
-
- if (curves.empty()) {
- throw CurveError("empty composite curve");
- }
- }
+ // --------------------------------------------------
+ CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv)
+ : BoundedCurve(entity,conv)
+ , total()
+ {
+ curves.reserve(entity.Segments.size());
+ for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) {
+ // according to the specification, this must be a bounded curve
+ std::shared_ptr< Curve > cv(Curve::Convert(curveSegment.ParentCurve,conv));
+ std::shared_ptr< BoundedCurve > bc = std::dynamic_pointer_cast<BoundedCurve>(cv);
+
+ if (!bc) {
+ IFCImporter::LogError("expected segment of composite curve to be a bounded curve");
+ continue;
+ }
+
+ if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
+ IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
+ }
+
+ curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
+ total += bc->GetParametricRangeDelta();
+ }
+
+ if (curves.empty()) {
+ throw CurveError("empty composite curve");
+ }
+ }
public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat u) const {
- if (curves.empty()) {
- return IfcVector3();
- }
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat u) const {
+ if (curves.empty()) {
+ return IfcVector3();
+ }
- IfcFloat acc = 0;
- BOOST_FOREACH(const CurveEntry& entry, curves) {
- const ParamRange& range = entry.first->GetParametricRange();
+ IfcFloat acc = 0;
+ for(const CurveEntry& entry : curves) {
+ const ParamRange& range = entry.first->GetParametricRange();
const IfcFloat delta = std::abs(range.second-range.first);
- if (u < acc+delta) {
- return entry.first->Eval( entry.second ? (u-acc) + range.first : range.second-(u-acc));
- }
-
- acc += delta;
- }
- // clamp to end
- return curves.back().first->Eval(curves.back().first->GetParametricRange().second);
- }
-
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
- size_t cnt = 0;
-
- IfcFloat acc = 0;
- BOOST_FOREACH(const CurveEntry& entry, curves) {
- const ParamRange& range = entry.first->GetParametricRange();
+ if (u < acc+delta) {
+ return entry.first->Eval( entry.second ? (u-acc) + range.first : range.second-(u-acc));
+ }
+
+ acc += delta;
+ }
+ // clamp to end
+ return curves.back().first->Eval(curves.back().first->GetParametricRange().second);
+ }
+
+ // --------------------------------------------------
+ size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
+ size_t cnt = 0;
+
+ IfcFloat acc = 0;
+ for(const CurveEntry& entry : curves) {
+ const ParamRange& range = entry.first->GetParametricRange();
const IfcFloat delta = std::abs(range.second-range.first);
- if (a <= acc+delta && b >= acc) {
- const IfcFloat at = std::max(static_cast<IfcFloat>( 0. ),a-acc), bt = std::min(delta,b-acc);
- cnt += entry.first->EstimateSampleCount( entry.second ? at + range.first : range.second - bt, entry.second ? bt + range.first : range.second - at );
- }
+ if (a <= acc+delta && b >= acc) {
+ const IfcFloat at = std::max(static_cast<IfcFloat>( 0. ),a-acc), bt = std::min(delta,b-acc);
+ cnt += entry.first->EstimateSampleCount( entry.second ? at + range.first : range.second - bt, entry.second ? bt + range.first : range.second - at );
+ }
- acc += delta;
- }
+ acc += delta;
+ }
- return cnt;
- }
+ return cnt;
+ }
- // --------------------------------------------------
- void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
- {
- ai_assert(InRange(a) && InRange(b));
+ // --------------------------------------------------
+ void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
+ {
+ ai_assert(InRange(a) && InRange(b));
- const size_t cnt = EstimateSampleCount(a,b);
- out.verts.reserve(out.verts.size() + cnt);
+ const size_t cnt = EstimateSampleCount(a,b);
+ out.verts.reserve(out.verts.size() + cnt);
- BOOST_FOREACH(const CurveEntry& entry, curves) {
- const size_t cnt = out.verts.size();
- entry.first->SampleDiscrete(out);
+ for(const CurveEntry& entry : curves) {
+ const size_t cnt = out.verts.size();
+ entry.first->SampleDiscrete(out);
- if (!entry.second && cnt != out.verts.size()) {
- std::reverse(out.verts.begin()+cnt,out.verts.end());
- }
- }
- }
+ if (!entry.second && cnt != out.verts.size()) {
+ std::reverse(out.verts.begin()+cnt,out.verts.end());
+ }
+ }
+ }
- // --------------------------------------------------
- ParamRange GetParametricRange() const {
- return std::make_pair(static_cast<IfcFloat>( 0. ),total);
- }
+ // --------------------------------------------------
+ ParamRange GetParametricRange() const {
+ return std::make_pair(static_cast<IfcFloat>( 0. ),total);
+ }
private:
- const IfcCompositeCurve& entity;
- std::vector< CurveEntry > curves;
+ std::vector< CurveEntry > curves;
- IfcFloat total;
+ IfcFloat total;
};
// --------------------------------------------------------------------------------
// TrimmedCurve can be used to trim an unbounded curve to a bounded range
// --------------------------------------------------------------------------------
-class TrimmedCurve : public BoundedCurve
+class TrimmedCurve : public BoundedCurve
{
public:
- // --------------------------------------------------
- TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
- : BoundedCurve(entity,conv)
- , entity(entity)
- , ok()
- {
- base = boost::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));
-
- typedef boost::shared_ptr<const STEP::EXPRESS::DataType> Entry;
-
- // for some reason, trimmed curves can either specify a parametric value
- // or a point on the curve, or both. And they can even specify which of the
- // two representations they prefer, even though an information invariant
- // claims that they must be identical if both are present.
- // oh well.
- bool have_param = false, have_point = false;
- IfcVector3 point;
- BOOST_FOREACH(const Entry sel,entity.Trim1) {
- if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
- range.first = *r;
- have_param = true;
- break;
- }
- else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
- ConvertCartesianPoint(point,*r);
- have_point = true;
- }
- }
- if (!have_param) {
- if (!have_point || !base->ReverseEval(point,range.first)) {
- throw CurveError("IfcTrimmedCurve: failed to read first trim parameter, ignoring curve");
- }
- }
- have_param = false, have_point = false;
- BOOST_FOREACH(const Entry sel,entity.Trim2) {
- if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
- range.second = *r;
- have_param = true;
- break;
- }
- else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
- ConvertCartesianPoint(point,*r);
- have_point = true;
- }
- }
- if (!have_param) {
- if (!have_point || !base->ReverseEval(point,range.second)) {
- throw CurveError("IfcTrimmedCurve: failed to read second trim parameter, ignoring curve");
- }
- }
-
- agree_sense = IsTrue(entity.SenseAgreement);
- if( !agree_sense ) {
- std::swap(range.first,range.second);
- }
-
- // "NOTE In case of a closed curve, it may be necessary to increment t1 or t2
- // by the parametric length for consistency with the sense flag."
- if (base->IsClosed()) {
- if( range.first > range.second ) {
- range.second += base->GetParametricRangeDelta();
- }
- }
-
- maxval = range.second-range.first;
- ai_assert(maxval >= 0);
- }
+ // --------------------------------------------------
+ TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv)
+ : BoundedCurve(entity,conv)
+ {
+ base = std::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));
+
+ typedef std::shared_ptr<const STEP::EXPRESS::DataType> Entry;
+
+ // for some reason, trimmed curves can either specify a parametric value
+ // or a point on the curve, or both. And they can even specify which of the
+ // two representations they prefer, even though an information invariant
+ // claims that they must be identical if both are present.
+ // oh well.
+ bool have_param = false, have_point = false;
+ IfcVector3 point;
+ for(const Entry sel :entity.Trim1) {
+ if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
+ range.first = *r;
+ have_param = true;
+ break;
+ }
+ else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
+ ConvertCartesianPoint(point,*r);
+ have_point = true;
+ }
+ }
+ if (!have_param) {
+ if (!have_point || !base->ReverseEval(point,range.first)) {
+ throw CurveError("IfcTrimmedCurve: failed to read first trim parameter, ignoring curve");
+ }
+ }
+ have_param = false, have_point = false;
+ for(const Entry sel :entity.Trim2) {
+ if (const EXPRESS::REAL* const r = sel->ToPtr<EXPRESS::REAL>()) {
+ range.second = *r;
+ have_param = true;
+ break;
+ }
+ else if (const IfcCartesianPoint* const r = sel->ResolveSelectPtr<IfcCartesianPoint>(conv.db)) {
+ ConvertCartesianPoint(point,*r);
+ have_point = true;
+ }
+ }
+ if (!have_param) {
+ if (!have_point || !base->ReverseEval(point,range.second)) {
+ throw CurveError("IfcTrimmedCurve: failed to read second trim parameter, ignoring curve");
+ }
+ }
+
+ agree_sense = IsTrue(entity.SenseAgreement);
+ if( !agree_sense ) {
+ std::swap(range.first,range.second);
+ }
+
+ // "NOTE In case of a closed curve, it may be necessary to increment t1 or t2
+ // by the parametric length for consistency with the sense flag."
+ if (base->IsClosed()) {
+ if( range.first > range.second ) {
+ range.second += base->GetParametricRangeDelta();
+ }
+ }
+
+ maxval = range.second-range.first;
+ ai_assert(maxval >= 0);
+ }
public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat p) const {
- ai_assert(InRange(p));
- return base->Eval( TrimParam(p) );
- }
-
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
- return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
- }
-
- // --------------------------------------------------
- void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
- return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
- }
-
- // --------------------------------------------------
- ParamRange GetParametricRange() const {
- return std::make_pair(static_cast<IfcFloat>( 0. ),maxval);
- }
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat p) const {
+ ai_assert(InRange(p));
+ return base->Eval( TrimParam(p) );
+ }
+
+ // --------------------------------------------------
+ size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
+ return base->EstimateSampleCount(TrimParam(a),TrimParam(b));
+ }
+
+ // --------------------------------------------------
+ void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
+ return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
+ }
+
+ // --------------------------------------------------
+ ParamRange GetParametricRange() const {
+ return std::make_pair(static_cast<IfcFloat>( 0. ),maxval);
+ }
private:
- // --------------------------------------------------
- IfcFloat TrimParam(IfcFloat f) const {
- return agree_sense ? f + range.first : range.second - f;
- }
+ // --------------------------------------------------
+ IfcFloat TrimParam(IfcFloat f) const {
+ return agree_sense ? f + range.first : range.second - f;
+ }
private:
- const IfcTrimmedCurve& entity;
- ParamRange range;
- IfcFloat maxval;
- bool agree_sense;
- bool ok;
+ ParamRange range;
+ IfcFloat maxval;
+ bool agree_sense;
- boost::shared_ptr<const Curve> base;
+ std::shared_ptr<const Curve> base;
};
// --------------------------------------------------------------------------------
// PolyLine is a 'curve' defined by linear interpolation over a set of discrete points
// --------------------------------------------------------------------------------
-class PolyLine : public BoundedCurve
+class PolyLine : public BoundedCurve
{
public:
- // --------------------------------------------------
- PolyLine(const IfcPolyline& entity, ConversionData& conv)
- : BoundedCurve(entity,conv)
- , entity(entity)
- {
- points.reserve(entity.Points.size());
+ // --------------------------------------------------
+ PolyLine(const IfcPolyline& entity, ConversionData& conv)
+ : BoundedCurve(entity,conv)
+ {
+ points.reserve(entity.Points.size());
- IfcVector3 t;
- BOOST_FOREACH(const IfcCartesianPoint& cp, entity.Points) {
- ConvertCartesianPoint(t,cp);
- points.push_back(t);
- }
- }
+ IfcVector3 t;
+ for(const IfcCartesianPoint& cp : entity.Points) {
+ ConvertCartesianPoint(t,cp);
+ points.push_back(t);
+ }
+ }
public:
- // --------------------------------------------------
- IfcVector3 Eval(IfcFloat p) const {
- ai_assert(InRange(p));
-
+ // --------------------------------------------------
+ IfcVector3 Eval(IfcFloat p) const {
+ ai_assert(InRange(p));
+
const size_t b = static_cast<size_t>(std::floor(p));
- if (b == points.size()-1) {
- return points.back();
- }
+ if (b == points.size()-1) {
+ return points.back();
+ }
- const IfcFloat d = p-static_cast<IfcFloat>(b);
- return points[b+1] * d + points[b] * (static_cast<IfcFloat>( 1. )-d);
- }
+ const IfcFloat d = p-static_cast<IfcFloat>(b);
+ return points[b+1] * d + points[b] * (static_cast<IfcFloat>( 1. )-d);
+ }
- // --------------------------------------------------
- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
- ai_assert(InRange(a) && InRange(b));
+ // --------------------------------------------------
+ size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
+ ai_assert(InRange(a) && InRange(b));
return static_cast<size_t>( std::ceil(b) - std::floor(a) );
- }
+ }
- // --------------------------------------------------
- ParamRange GetParametricRange() const {
- return std::make_pair(static_cast<IfcFloat>( 0. ),static_cast<IfcFloat>(points.size()-1));
- }
+ // --------------------------------------------------
+ ParamRange GetParametricRange() const {
+ return std::make_pair(static_cast<IfcFloat>( 0. ),static_cast<IfcFloat>(points.size()-1));
+ }
private:
- const IfcPolyline& entity;
- std::vector<IfcVector3> points;
+ std::vector<IfcVector3> points;
};
@@ -516,159 +506,159 @@ private:
// ------------------------------------------------------------------------------------------------
-Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
+Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv)
{
- if(curve.ToPtr<IfcBoundedCurve>()) {
- if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
- return new PolyLine(*c,conv);
- }
- if(const IfcTrimmedCurve* c = curve.ToPtr<IfcTrimmedCurve>()) {
- return new TrimmedCurve(*c,conv);
- }
- if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
- return new CompositeCurve(*c,conv);
- }
- //if(const IfcBSplineCurve* c = curve.ToPtr<IfcBSplineCurve>()) {
- // return new BSplineCurve(*c,conv);
- //}
- }
-
- if(curve.ToPtr<IfcConic>()) {
- if(const IfcCircle* c = curve.ToPtr<IfcCircle>()) {
- return new Circle(*c,conv);
- }
- if(const IfcEllipse* c = curve.ToPtr<IfcEllipse>()) {
- return new Ellipse(*c,conv);
- }
- }
-
- if(const IfcLine* c = curve.ToPtr<IfcLine>()) {
- return new Line(*c,conv);
- }
-
- // XXX OffsetCurve2D, OffsetCurve3D not currently supported
- return NULL;
+ if(curve.ToPtr<IfcBoundedCurve>()) {
+ if(const IfcPolyline* c = curve.ToPtr<IfcPolyline>()) {
+ return new PolyLine(*c,conv);
+ }
+ if(const IfcTrimmedCurve* c = curve.ToPtr<IfcTrimmedCurve>()) {
+ return new TrimmedCurve(*c,conv);
+ }
+ if(const IfcCompositeCurve* c = curve.ToPtr<IfcCompositeCurve>()) {
+ return new CompositeCurve(*c,conv);
+ }
+ //if(const IfcBSplineCurve* c = curve.ToPtr<IfcBSplineCurve>()) {
+ // return new BSplineCurve(*c,conv);
+ //}
+ }
+
+ if(curve.ToPtr<IfcConic>()) {
+ if(const IfcCircle* c = curve.ToPtr<IfcCircle>()) {
+ return new Circle(*c,conv);
+ }
+ if(const IfcEllipse* c = curve.ToPtr<IfcEllipse>()) {
+ return new Ellipse(*c,conv);
+ }
+ }
+
+ if(const IfcLine* c = curve.ToPtr<IfcLine>()) {
+ return new Line(*c,conv);
+ }
+
+ // XXX OffsetCurve2D, OffsetCurve3D not currently supported
+ return NULL;
}
#ifdef ASSIMP_BUILD_DEBUG
// ------------------------------------------------------------------------------------------------
-bool Curve :: InRange(IfcFloat u) const
+bool Curve :: InRange(IfcFloat u) const
{
- const ParamRange range = GetParametricRange();
- if (IsClosed()) {
- return true;
- //ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
+ const ParamRange range = GetParametricRange();
+ if (IsClosed()) {
+ return true;
+ //ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
//u = range.first + std::fmod(u-range.first,range.second-range.first);
- }
- const IfcFloat epsilon = 1e-5;
- return u - range.first > -epsilon && range.second - u > -epsilon;
+ }
+ const IfcFloat epsilon = 1e-5;
+ return u - range.first > -epsilon && range.second - u > -epsilon;
}
-#endif
+#endif
// ------------------------------------------------------------------------------------------------
IfcFloat Curve :: GetParametricRangeDelta() const
{
- const ParamRange& range = GetParametricRange();
+ const ParamRange& range = GetParametricRange();
return std::abs(range.second - range.first);
}
// ------------------------------------------------------------------------------------------------
size_t Curve :: EstimateSampleCount(IfcFloat a, IfcFloat b) const
{
- ai_assert(InRange(a) && InRange(b));
+ ai_assert(InRange(a) && InRange(b));
- // arbitrary default value, deriving classes should supply better suited values
- return 16;
+ // arbitrary default value, deriving classes should supply better suited values
+ return 16;
}
// ------------------------------------------------------------------------------------------------
IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b, unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15)
{
- ai_assert(samples>1);
-
- const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
- IfcFloat min_point[2] = {a,b}, min_diff[2] = {inf,inf};
- IfcFloat runner = a;
-
- for (unsigned int i = 0; i < samples; ++i, runner += delta) {
- const IfcFloat diff = (cv->Eval(runner)-val).SquareLength();
- if (diff < min_diff[0]) {
- min_diff[1] = min_diff[0];
- min_point[1] = min_point[0];
-
- min_diff[0] = diff;
- min_point[0] = runner;
- }
- else if (diff < min_diff[1]) {
- min_diff[1] = diff;
- min_point[1] = runner;
- }
- }
-
- ai_assert(min_diff[0] != inf && min_diff[1] != inf);
+ ai_assert(samples>1);
+
+ const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits<IfcFloat>::infinity();
+ IfcFloat min_point[2] = {a,b}, min_diff[2] = {inf,inf};
+ IfcFloat runner = a;
+
+ for (unsigned int i = 0; i < samples; ++i, runner += delta) {
+ const IfcFloat diff = (cv->Eval(runner)-val).SquareLength();
+ if (diff < min_diff[0]) {
+ min_diff[1] = min_diff[0];
+ min_point[1] = min_point[0];
+
+ min_diff[0] = diff;
+ min_point[0] = runner;
+ }
+ else if (diff < min_diff[1]) {
+ min_diff[1] = diff;
+ min_point[1] = runner;
+ }
+ }
+
+ ai_assert(min_diff[0] != inf && min_diff[1] != inf);
if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
- return min_point[0];
- }
+ return min_point[0];
+ }
- // fix for closed curves to take their wrap-over into account
+ // fix for closed curves to take their wrap-over into account
if (cv->IsClosed() && std::fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
- const Curve::ParamRange& range = cv->GetParametricRange();
- const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();
+ const Curve::ParamRange& range = cv->GetParametricRange();
+ const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();
- if (wrapdiff < min_diff[0]) {
- const IfcFloat t = min_point[0];
- min_point[0] = min_point[1] > min_point[0] ? range.first : range.second;
- min_point[1] = t;
- }
- }
+ if (wrapdiff < min_diff[0]) {
+ const IfcFloat t = min_point[0];
+ min_point[0] = min_point[1] > min_point[0] ? range.first : range.second;
+ min_point[1] = t;
+ }
+ }
- return RecursiveSearch(cv,val,min_point[0],min_point[1],samples,threshold,recurse+1,max_recurse);
+ return RecursiveSearch(cv,val,min_point[0],min_point[1],samples,threshold,recurse+1,max_recurse);
}
// ------------------------------------------------------------------------------------------------
bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const
{
- // note: the following algorithm is not guaranteed to find the 'right' parameter value
- // in all possible cases, but it will always return at least some value so this function
- // will never fail in the default implementation.
+ // note: the following algorithm is not guaranteed to find the 'right' parameter value
+ // in all possible cases, but it will always return at least some value so this function
+ // will never fail in the default implementation.
- // XXX derive threshold from curve topology
- const IfcFloat threshold = 1e-4f;
- const unsigned int samples = 16;
+ // XXX derive threshold from curve topology
+ const IfcFloat threshold = 1e-4f;
+ const unsigned int samples = 16;
- const ParamRange& range = GetParametricRange();
- paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
+ const ParamRange& range = GetParametricRange();
+ paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold);
- return true;
+ return true;
}
// ------------------------------------------------------------------------------------------------
void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const
{
- ai_assert(InRange(a) && InRange(b));
+ ai_assert(InRange(a) && InRange(b));
- const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
- out.verts.reserve( out.verts.size() + cnt );
+ const size_t cnt = std::max(static_cast<size_t>(0),EstimateSampleCount(a,b));
+ out.verts.reserve( out.verts.size() + cnt + 1);
- IfcFloat p = a, delta = (b-a)/cnt;
- for(size_t i = 0; i < cnt; ++i, p += delta) {
- out.verts.push_back(Eval(p));
- }
+ IfcFloat p = a, delta = (b-a)/cnt;
+ for(size_t i = 0; i <= cnt; ++i, p += delta) {
+ out.verts.push_back(Eval(p));
+ }
}
// ------------------------------------------------------------------------------------------------
bool BoundedCurve :: IsClosed() const
{
- return false;
+ return false;
}
// ------------------------------------------------------------------------------------------------
void BoundedCurve :: SampleDiscrete(TempMesh& out) const
{
- const ParamRange& range = GetParametricRange();
- ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
+ const ParamRange& range = GetParametricRange();
+ ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
- return SampleDiscrete(out,range.first,range.second);
+ return SampleDiscrete(out,range.first,range.second);
}
} // IFC
diff --git a/src/3rdparty/assimp/code/IFCGeometry.cpp b/src/3rdparty/assimp/code/IFCGeometry.cpp
index 96ccf2910..5a2e4a09d 100644
--- a/src/3rdparty/assimp/code/IFCGeometry.cpp
+++ b/src/3rdparty/assimp/code/IFCGeometry.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2010, 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Geometry conversion and synthesis for IFC
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
@@ -51,268 +51,269 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../contrib/poly2tri/poly2tri/poly2tri.h"
#include "../contrib/clipper/clipper.hpp"
+#include <memory>
#include <iterator>
namespace Assimp {
- namespace IFC {
+ namespace IFC {
// ------------------------------------------------------------------------------------------------
bool ProcessPolyloop(const IfcPolyLoop& loop, TempMesh& meshout, ConversionData& /*conv*/)
{
- size_t cnt = 0;
- BOOST_FOREACH(const IfcCartesianPoint& c, loop.Polygon) {
- IfcVector3 tmp;
- ConvertCartesianPoint(tmp,c);
-
- meshout.verts.push_back(tmp);
- ++cnt;
- }
-
- meshout.vertcnt.push_back(cnt);
-
- // zero- or one- vertex polyloops simply ignored
- if (meshout.vertcnt.back() > 1) {
- return true;
- }
-
- if (meshout.vertcnt.back()==1) {
- meshout.vertcnt.pop_back();
- meshout.verts.pop_back();
- }
- return false;
+ size_t cnt = 0;
+ for(const IfcCartesianPoint& c : loop.Polygon) {
+ IfcVector3 tmp;
+ ConvertCartesianPoint(tmp,c);
+
+ meshout.verts.push_back(tmp);
+ ++cnt;
+ }
+
+ meshout.vertcnt.push_back(cnt);
+
+ // zero- or one- vertex polyloops simply ignored
+ if (meshout.vertcnt.back() > 1) {
+ return true;
+ }
+
+ if (meshout.vertcnt.back()==1) {
+ meshout.vertcnt.pop_back();
+ meshout.verts.pop_back();
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
-void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1)
+void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t master_bounds = (size_t)-1)
{
- // handle all trivial cases
- if(inmesh.vertcnt.empty()) {
- return;
- }
- if(inmesh.vertcnt.size() == 1) {
- result.Append(inmesh);
- return;
- }
-
- ai_assert(std::count(inmesh.vertcnt.begin(), inmesh.vertcnt.end(), 0) == 0);
-
- typedef std::vector<unsigned int>::const_iterator face_iter;
-
- face_iter begin = inmesh.vertcnt.begin(), end = inmesh.vertcnt.end(), iit;
- std::vector<unsigned int>::const_iterator outer_polygon_it = end;
-
- // major task here: given a list of nested polygon boundaries (one of which
- // is the outer contour), reduce the triangulation task arising here to
- // one that can be solved using the "quadrulation" algorithm which we use
- // for pouring windows out of walls. The algorithm does not handle all
- // cases but at least it is numerically stable and gives "nice" triangles.
-
- // first compute normals for all polygons using Newell's algorithm
- // do not normalize 'normals', we need the original length for computing the polygon area
- std::vector<IfcVector3> normals;
- inmesh.ComputePolygonNormals(normals,false);
-
- // One of the polygons might be a IfcFaceOuterBound (in which case `master_bounds`
- // is its index). Sadly we can't rely on it, the docs say 'At most one of the bounds
- // shall be of the type IfcFaceOuterBound'
- IfcFloat area_outer_polygon = 1e-10f;
- if (master_bounds != (size_t)-1) {
- ai_assert(master_bounds < inmesh.vertcnt.size());
- outer_polygon_it = begin + master_bounds;
- }
- else {
- for(iit = begin; iit != end; iit++) {
- // find the polygon with the largest area and take it as the outer bound.
- IfcVector3& n = normals[std::distance(begin,iit)];
- const IfcFloat area = n.SquareLength();
- if (area > area_outer_polygon) {
- area_outer_polygon = area;
- outer_polygon_it = iit;
- }
- }
- }
-
- ai_assert(outer_polygon_it != end);
-
- const size_t outer_polygon_size = *outer_polygon_it;
- const IfcVector3& master_normal = normals[std::distance(begin, outer_polygon_it)];
-
- // Generate fake openings to meet the interface for the quadrulate
- // algorithm. It boils down to generating small boxes given the
- // inner polygon and the surface normal of the outer contour.
- // It is important that we use the outer contour's normal because
- // this is the plane onto which the quadrulate algorithm will
- // project the entire mesh.
- std::vector<TempOpening> fake_openings;
- fake_openings.reserve(inmesh.vertcnt.size()-1);
-
- std::vector<IfcVector3>::const_iterator vit = inmesh.verts.begin(), outer_vit;
-
- for(iit = begin; iit != end; vit += *iit++) {
- if (iit == outer_polygon_it) {
- outer_vit = vit;
- continue;
- }
-
- // Filter degenerate polygons to keep them from causing trouble later on
- IfcVector3& n = normals[std::distance(begin,iit)];
- const IfcFloat area = n.SquareLength();
- if (area < 1e-5f) {
- IFCImporter::LogWarn("skipping degenerate polygon (ProcessPolygonBoundaries)");
- continue;
- }
-
- fake_openings.push_back(TempOpening());
- TempOpening& opening = fake_openings.back();
-
- opening.extrusionDir = master_normal;
- opening.solid = NULL;
-
- opening.profileMesh = boost::make_shared<TempMesh>();
- opening.profileMesh->verts.reserve(*iit);
- opening.profileMesh->vertcnt.push_back(*iit);
-
- std::copy(vit, vit + *iit, std::back_inserter(opening.profileMesh->verts));
- }
-
- // fill a mesh with ONLY the main polygon
- TempMesh temp;
- temp.verts.reserve(outer_polygon_size);
- temp.vertcnt.push_back(outer_polygon_size);
- std::copy(outer_vit, outer_vit+outer_polygon_size,
- std::back_inserter(temp.verts));
-
- GenerateOpenings(fake_openings, normals, temp, false, false);
- result.Append(temp);
+ // handle all trivial cases
+ if(inmesh.vertcnt.empty()) {
+ return;
+ }
+ if(inmesh.vertcnt.size() == 1) {
+ result.Append(inmesh);
+ return;
+ }
+
+ ai_assert(std::count(inmesh.vertcnt.begin(), inmesh.vertcnt.end(), 0) == 0);
+
+ typedef std::vector<unsigned int>::const_iterator face_iter;
+
+ face_iter begin = inmesh.vertcnt.begin(), end = inmesh.vertcnt.end(), iit;
+ std::vector<unsigned int>::const_iterator outer_polygon_it = end;
+
+ // major task here: given a list of nested polygon boundaries (one of which
+ // is the outer contour), reduce the triangulation task arising here to
+ // one that can be solved using the "quadrulation" algorithm which we use
+ // for pouring windows out of walls. The algorithm does not handle all
+ // cases but at least it is numerically stable and gives "nice" triangles.
+
+ // first compute normals for all polygons using Newell's algorithm
+ // do not normalize 'normals', we need the original length for computing the polygon area
+ std::vector<IfcVector3> normals;
+ inmesh.ComputePolygonNormals(normals,false);
+
+ // One of the polygons might be a IfcFaceOuterBound (in which case `master_bounds`
+ // is its index). Sadly we can't rely on it, the docs say 'At most one of the bounds
+ // shall be of the type IfcFaceOuterBound'
+ IfcFloat area_outer_polygon = 1e-10f;
+ if (master_bounds != (size_t)-1) {
+ ai_assert(master_bounds < inmesh.vertcnt.size());
+ outer_polygon_it = begin + master_bounds;
+ }
+ else {
+ for(iit = begin; iit != end; iit++) {
+ // find the polygon with the largest area and take it as the outer bound.
+ IfcVector3& n = normals[std::distance(begin,iit)];
+ const IfcFloat area = n.SquareLength();
+ if (area > area_outer_polygon) {
+ area_outer_polygon = area;
+ outer_polygon_it = iit;
+ }
+ }
+ }
+
+ ai_assert(outer_polygon_it != end);
+
+ const size_t outer_polygon_size = *outer_polygon_it;
+ const IfcVector3& master_normal = normals[std::distance(begin, outer_polygon_it)];
+
+ // Generate fake openings to meet the interface for the quadrulate
+ // algorithm. It boils down to generating small boxes given the
+ // inner polygon and the surface normal of the outer contour.
+ // It is important that we use the outer contour's normal because
+ // this is the plane onto which the quadrulate algorithm will
+ // project the entire mesh.
+ std::vector<TempOpening> fake_openings;
+ fake_openings.reserve(inmesh.vertcnt.size()-1);
+
+ std::vector<IfcVector3>::const_iterator vit = inmesh.verts.begin(), outer_vit;
+
+ for(iit = begin; iit != end; vit += *iit++) {
+ if (iit == outer_polygon_it) {
+ outer_vit = vit;
+ continue;
+ }
+
+ // Filter degenerate polygons to keep them from causing trouble later on
+ IfcVector3& n = normals[std::distance(begin,iit)];
+ const IfcFloat area = n.SquareLength();
+ if (area < 1e-5f) {
+ IFCImporter::LogWarn("skipping degenerate polygon (ProcessPolygonBoundaries)");
+ continue;
+ }
+
+ fake_openings.push_back(TempOpening());
+ TempOpening& opening = fake_openings.back();
+
+ opening.extrusionDir = master_normal;
+ opening.solid = NULL;
+
+ opening.profileMesh = std::make_shared<TempMesh>();
+ opening.profileMesh->verts.reserve(*iit);
+ opening.profileMesh->vertcnt.push_back(*iit);
+
+ std::copy(vit, vit + *iit, std::back_inserter(opening.profileMesh->verts));
+ }
+
+ // fill a mesh with ONLY the main polygon
+ TempMesh temp;
+ temp.verts.reserve(outer_polygon_size);
+ temp.vertcnt.push_back(outer_polygon_size);
+ std::copy(outer_vit, outer_vit+outer_polygon_size,
+ std::back_inserter(temp.verts));
+
+ GenerateOpenings(fake_openings, normals, temp, false, false);
+ result.Append(temp);
}
// ------------------------------------------------------------------------------------------------
void ProcessConnectedFaceSet(const IfcConnectedFaceSet& fset, TempMesh& result, ConversionData& conv)
{
- BOOST_FOREACH(const IfcFace& face, fset.CfsFaces) {
- // size_t ob = -1, cnt = 0;
- TempMesh meshout;
- BOOST_FOREACH(const IfcFaceBound& bound, face.Bounds) {
-
- if(const IfcPolyLoop* const polyloop = bound.Bound->ToPtr<IfcPolyLoop>()) {
- if(ProcessPolyloop(*polyloop, meshout,conv)) {
-
- // The outer boundary is better determined by checking which
- // polygon covers the largest area.
-
- //if(bound.ToPtr<IfcFaceOuterBound>()) {
- // ob = cnt;
- //}
- //++cnt;
-
- }
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is " + bound.Bound->GetClassName());
- continue;
- }
-
- // And this, even though it is sometimes TRUE and sometimes FALSE,
- // does not really improve results.
-
- /*if(!IsTrue(bound.Orientation)) {
- size_t c = 0;
- BOOST_FOREACH(unsigned int& c, meshout.vertcnt) {
- std::reverse(result.verts.begin() + cnt,result.verts.begin() + cnt + c);
- cnt += c;
- }
- }*/
- }
- ProcessPolygonBoundaries(result, meshout);
- }
+ for(const IfcFace& face : fset.CfsFaces) {
+ // size_t ob = -1, cnt = 0;
+ TempMesh meshout;
+ for(const IfcFaceBound& bound : face.Bounds) {
+
+ if(const IfcPolyLoop* const polyloop = bound.Bound->ToPtr<IfcPolyLoop>()) {
+ if(ProcessPolyloop(*polyloop, meshout,conv)) {
+
+ // The outer boundary is better determined by checking which
+ // polygon covers the largest area.
+
+ //if(bound.ToPtr<IfcFaceOuterBound>()) {
+ // ob = cnt;
+ //}
+ //++cnt;
+
+ }
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is " + bound.Bound->GetClassName());
+ continue;
+ }
+
+ // And this, even though it is sometimes TRUE and sometimes FALSE,
+ // does not really improve results.
+
+ /*if(!IsTrue(bound.Orientation)) {
+ size_t c = 0;
+ for(unsigned int& c : meshout.vertcnt) {
+ std::reverse(result.verts.begin() + cnt,result.verts.begin() + cnt + c);
+ cnt += c;
+ }
+ }*/
+ }
+ ProcessPolygonBoundaries(result, meshout);
+ }
}
// ------------------------------------------------------------------------------------------------
void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& result, ConversionData& conv)
{
- TempMesh meshout;
-
- // first read the profile description
- if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
- return;
- }
-
- IfcVector3 axis, pos;
- ConvertAxisPlacement(axis,pos,solid.Axis);
-
- IfcMatrix4 tb0,tb1;
- IfcMatrix4::Translation(pos,tb0);
- IfcMatrix4::Translation(-pos,tb1);
-
- const std::vector<IfcVector3>& in = meshout.verts;
- const size_t size=in.size();
-
- bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
- const IfcFloat max_angle = solid.Angle*conv.angle_scale;
- if(std::fabs(max_angle) < 1e-3) {
- if(has_area) {
- result = meshout;
- }
- return;
- }
-
- const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
- const IfcFloat delta = max_angle/cnt_segments;
-
- has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
-
- result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0)));
- result.vertcnt.reserve(size*cnt_segments+2);
-
- IfcMatrix4 rot;
- rot = tb0 * IfcMatrix4::Rotation(delta,axis,rot) * tb1;
-
- size_t base = 0;
- std::vector<IfcVector3>& out = result.verts;
-
- // dummy data to simplify later processing
- for(size_t i = 0; i < size; ++i) {
- out.insert(out.end(),4,in[i]);
- }
-
- for(unsigned int seg = 0; seg < cnt_segments; ++seg) {
- for(size_t i = 0; i < size; ++i) {
- const size_t next = (i+1)%size;
-
- result.vertcnt.push_back(4);
- const IfcVector3& base_0 = out[base+i*4+3],base_1 = out[base+next*4+3];
-
- out.push_back(base_0);
- out.push_back(base_1);
- out.push_back(rot*base_1);
- out.push_back(rot*base_0);
- }
- base += size*4;
- }
-
- out.erase(out.begin(),out.begin()+size*4);
-
- if(has_area) {
- // leave the triangulation of the profile area to the ear cutting
- // implementation in aiProcess_Triangulate - for now we just
- // feed in two huge polygons.
- base -= size*8;
- for(size_t i = size; i--; ) {
- out.push_back(out[base+i*4+3]);
- }
- for(size_t i = 0; i < size; ++i ) {
- out.push_back(out[i*4]);
- }
- result.vertcnt.push_back(size);
- result.vertcnt.push_back(size);
- }
-
- IfcMatrix4 trafo;
- ConvertAxisPlacement(trafo, solid.Position);
-
- result.Transform(trafo);
- IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
+ TempMesh meshout;
+
+ // first read the profile description
+ if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
+ return;
+ }
+
+ IfcVector3 axis, pos;
+ ConvertAxisPlacement(axis,pos,solid.Axis);
+
+ IfcMatrix4 tb0,tb1;
+ IfcMatrix4::Translation(pos,tb0);
+ IfcMatrix4::Translation(-pos,tb1);
+
+ const std::vector<IfcVector3>& in = meshout.verts;
+ const size_t size=in.size();
+
+ bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
+ const IfcFloat max_angle = solid.Angle*conv.angle_scale;
+ if(std::fabs(max_angle) < 1e-3) {
+ if(has_area) {
+ result = meshout;
+ }
+ return;
+ }
+
+ const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
+ const IfcFloat delta = max_angle/cnt_segments;
+
+ has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
+
+ result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0)));
+ result.vertcnt.reserve(size*cnt_segments+2);
+
+ IfcMatrix4 rot;
+ rot = tb0 * IfcMatrix4::Rotation(delta,axis,rot) * tb1;
+
+ size_t base = 0;
+ std::vector<IfcVector3>& out = result.verts;
+
+ // dummy data to simplify later processing
+ for(size_t i = 0; i < size; ++i) {
+ out.insert(out.end(),4,in[i]);
+ }
+
+ for(unsigned int seg = 0; seg < cnt_segments; ++seg) {
+ for(size_t i = 0; i < size; ++i) {
+ const size_t next = (i+1)%size;
+
+ result.vertcnt.push_back(4);
+ const IfcVector3& base_0 = out[base+i*4+3],base_1 = out[base+next*4+3];
+
+ out.push_back(base_0);
+ out.push_back(base_1);
+ out.push_back(rot*base_1);
+ out.push_back(rot*base_0);
+ }
+ base += size*4;
+ }
+
+ out.erase(out.begin(),out.begin()+size*4);
+
+ if(has_area) {
+ // leave the triangulation of the profile area to the ear cutting
+ // implementation in aiProcess_Triangulate - for now we just
+ // feed in two huge polygons.
+ base -= size*8;
+ for(size_t i = size; i--; ) {
+ out.push_back(out[base+i*4+3]);
+ }
+ for(size_t i = 0; i < size; ++i ) {
+ out.push_back(out[i*4]);
+ }
+ result.vertcnt.push_back(size);
+ result.vertcnt.push_back(size);
+ }
+
+ IfcMatrix4 trafo;
+ ConvertAxisPlacement(trafo, solid.Position);
+
+ result.Transform(trafo);
+ IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
}
@@ -320,530 +321,566 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
// ------------------------------------------------------------------------------------------------
void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, ConversionData& conv)
{
- const Curve* const curve = Curve::Convert(*solid.Directrix, conv);
- if(!curve) {
- IFCImporter::LogError("failed to convert Directrix curve (IfcSweptDiskSolid)");
- return;
- }
-
- const unsigned int cnt_segments = 16;
- const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments;
+ const Curve* const curve = Curve::Convert(*solid.Directrix, conv);
+ if(!curve) {
+ IFCImporter::LogError("failed to convert Directrix curve (IfcSweptDiskSolid)");
+ return;
+ }
+
+ const unsigned int cnt_segments = 16;
+ const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments;
+
+ const size_t samples = curve->EstimateSampleCount(solid.StartParam,solid.EndParam);
- const size_t samples = curve->EstimateSampleCount(solid.StartParam,solid.EndParam);
+ result.verts.reserve(cnt_segments * samples * 4);
+ result.vertcnt.reserve((cnt_segments - 1) * samples);
- result.verts.reserve(cnt_segments * samples * 4);
- result.vertcnt.reserve((cnt_segments - 1) * samples);
+ std::vector<IfcVector3> points;
+ points.reserve(cnt_segments * samples);
- std::vector<IfcVector3> points;
- points.reserve(cnt_segments * samples);
+ TempMesh temp;
+ curve->SampleDiscrete(temp,solid.StartParam,solid.EndParam);
+ const std::vector<IfcVector3>& curve_points = temp.verts;
- TempMesh temp;
- curve->SampleDiscrete(temp,solid.StartParam,solid.EndParam);
- const std::vector<IfcVector3>& curve_points = temp.verts;
+ if(curve_points.empty()) {
+ IFCImporter::LogWarn("curve evaluation yielded no points (IfcSweptDiskSolid)");
+ return;
+ }
- if(curve_points.empty()) {
- IFCImporter::LogWarn("curve evaluation yielded no points (IfcSweptDiskSolid)");
- return;
- }
+ IfcVector3 current = curve_points[0];
+ IfcVector3 previous = current;
+ IfcVector3 next;
- IfcVector3 current = curve_points[0];
- IfcVector3 previous = current;
- IfcVector3 next;
+ IfcVector3 startvec;
+ startvec.x = 1.0f;
+ startvec.y = 1.0f;
+ startvec.z = 1.0f;
- IfcVector3 startvec;
- startvec.x = 1.0f;
- startvec.y = 1.0f;
- startvec.z = 1.0f;
+ unsigned int last_dir = 0;
- unsigned int last_dir = 0;
+ // generate circles at the sweep positions
+ for(size_t i = 0; i < samples; ++i) {
- // generate circles at the sweep positions
- for(size_t i = 0; i < samples; ++i) {
+ if(i != samples - 1) {
+ next = curve_points[i + 1];
+ }
- if(i != samples - 1) {
- next = curve_points[i + 1];
- }
+ // get a direction vector reflecting the approximate curvature (i.e. tangent)
+ IfcVector3 d = (current-previous) + (next-previous);
- // get a direction vector reflecting the approximate curvature (i.e. tangent)
- IfcVector3 d = (current-previous) + (next-previous);
-
- d.Normalize();
+ d.Normalize();
- // figure out an arbitrary point q so that (p-q) * d = 0,
- // try to maximize ||(p-q)|| * ||(p_last-q_last)||
- IfcVector3 q;
- bool take_any = false;
+ // figure out an arbitrary point q so that (p-q) * d = 0,
+ // try to maximize ||(p-q)|| * ||(p_last-q_last)||
+ IfcVector3 q;
+ bool take_any = false;
- for (unsigned int i = 0; i < 2; ++i, take_any = true) {
+ for (unsigned int i = 0; i < 2; ++i, take_any = true) {
if ((last_dir == 0 || take_any) && std::abs(d.x) > 1e-6) {
- q.y = startvec.y;
- q.z = startvec.z;
- q.x = -(d.y * q.y + d.z * q.z) / d.x;
- last_dir = 0;
- break;
- }
+ q.y = startvec.y;
+ q.z = startvec.z;
+ q.x = -(d.y * q.y + d.z * q.z) / d.x;
+ last_dir = 0;
+ break;
+ }
else if ((last_dir == 1 || take_any) && std::abs(d.y) > 1e-6) {
- q.x = startvec.x;
- q.z = startvec.z;
- q.y = -(d.x * q.x + d.z * q.z) / d.y;
- last_dir = 1;
- break;
- }
+ q.x = startvec.x;
+ q.z = startvec.z;
+ q.y = -(d.x * q.x + d.z * q.z) / d.y;
+ last_dir = 1;
+ break;
+ }
else if ((last_dir == 2 && std::abs(d.z) > 1e-6) || take_any) {
- q.y = startvec.y;
- q.x = startvec.x;
- q.z = -(d.y * q.y + d.x * q.x) / d.z;
- last_dir = 2;
- break;
- }
- }
-
- q *= solid.Radius / q.Length();
- startvec = q;
-
- // generate a rotation matrix to rotate q around d
- IfcMatrix4 rot;
- IfcMatrix4::Rotation(deltaAngle,d,rot);
-
- for (unsigned int seg = 0; seg < cnt_segments; ++seg, q *= rot ) {
- points.push_back(q + current);
- }
-
- previous = current;
- current = next;
- }
-
- // make quads
- for(size_t i = 0; i < samples - 1; ++i) {
-
- const aiVector3D& this_start = points[ i * cnt_segments ];
-
- // locate corresponding point on next sample ring
- unsigned int best_pair_offset = 0;
- float best_distance_squared = 1e10f;
- for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
- const aiVector3D& p = points[ (i+1) * cnt_segments + seg];
- const float l = (p-this_start).SquareLength();
-
- if(l < best_distance_squared) {
- best_pair_offset = seg;
- best_distance_squared = l;
- }
- }
-
- for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
-
- result.verts.push_back(points[ i * cnt_segments + (seg % cnt_segments)]);
- result.verts.push_back(points[ i * cnt_segments + (seg + 1) % cnt_segments]);
- result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + 1 + best_pair_offset) % cnt_segments)]);
- result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + best_pair_offset) % cnt_segments)]);
-
- IfcVector3& v1 = *(result.verts.end()-1);
- IfcVector3& v2 = *(result.verts.end()-2);
- IfcVector3& v3 = *(result.verts.end()-3);
- IfcVector3& v4 = *(result.verts.end()-4);
-
- if (((v4-v3) ^ (v4-v1)) * (v4 - curve_points[i]) < 0.0f) {
- std::swap(v4, v1);
- std::swap(v3, v2);
- }
-
- result.vertcnt.push_back(4);
- }
- }
-
- IFCImporter::LogDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)");
+ q.y = startvec.y;
+ q.x = startvec.x;
+ q.z = -(d.y * q.y + d.x * q.x) / d.z;
+ last_dir = 2;
+ break;
+ }
+ }
+
+ q *= solid.Radius / q.Length();
+ startvec = q;
+
+ // generate a rotation matrix to rotate q around d
+ IfcMatrix4 rot;
+ IfcMatrix4::Rotation(deltaAngle,d,rot);
+
+ for (unsigned int seg = 0; seg < cnt_segments; ++seg, q *= rot ) {
+ points.push_back(q + current);
+ }
+
+ previous = current;
+ current = next;
+ }
+
+ // make quads
+ for(size_t i = 0; i < samples - 1; ++i) {
+
+ const aiVector3D& this_start = points[ i * cnt_segments ];
+
+ // locate corresponding point on next sample ring
+ unsigned int best_pair_offset = 0;
+ float best_distance_squared = 1e10f;
+ for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
+ const aiVector3D& p = points[ (i+1) * cnt_segments + seg];
+ const float l = (p-this_start).SquareLength();
+
+ if(l < best_distance_squared) {
+ best_pair_offset = seg;
+ best_distance_squared = l;
+ }
+ }
+
+ for (unsigned int seg = 0; seg < cnt_segments; ++seg) {
+
+ result.verts.push_back(points[ i * cnt_segments + (seg % cnt_segments)]);
+ result.verts.push_back(points[ i * cnt_segments + (seg + 1) % cnt_segments]);
+ result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + 1 + best_pair_offset) % cnt_segments)]);
+ result.verts.push_back(points[ (i+1) * cnt_segments + ((seg + best_pair_offset) % cnt_segments)]);
+
+ IfcVector3& v1 = *(result.verts.end()-1);
+ IfcVector3& v2 = *(result.verts.end()-2);
+ IfcVector3& v3 = *(result.verts.end()-3);
+ IfcVector3& v4 = *(result.verts.end()-4);
+
+ if (((v4-v3) ^ (v4-v1)) * (v4 - curve_points[i]) < 0.0f) {
+ std::swap(v4, v1);
+ std::swap(v3, v2);
+ }
+
+ result.vertcnt.push_back(4);
+ }
+ }
+
+ IFCImporter::LogDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)");
}
// ------------------------------------------------------------------------------------------------
-IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut)
+IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut)
{
- const std::vector<IfcVector3>& out = curmesh.verts;
- IfcMatrix3 m;
-
- ok = true;
-
- // The input "mesh" must be a single polygon
- const size_t s = out.size();
- assert(curmesh.vertcnt.size() == 1 && curmesh.vertcnt.back() == s);
-
- const IfcVector3 any_point = out[s-1];
- IfcVector3 nor;
-
- // The input polygon is arbitrarily shaped, therefore we might need some tries
- // until we find a suitable normal. Note that Newell's algorithm would give
- // a more robust result, but this variant also gives us a suitable first
- // axis for the 2D coordinate space on the polygon plane, exploiting the
- // fact that the input polygon is nearly always a quad.
- bool done = false;
- size_t i, j;
- for (i = 0; !done && i < s-2; done || ++i) {
- for (j = i+1; j < s-1; ++j) {
- nor = -((out[i]-any_point)^(out[j]-any_point));
- if(std::fabs(nor.Length()) > 1e-8f) {
- done = true;
- break;
- }
- }
- }
-
- if(!done) {
- ok = false;
- return m;
- }
-
- nor.Normalize();
- norOut = nor;
-
- IfcVector3 r = (out[i]-any_point);
- r.Normalize();
-
- //if(d) {
- // *d = -any_point * nor;
- //}
-
- // Reconstruct orthonormal basis
- // XXX use Gram Schmidt for increased robustness
- IfcVector3 u = r ^ nor;
- u.Normalize();
-
- m.a1 = r.x;
- m.a2 = r.y;
- m.a3 = r.z;
-
- m.b1 = u.x;
- m.b2 = u.y;
- m.b3 = u.z;
-
- m.c1 = -nor.x;
- m.c2 = -nor.y;
- m.c3 = -nor.z;
-
- return m;
+ const std::vector<IfcVector3>& out = curmesh.verts;
+ IfcMatrix3 m;
+
+ ok = true;
+
+ // The input "mesh" must be a single polygon
+ const size_t s = out.size();
+ assert(curmesh.vertcnt.size() == 1 && curmesh.vertcnt.back() == s);
+
+ const IfcVector3 any_point = out[s-1];
+ IfcVector3 nor;
+
+ // The input polygon is arbitrarily shaped, therefore we might need some tries
+ // until we find a suitable normal. Note that Newell's algorithm would give
+ // a more robust result, but this variant also gives us a suitable first
+ // axis for the 2D coordinate space on the polygon plane, exploiting the
+ // fact that the input polygon is nearly always a quad.
+ bool done = false;
+ size_t i, j;
+ for (i = 0; !done && i < s-2; done || ++i) {
+ for (j = i+1; j < s-1; ++j) {
+ nor = -((out[i]-any_point)^(out[j]-any_point));
+ if(std::fabs(nor.Length()) > 1e-8f) {
+ done = true;
+ break;
+ }
+ }
+ }
+
+ if(!done) {
+ ok = false;
+ return m;
+ }
+
+ nor.Normalize();
+ norOut = nor;
+
+ IfcVector3 r = (out[i]-any_point);
+ r.Normalize();
+
+ //if(d) {
+ // *d = -any_point * nor;
+ //}
+
+ // Reconstruct orthonormal basis
+ // XXX use Gram Schmidt for increased robustness
+ IfcVector3 u = r ^ nor;
+ u.Normalize();
+
+ m.a1 = r.x;
+ m.a2 = r.y;
+ m.a3 = r.z;
+
+ m.b1 = u.x;
+ m.b2 = u.y;
+ m.b3 = u.z;
+
+ m.c1 = -nor.x;
+ m.c2 = -nor.y;
+ m.c3 = -nor.z;
+
+ return m;
}
+// Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary.
+void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curve,
+ const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings)
+{
+ // Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis,
+ // forming new triangles.
+ const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.verts.size() > 2;
+ if( solid.Depth < 1e-6 ) {
+ if( has_area ) {
+ result.Append(curve);
+ }
+ return;
+ }
+
+ result.verts.reserve(curve.verts.size()*(has_area ? 4 : 2));
+ result.vertcnt.reserve(curve.verts.size() + 2);
+ std::vector<IfcVector3> in = curve.verts;
+
+ // First step: transform all vertices into the target coordinate space
+ IfcMatrix4 trafo;
+ ConvertAxisPlacement(trafo, solid.Position);
+
+ IfcVector3 vmin, vmax;
+ MinMaxChooser<IfcVector3>()(vmin, vmax);
+ for(IfcVector3& v : in) {
+ v *= trafo;
+
+ vmin = std::min(vmin, v);
+ vmax = std::max(vmax, v);
+ }
+
+ vmax -= vmin;
+ const IfcFloat diag = vmax.Length();
+ IfcVector3 dir = IfcMatrix3(trafo) * extrusionDir;
+
+ // reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction
+ IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size());
+ if( profileNormal * dir < 0.0 )
+ std::reverse(in.begin(), in.end());
+
+ std::vector<IfcVector3> nors;
+ const bool openings = !!conv.apply_openings && conv.apply_openings->size();
+
+ // Compute the normal vectors for all opening polygons as a prerequisite
+ // to TryAddOpenings_Poly2Tri()
+ // XXX this belongs into the aforementioned function
+ if( openings ) {
+
+ if( !conv.settings.useCustomTriangulation ) {
+ // it is essential to apply the openings in the correct spatial order. The direction
+ // doesn't matter, but we would screw up if we started with e.g. a door in between
+ // two windows.
+ std::sort(conv.apply_openings->begin(), conv.apply_openings->end(), TempOpening::DistanceSorter(in[0]));
+ }
+
+ nors.reserve(conv.apply_openings->size());
+ for(TempOpening& t : *conv.apply_openings) {
+ TempMesh& bounds = *t.profileMesh.get();
+
+ if( bounds.verts.size() <= 2 ) {
+ nors.push_back(IfcVector3());
+ continue;
+ }
+ nors.push_back(((bounds.verts[2] - bounds.verts[0]) ^ (bounds.verts[1] - bounds.verts[0])).Normalize());
+ }
+ }
+
+
+ TempMesh temp;
+ TempMesh& curmesh = openings ? temp : result;
+ std::vector<IfcVector3>& out = curmesh.verts;
+
+ size_t sides_with_openings = 0;
+ for( size_t i = 0; i < in.size(); ++i ) {
+ const size_t next = (i + 1) % in.size();
+
+ curmesh.vertcnt.push_back(4);
+
+ out.push_back(in[i]);
+ out.push_back(in[next]);
+ out.push_back(in[next] + dir);
+ out.push_back(in[i] + dir);
+
+ if( openings ) {
+ if( (in[i] - in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
+ ++sides_with_openings;
+ }
+
+ result.Append(temp);
+ temp.Clear();
+ }
+ }
+
+ if( openings ) {
+ for(TempOpening& opening : *conv.apply_openings) {
+ if( !opening.wallPoints.empty() ) {
+ IFCImporter::LogError("failed to generate all window caps");
+ }
+ opening.wallPoints.clear();
+ }
+ }
+
+ size_t sides_with_v_openings = 0;
+ if( has_area ) {
+
+ for( size_t n = 0; n < 2; ++n ) {
+ if( n > 0 ) {
+ for( size_t i = 0; i < in.size(); ++i )
+ out.push_back(in[i] + dir);
+ }
+ else {
+ for( size_t i = in.size(); i--; )
+ out.push_back(in[i]);
+ }
+
+ curmesh.vertcnt.push_back(in.size());
+ if( openings && in.size() > 2 ) {
+ if( GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
+ ++sides_with_v_openings;
+ }
+
+ result.Append(temp);
+ temp.Clear();
+ }
+ }
+ }
+
+ if( openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings)) ) {
+ IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
+ }
+
+ IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
+
+ // If this is an opening element, store both the extruded mesh and the 2D profile mesh
+ // it was created from. Return an empty mesh to the caller.
+ if( collect_openings && !result.IsEmpty() ) {
+ ai_assert(conv.collect_openings);
+ std::shared_ptr<TempMesh> profile = std::shared_ptr<TempMesh>(new TempMesh());
+ profile->Swap(result);
+
+ std::shared_ptr<TempMesh> profile2D = std::shared_ptr<TempMesh>(new TempMesh());
+ profile2D->verts.insert(profile2D->verts.end(), in.begin(), in.end());
+ profile2D->vertcnt.push_back(in.size());
+ conv.collect_openings->push_back(TempOpening(&solid, dir, profile, profile2D));
+
+ ai_assert(result.IsEmpty());
+ }
+}
// ------------------------------------------------------------------------------------------------
-void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
- ConversionData& conv, bool collect_openings)
+void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
+ ConversionData& conv, bool collect_openings)
{
- TempMesh meshout;
-
- // First read the profile description
- if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
- return;
- }
-
- IfcVector3 dir;
- ConvertDirection(dir,solid.ExtrudedDirection);
-
- dir *= solid.Depth; /*
- if(conv.collect_openings && !conv.apply_openings) {
- dir *= 1000.0;
- } */
-
- // Outline: assuming that `meshout.verts` is now a list of vertex points forming
- // the underlying profile, extrude along the given axis, forming new
- // triangles.
-
- std::vector<IfcVector3>& in = meshout.verts;
- const size_t size=in.size();
-
- const bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
- if(solid.Depth < 1e-6) {
- if(has_area) {
- result = meshout;
- }
- return;
- }
-
- result.verts.reserve(size*(has_area?4:2));
- result.vertcnt.reserve(meshout.vertcnt.size()+2);
-
- // First step: transform all vertices into the target coordinate space
- IfcMatrix4 trafo;
- ConvertAxisPlacement(trafo, solid.Position);
-
- IfcVector3 vmin, vmax;
- MinMaxChooser<IfcVector3>()(vmin, vmax);
- BOOST_FOREACH(IfcVector3& v,in) {
- v *= trafo;
-
- vmin = std::min(vmin, v);
- vmax = std::max(vmax, v);
- }
-
- vmax -= vmin;
- const IfcFloat diag = vmax.Length();
-
- IfcVector3 min = in[0];
- dir *= IfcMatrix3(trafo);
-
- std::vector<IfcVector3> nors;
- const bool openings = !!conv.apply_openings && conv.apply_openings->size();
-
- // Compute the normal vectors for all opening polygons as a prerequisite
- // to TryAddOpenings_Poly2Tri()
- // XXX this belongs into the aforementioned function
- if (openings) {
-
- if (!conv.settings.useCustomTriangulation) {
- // it is essential to apply the openings in the correct spatial order. The direction
- // doesn't matter, but we would screw up if we started with e.g. a door in between
- // two windows.
- std::sort(conv.apply_openings->begin(),conv.apply_openings->end(),
- TempOpening::DistanceSorter(min));
- }
-
- nors.reserve(conv.apply_openings->size());
- BOOST_FOREACH(TempOpening& t,*conv.apply_openings) {
- TempMesh& bounds = *t.profileMesh.get();
-
- if (bounds.verts.size() <= 2) {
- nors.push_back(IfcVector3());
- continue;
- }
- nors.push_back(((bounds.verts[2]-bounds.verts[0])^(bounds.verts[1]-bounds.verts[0]) ).Normalize());
- }
- }
-
-
- TempMesh temp;
- TempMesh& curmesh = openings ? temp : result;
- std::vector<IfcVector3>& out = curmesh.verts;
-
- size_t sides_with_openings = 0;
- for(size_t i = 0; i < size; ++i) {
- const size_t next = (i+1)%size;
-
- curmesh.vertcnt.push_back(4);
-
- out.push_back(in[i]);
- out.push_back(in[i]+dir);
- out.push_back(in[next]+dir);
- out.push_back(in[next]);
-
- if(openings) {
- if((in[i]-in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
- ++sides_with_openings;
- }
-
- result.Append(temp);
- temp.Clear();
- }
- }
-
- if(openings) {
- BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) {
- if (!opening.wallPoints.empty()) {
- IFCImporter::LogError("failed to generate all window caps");
- }
- opening.wallPoints.clear();
- }
- }
-
- size_t sides_with_v_openings = 0;
- if(has_area) {
-
- for(size_t n = 0; n < 2; ++n) {
- for(size_t i = size; i--; ) {
- out.push_back(in[i]+(n?dir:IfcVector3()));
- }
-
- curmesh.vertcnt.push_back(size);
- if(openings && size > 2) {
- if(GenerateOpenings(*conv.apply_openings,nors,temp,true, true, dir)) {
- ++sides_with_v_openings;
- }
-
- result.Append(temp);
- temp.Clear();
- }
- }
- }
-
- if(openings && ((sides_with_openings == 1 && sides_with_openings) || (sides_with_v_openings == 2 && sides_with_v_openings))) {
- IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
- }
-
- IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
-
- // If this is an opening element, store both the extruded mesh and the 2D profile mesh
- // it was created from. Return an empty mesh to the caller.
- if(collect_openings && !result.IsEmpty()) {
- ai_assert(conv.collect_openings);
- boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
- profile->Swap(result);
-
- boost::shared_ptr<TempMesh> profile2D = boost::shared_ptr<TempMesh>(new TempMesh());
- profile2D->Swap(meshout);
- conv.collect_openings->push_back(TempOpening(&solid,dir,profile, profile2D));
-
- ai_assert(result.IsEmpty());
- }
+ TempMesh meshout;
+
+ // First read the profile description.
+ if(!ProcessProfile(*solid.SweptArea,meshout,conv) || meshout.verts.size()<=1) {
+ return;
+ }
+
+ IfcVector3 dir;
+ ConvertDirection(dir,solid.ExtrudedDirection);
+ dir *= solid.Depth;
+
+ // Some profiles bring their own holes, for which we need to provide a container. This all is somewhat backwards,
+ // and there's still so many corner cases uncovered - we really need a generic solution to all of this hole carving.
+ std::vector<TempOpening> fisherPriceMyFirstOpenings;
+ std::vector<TempOpening>* oldApplyOpenings = conv.apply_openings;
+ if( const IfcArbitraryProfileDefWithVoids* const cprofile = solid.SweptArea->ToPtr<IfcArbitraryProfileDefWithVoids>() ) {
+ if( !cprofile->InnerCurves.empty() ) {
+ // read all inner curves and extrude them to form proper openings.
+ std::vector<TempOpening>* oldCollectOpenings = conv.collect_openings;
+ conv.collect_openings = &fisherPriceMyFirstOpenings;
+
+ for(const IfcCurve* curve : cprofile->InnerCurves) {
+ TempMesh curveMesh, tempMesh;
+ ProcessCurve(*curve, curveMesh, conv);
+ ProcessExtrudedArea(solid, curveMesh, dir, tempMesh, conv, true);
+ }
+ // and then apply those to the geometry we're about to generate
+ conv.apply_openings = conv.collect_openings;
+ conv.collect_openings = oldCollectOpenings;
+ }
+ }
+
+ ProcessExtrudedArea(solid, meshout, dir, result, conv, collect_openings);
+ conv.apply_openings = oldApplyOpenings;
}
// ------------------------------------------------------------------------------------------------
-void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
- ConversionData& conv)
+void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
+ ConversionData& conv)
{
- if(const IfcExtrudedAreaSolid* const solid = swept.ToPtr<IfcExtrudedAreaSolid>()) {
- ProcessExtrudedAreaSolid(*solid,meshout,conv, !!conv.collect_openings);
- }
- else if(const IfcRevolvedAreaSolid* const rev = swept.ToPtr<IfcRevolvedAreaSolid>()) {
- ProcessRevolvedAreaSolid(*rev,meshout,conv);
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is " + swept.GetClassName());
- }
+ if(const IfcExtrudedAreaSolid* const solid = swept.ToPtr<IfcExtrudedAreaSolid>()) {
+ ProcessExtrudedAreaSolid(*solid,meshout,conv, !!conv.collect_openings);
+ }
+ else if(const IfcRevolvedAreaSolid* const rev = swept.ToPtr<IfcRevolvedAreaSolid>()) {
+ ProcessRevolvedAreaSolid(*rev,meshout,conv);
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is " + swept.GetClassName());
+ }
}
// ------------------------------------------------------------------------------------------------
-bool ProcessGeometricItem(const IfcRepresentationItem& geo, std::vector<unsigned int>& mesh_indices,
- ConversionData& conv)
+bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid, std::vector<unsigned int>& mesh_indices,
+ ConversionData& conv)
{
- bool fix_orientation = true;
- boost::shared_ptr< TempMesh > meshtmp = boost::make_shared<TempMesh>();
- if(const IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<IfcShellBasedSurfaceModel>()) {
- BOOST_FOREACH(boost::shared_ptr<const IfcShell> shell,shellmod->SbsmBoundary) {
- try {
- const EXPRESS::ENTITY& e = shell->To<ENTITY>();
- const IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<IfcConnectedFaceSet>();
-
- ProcessConnectedFaceSet(fs,*meshtmp.get(),conv);
- }
- catch(std::bad_cast&) {
- IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet");
- }
- }
- }
- else if(const IfcConnectedFaceSet* fset = geo.ToPtr<IfcConnectedFaceSet>()) {
- ProcessConnectedFaceSet(*fset,*meshtmp.get(),conv);
- }
- else if(const IfcSweptAreaSolid* swept = geo.ToPtr<IfcSweptAreaSolid>()) {
- ProcessSweptAreaSolid(*swept,*meshtmp.get(),conv);
- }
- else if(const IfcSweptDiskSolid* disk = geo.ToPtr<IfcSweptDiskSolid>()) {
- ProcessSweptDiskSolid(*disk,*meshtmp.get(),conv);
- fix_orientation = false;
- }
- else if(const IfcManifoldSolidBrep* brep = geo.ToPtr<IfcManifoldSolidBrep>()) {
- ProcessConnectedFaceSet(brep->Outer,*meshtmp.get(),conv);
- }
- else if(const IfcFaceBasedSurfaceModel* surf = geo.ToPtr<IfcFaceBasedSurfaceModel>()) {
- BOOST_FOREACH(const IfcConnectedFaceSet& fc, surf->FbsmFaces) {
- ProcessConnectedFaceSet(fc,*meshtmp.get(),conv);
- }
- }
- else if(const IfcBooleanResult* boolean = geo.ToPtr<IfcBooleanResult>()) {
- ProcessBoolean(*boolean,*meshtmp.get(),conv);
- }
- else if(geo.ToPtr<IfcBoundingBox>()) {
- // silently skip over bounding boxes
- return false;
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is " + geo.GetClassName());
- return false;
- }
-
- // Do we just collect openings for a parent element (i.e. a wall)?
- // In such a case, we generate the polygonal mesh as usual,
- // but attach it to a TempOpening instance which will later be applied
- // to the wall it pertains to.
-
- // Note: swep area solids are added in ProcessExtrudedAreaSolid(),
- // which returns an empty mesh.
- if(conv.collect_openings) {
- if (!meshtmp->IsEmpty()) {
- conv.collect_openings->push_back(TempOpening(geo.ToPtr<IfcSolidModel>(),
- IfcVector3(0,0,0),
- meshtmp,
- boost::shared_ptr<TempMesh>()));
- }
- return true;
- }
-
- if (meshtmp->IsEmpty()) {
- return false;
- }
-
- meshtmp->RemoveAdjacentDuplicates();
- meshtmp->RemoveDegenerates();
-
- if(fix_orientation) {
- meshtmp->FixupFaceOrientation();
- }
-
- aiMesh* const mesh = meshtmp->ToMesh();
- if(mesh) {
- mesh->mMaterialIndex = ProcessMaterials(geo,conv);
- mesh_indices.push_back(conv.meshes.size());
- conv.meshes.push_back(mesh);
- return true;
- }
- return false;
+ bool fix_orientation = false;
+ std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
+ if(const IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<IfcShellBasedSurfaceModel>()) {
+ for(std::shared_ptr<const IfcShell> shell :shellmod->SbsmBoundary) {
+ try {
+ const EXPRESS::ENTITY& e = shell->To<ENTITY>();
+ const IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<IfcConnectedFaceSet>();
+
+ ProcessConnectedFaceSet(fs,*meshtmp.get(),conv);
+ }
+ catch(std::bad_cast&) {
+ IFCImporter::LogWarn("unexpected type error, IfcShell ought to inherit from IfcConnectedFaceSet");
+ }
+ }
+ fix_orientation = true;
+ }
+ else if(const IfcConnectedFaceSet* fset = geo.ToPtr<IfcConnectedFaceSet>()) {
+ ProcessConnectedFaceSet(*fset,*meshtmp.get(),conv);
+ fix_orientation = true;
+ }
+ else if(const IfcSweptAreaSolid* swept = geo.ToPtr<IfcSweptAreaSolid>()) {
+ ProcessSweptAreaSolid(*swept,*meshtmp.get(),conv);
+ }
+ else if(const IfcSweptDiskSolid* disk = geo.ToPtr<IfcSweptDiskSolid>()) {
+ ProcessSweptDiskSolid(*disk,*meshtmp.get(),conv);
+ }
+ else if(const IfcManifoldSolidBrep* brep = geo.ToPtr<IfcManifoldSolidBrep>()) {
+ ProcessConnectedFaceSet(brep->Outer,*meshtmp.get(),conv);
+ fix_orientation = true;
+ }
+ else if(const IfcFaceBasedSurfaceModel* surf = geo.ToPtr<IfcFaceBasedSurfaceModel>()) {
+ for(const IfcConnectedFaceSet& fc : surf->FbsmFaces) {
+ ProcessConnectedFaceSet(fc,*meshtmp.get(),conv);
+ }
+ fix_orientation = true;
+ }
+ else if(const IfcBooleanResult* boolean = geo.ToPtr<IfcBooleanResult>()) {
+ ProcessBoolean(*boolean,*meshtmp.get(),conv);
+ }
+ else if(geo.ToPtr<IfcBoundingBox>()) {
+ // silently skip over bounding boxes
+ return false;
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is " + geo.GetClassName());
+ return false;
+ }
+
+ // Do we just collect openings for a parent element (i.e. a wall)?
+ // In such a case, we generate the polygonal mesh as usual,
+ // but attach it to a TempOpening instance which will later be applied
+ // to the wall it pertains to.
+
+ // Note: swep area solids are added in ProcessExtrudedAreaSolid(),
+ // which returns an empty mesh.
+ if(conv.collect_openings) {
+ if (!meshtmp->IsEmpty()) {
+ conv.collect_openings->push_back(TempOpening(geo.ToPtr<IfcSolidModel>(),
+ IfcVector3(0,0,0),
+ meshtmp,
+ std::shared_ptr<TempMesh>()));
+ }
+ return true;
+ }
+
+ if (meshtmp->IsEmpty()) {
+ return false;
+ }
+
+ meshtmp->RemoveAdjacentDuplicates();
+ meshtmp->RemoveDegenerates();
+
+ if(fix_orientation) {
+// meshtmp->FixupFaceOrientation();
+ }
+
+ aiMesh* const mesh = meshtmp->ToMesh();
+ if(mesh) {
+ mesh->mMaterialIndex = matid;
+ mesh_indices.push_back(conv.meshes.size());
+ conv.meshes.push_back(mesh);
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,
- ConversionData& /*conv*/)
+ ConversionData& /*conv*/)
{
- if (!mesh_indices.empty()) {
+ if (!mesh_indices.empty()) {
- // make unique
- std::sort(mesh_indices.begin(),mesh_indices.end());
- std::vector<unsigned int>::iterator it_end = std::unique(mesh_indices.begin(),mesh_indices.end());
+ // make unique
+ std::sort(mesh_indices.begin(),mesh_indices.end());
+ std::vector<unsigned int>::iterator it_end = std::unique(mesh_indices.begin(),mesh_indices.end());
- const size_t size = std::distance(mesh_indices.begin(),it_end);
+ const size_t size = std::distance(mesh_indices.begin(),it_end);
- nd->mNumMeshes = size;
- nd->mMeshes = new unsigned int[nd->mNumMeshes];
- for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
- nd->mMeshes[i] = mesh_indices[i];
- }
- }
+ nd->mNumMeshes = size;
+ nd->mMeshes = new unsigned int[nd->mNumMeshes];
+ for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
+ nd->mMeshes[i] = mesh_indices[i];
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-bool TryQueryMeshCache(const IfcRepresentationItem& item,
- std::vector<unsigned int>& mesh_indices,
- ConversionData& conv)
+bool TryQueryMeshCache(const IfcRepresentationItem& item,
+ std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
+ ConversionData& conv)
{
- ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(&item);
- if (it != conv.cached_meshes.end()) {
- std::copy((*it).second.begin(),(*it).second.end(),std::back_inserter(mesh_indices));
- return true;
- }
- return false;
+ ConversionData::MeshCacheIndex idx(&item, mat_index);
+ ConversionData::MeshCache::const_iterator it = conv.cached_meshes.find(idx);
+ if (it != conv.cached_meshes.end()) {
+ std::copy((*it).second.begin(),(*it).second.end(),std::back_inserter(mesh_indices));
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
-void PopulateMeshCache(const IfcRepresentationItem& item,
- const std::vector<unsigned int>& mesh_indices,
- ConversionData& conv)
+void PopulateMeshCache(const IfcRepresentationItem& item,
+ const std::vector<unsigned int>& mesh_indices, unsigned int mat_index,
+ ConversionData& conv)
{
- conv.cached_meshes[&item] = mesh_indices;
+ ConversionData::MeshCacheIndex idx(&item, mat_index);
+ conv.cached_meshes[idx] = mesh_indices;
}
// ------------------------------------------------------------------------------------------------
-bool ProcessRepresentationItem(const IfcRepresentationItem& item,
- std::vector<unsigned int>& mesh_indices,
- ConversionData& conv)
+bool ProcessRepresentationItem(const IfcRepresentationItem& item, unsigned int matid,
+ std::vector<unsigned int>& mesh_indices,
+ ConversionData& conv)
{
- if (!TryQueryMeshCache(item,mesh_indices,conv)) {
- if(ProcessGeometricItem(item,mesh_indices,conv)) {
- if(mesh_indices.size()) {
- PopulateMeshCache(item,mesh_indices,conv);
- }
- }
- else return false;
- }
- return true;
+ // determine material
+ unsigned int localmatid = ProcessMaterials(item.GetID(), matid, conv, true);
+
+ if (!TryQueryMeshCache(item,mesh_indices,localmatid,conv)) {
+ if(ProcessGeometricItem(item,localmatid,mesh_indices,conv)) {
+ if(mesh_indices.size()) {
+ PopulateMeshCache(item,mesh_indices,localmatid,conv);
+ }
+ }
+ else return false;
+ }
+ return true;
}
} // ! IFC
} // ! Assimp
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/IFCLoader.cpp b/src/3rdparty/assimp/code/IFCLoader.cpp
index 9963ce70a..34977f5b0 100644
--- a/src/3rdparty/assimp/code/IFCLoader.cpp
+++ b/src/3rdparty/assimp/code/IFCLoader.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,15 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file IFCLoad.cpp
* @brief Implementation of the Industry Foundation Classes loader.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include <iterator>
-#include <boost/tuple/tuple.hpp>
+#include <limits>
+#include <tuple>
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
-# include "../contrib/unzip/unzip.h"
+# include <contrib/unzip/unzip.h>
#endif
#include "IFCLoader.h"
@@ -59,9 +60,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+
namespace Assimp {
- template<> const std::string LogFunctions<IFCImporter>::log_prefix = "IFC: ";
+ template<> const std::string LogFunctions<IFCImporter>::log_prefix = "IFC: ";
}
using namespace Assimp;
@@ -89,24 +93,22 @@ namespace {
void SetUnits(ConversionData& conv);
void SetCoordinateSpace(ConversionData& conv);
void ProcessSpatialStructures(ConversionData& conv);
-aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el ,ConversionData& conv);
-void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, ConversionData& conv);
void MakeTreeRelative(ConversionData& conv);
void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv);
} // anon
static const aiImporterDesc desc = {
- "Industry Foundation Classes (IFC) Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "ifc ifczip"
+ "Industry Foundation Classes (IFC) Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ifc ifczip"
};
@@ -116,35 +118,35 @@ IFCImporter::IFCImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
IFCImporter::~IFCImporter()
{
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string& extension = GetExtension(pFile);
- if (extension == "ifc" || extension == "ifczip") {
- return true;
- }
-
- else if ((!extension.length() || checkSig) && pIOHandler) {
- // note: this is the common identification for STEP-encoded files, so
- // it is only unambiguous as long as we don't support any further
- // file formats with STEP as their encoding.
- const char* tokens[] = {"ISO-10303-21"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string& extension = GetExtension(pFile);
+ if (extension == "ifc" || extension == "ifczip") {
+ return true;
+ }
+
+ else if ((!extension.length() || checkSig) && pIOHandler) {
+ // note: this is the common identification for STEP-encoded files, so
+ // it is only unambiguous as long as we don't support any further
+ // file formats with STEP as their encoding.
+ const char* tokens[] = {"ISO-10303-21"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
const aiImporterDesc* IFCImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
@@ -152,167 +154,167 @@ const aiImporterDesc* IFCImporter::GetInfo () const
// Setup configuration properties for the loader
void IFCImporter::SetupProperties(const Importer* pImp)
{
- settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true);
- settings.skipCurveRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS,true);
- settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true);
+ settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true);
+ settings.skipCurveRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS,true);
+ settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true);
- settings.conicSamplingAngle = 10.f;
- settings.skipAnnotations = true;
+ settings.conicSamplingAngle = 10.f;
+ settings.skipAnnotations = true;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void IFCImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void IFCImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile));
- if (!stream) {
- ThrowException("Could not open file for reading");
- }
+ std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile));
+ if (!stream) {
+ ThrowException("Could not open file for reading");
+ }
- // if this is a ifczip file, decompress its contents first
- if(GetExtension(pFile) == "ifczip") {
+ // if this is a ifczip file, decompress its contents first
+ if(GetExtension(pFile) == "ifczip") {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
- unzFile zip = unzOpen( pFile.c_str() );
- if(zip == NULL) {
- ThrowException("Could not open ifczip file for reading, unzip failed");
- }
-
- // chop 'zip' postfix
- std::string fileName = pFile.substr(0,pFile.length() - 3);
-
- std::string::size_type s = pFile.find_last_of('\\');
- if(s == std::string::npos) {
- s = pFile.find_last_of('/');
- }
- if(s != std::string::npos) {
- fileName = fileName.substr(s+1);
- }
-
- // search file (same name as the IFCZIP except for the file extension) and place file pointer there
- if(UNZ_OK == unzGoToFirstFile(zip)) {
- do {
- // get file size, etc.
- unz_file_info fileInfo;
- char filename[256];
- unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 );
- if (GetExtension(filename) != "ifc") {
- continue;
- }
- uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
- LogInfo("Decompressing IFCZIP file");
- unzOpenCurrentFile( zip );
- const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
- size_t filesize = fileInfo.uncompressed_size;
- if ( ret < 0 || size_t(ret) != filesize )
- {
- delete[] buff;
- ThrowException("Failed to decompress IFC ZIP file");
- }
- unzCloseCurrentFile( zip );
- stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true));
- break;
-
- if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) {
- ThrowException("Found no IFC file member in IFCZIP file (1)");
- }
-
- } while(true);
- }
- else {
- ThrowException("Found no IFC file member in IFCZIP file (2)");
- }
-
- unzClose(zip);
+ unzFile zip = unzOpen( pFile.c_str() );
+ if(zip == NULL) {
+ ThrowException("Could not open ifczip file for reading, unzip failed");
+ }
+
+ // chop 'zip' postfix
+ std::string fileName = pFile.substr(0,pFile.length() - 3);
+
+ std::string::size_type s = pFile.find_last_of('\\');
+ if(s == std::string::npos) {
+ s = pFile.find_last_of('/');
+ }
+ if(s != std::string::npos) {
+ fileName = fileName.substr(s+1);
+ }
+
+ // search file (same name as the IFCZIP except for the file extension) and place file pointer there
+ if(UNZ_OK == unzGoToFirstFile(zip)) {
+ do {
+ // get file size, etc.
+ unz_file_info fileInfo;
+ char filename[256];
+ unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 );
+ if (GetExtension(filename) != "ifc") {
+ continue;
+ }
+ uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
+ LogInfo("Decompressing IFCZIP file");
+ unzOpenCurrentFile( zip );
+ const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
+ size_t filesize = fileInfo.uncompressed_size;
+ if ( ret < 0 || size_t(ret) != filesize )
+ {
+ delete[] buff;
+ ThrowException("Failed to decompress IFC ZIP file");
+ }
+ unzCloseCurrentFile( zip );
+ stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true));
+ break;
+
+ if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) {
+ ThrowException("Found no IFC file member in IFCZIP file (1)");
+ }
+
+ } while(true);
+ }
+ else {
+ ThrowException("Found no IFC file member in IFCZIP file (2)");
+ }
+
+ unzClose(zip);
#else
- ThrowException("Could not open ifczip file for reading, assimp was built without ifczip support");
+ ThrowException("Could not open ifczip file for reading, assimp was built without ifczip support");
#endif
- }
-
- boost::scoped_ptr<STEP::DB> db(STEP::ReadFileHeader(stream));
- const STEP::HeaderInfo& head = static_cast<const STEP::DB&>(*db).GetHeader();
-
- if(!head.fileSchema.size() || head.fileSchema.substr(0,3) != "IFC") {
- ThrowException("Unrecognized file schema: " + head.fileSchema);
- }
-
- if (!DefaultLogger::isNullLogger()) {
- LogDebug("File schema is \'" + head.fileSchema + '\'');
- if (head.timestamp.length()) {
- LogDebug("Timestamp \'" + head.timestamp + '\'');
- }
- if (head.app.length()) {
- LogDebug("Application/Exporter identline is \'" + head.app + '\'');
- }
- }
-
- // obtain a copy of the machine-generated IFC scheme
- EXPRESS::ConversionSchema schema;
- GetSchema(schema);
-
- // tell the reader which entity types to track with special care
- static const char* const types_to_track[] = {
- "ifcsite", "ifcbuilding", "ifcproject"
- };
-
- // tell the reader for which types we need to simulate STEPs reverse indices
- static const char* const inverse_indices_to_track[] = {
- "ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem"
- };
-
- // feed the IFC schema into the reader and pre-parse all lines
- STEP::ReadFile(*db, schema, types_to_track, inverse_indices_to_track);
- const STEP::LazyObject* proj = db->GetObject("ifcproject");
- if (!proj) {
- ThrowException("missing IfcProject entity");
- }
-
- ConversionData conv(*db,proj->To<IfcProject>(),pScene,settings);
- SetUnits(conv);
- SetCoordinateSpace(conv);
- ProcessSpatialStructures(conv);
- MakeTreeRelative(conv);
-
- // NOTE - this is a stress test for the importer, but it works only
- // in a build with no entities disabled. See
- // scripts/IFCImporter/CPPGenerator.py
- // for more information.
- #ifdef ASSIMP_IFC_TEST
- db->EvaluateAll();
- #endif
-
- // do final data copying
- if (conv.meshes.size()) {
- pScene->mNumMeshes = static_cast<unsigned int>(conv.meshes.size());
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
- std::copy(conv.meshes.begin(),conv.meshes.end(),pScene->mMeshes);
-
- // needed to keep the d'tor from burning us
- conv.meshes.clear();
- }
-
- if (conv.materials.size()) {
- pScene->mNumMaterials = static_cast<unsigned int>(conv.materials.size());
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
- std::copy(conv.materials.begin(),conv.materials.end(),pScene->mMaterials);
-
- // needed to keep the d'tor from burning us
- conv.materials.clear();
- }
-
- // apply world coordinate system (which includes the scaling to convert to meters and a -90 degrees rotation around x)
- aiMatrix4x4 scale, rot;
- aiMatrix4x4::Scaling(static_cast<aiVector3D>(IfcVector3(conv.len_scale)),scale);
- aiMatrix4x4::RotationX(-AI_MATH_HALF_PI_F,rot);
-
- pScene->mRootNode->mTransformation = rot * scale * conv.wcs * pScene->mRootNode->mTransformation;
-
- // this must be last because objects are evaluated lazily as we process them
- if ( !DefaultLogger::isNullLogger() ){
- LogDebug((Formatter::format(),"STEP: evaluated ",db->GetEvaluatedObjectCount()," object records"));
- }
+ }
+
+ std::unique_ptr<STEP::DB> db(STEP::ReadFileHeader(stream));
+ const STEP::HeaderInfo& head = static_cast<const STEP::DB&>(*db).GetHeader();
+
+ if(!head.fileSchema.size() || head.fileSchema.substr(0,3) != "IFC") {
+ ThrowException("Unrecognized file schema: " + head.fileSchema);
+ }
+
+ if (!DefaultLogger::isNullLogger()) {
+ LogDebug("File schema is \'" + head.fileSchema + '\'');
+ if (head.timestamp.length()) {
+ LogDebug("Timestamp \'" + head.timestamp + '\'');
+ }
+ if (head.app.length()) {
+ LogDebug("Application/Exporter identline is \'" + head.app + '\'');
+ }
+ }
+
+ // obtain a copy of the machine-generated IFC scheme
+ EXPRESS::ConversionSchema schema;
+ GetSchema(schema);
+
+ // tell the reader which entity types to track with special care
+ static const char* const types_to_track[] = {
+ "ifcsite", "ifcbuilding", "ifcproject"
+ };
+
+ // tell the reader for which types we need to simulate STEPs reverse indices
+ static const char* const inverse_indices_to_track[] = {
+ "ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem"
+ };
+
+ // feed the IFC schema into the reader and pre-parse all lines
+ STEP::ReadFile(*db, schema, types_to_track, inverse_indices_to_track);
+ const STEP::LazyObject* proj = db->GetObject("ifcproject");
+ if (!proj) {
+ ThrowException("missing IfcProject entity");
+ }
+
+ ConversionData conv(*db,proj->To<IfcProject>(),pScene,settings);
+ SetUnits(conv);
+ SetCoordinateSpace(conv);
+ ProcessSpatialStructures(conv);
+ MakeTreeRelative(conv);
+
+ // NOTE - this is a stress test for the importer, but it works only
+ // in a build with no entities disabled. See
+ // scripts/IFCImporter/CPPGenerator.py
+ // for more information.
+ #ifdef ASSIMP_IFC_TEST
+ db->EvaluateAll();
+ #endif
+
+ // do final data copying
+ if (conv.meshes.size()) {
+ pScene->mNumMeshes = static_cast<unsigned int>(conv.meshes.size());
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
+ std::copy(conv.meshes.begin(),conv.meshes.end(),pScene->mMeshes);
+
+ // needed to keep the d'tor from burning us
+ conv.meshes.clear();
+ }
+
+ if (conv.materials.size()) {
+ pScene->mNumMaterials = static_cast<unsigned int>(conv.materials.size());
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
+ std::copy(conv.materials.begin(),conv.materials.end(),pScene->mMaterials);
+
+ // needed to keep the d'tor from burning us
+ conv.materials.clear();
+ }
+
+ // apply world coordinate system (which includes the scaling to convert to meters and a -90 degrees rotation around x)
+ aiMatrix4x4 scale, rot;
+ aiMatrix4x4::Scaling(static_cast<aiVector3D>(IfcVector3(conv.len_scale)),scale);
+ aiMatrix4x4::RotationX(-AI_MATH_HALF_PI_F,rot);
+
+ pScene->mRootNode->mTransformation = rot * scale * conv.wcs * pScene->mRootNode->mTransformation;
+
+ // this must be last because objects are evaluated lazily as we process them
+ if ( !DefaultLogger::isNullLogger() ){
+ LogDebug((Formatter::format(),"STEP: evaluated ",db->GetEvaluatedObjectCount()," object records"));
+ }
}
namespace {
@@ -321,637 +323,635 @@ namespace {
// ------------------------------------------------------------------------------------------------
void ConvertUnit(const IfcNamedUnit& unit,ConversionData& conv)
{
- if(const IfcSIUnit* const si = unit.ToPtr<IfcSIUnit>()) {
-
- if(si->UnitType == "LENGTHUNIT") {
- conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f;
- IFCImporter::LogDebug("got units used for lengths");
- }
- if(si->UnitType == "PLANEANGLEUNIT") {
- if (si->Name != "RADIAN") {
- IFCImporter::LogWarn("expected base unit for angles to be radian");
- }
- }
- }
- else if(const IfcConversionBasedUnit* const convu = unit.ToPtr<IfcConversionBasedUnit>()) {
-
- if(convu->UnitType == "PLANEANGLEUNIT") {
- try {
- conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>();
- ConvertUnit(*convu->ConversionFactor->UnitComponent,conv);
- IFCImporter::LogDebug("got units used for angles");
- }
- catch(std::bad_cast&) {
- IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL");
- }
- }
- }
+ if(const IfcSIUnit* const si = unit.ToPtr<IfcSIUnit>()) {
+
+ if(si->UnitType == "LENGTHUNIT") {
+ conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f;
+ IFCImporter::LogDebug("got units used for lengths");
+ }
+ if(si->UnitType == "PLANEANGLEUNIT") {
+ if (si->Name != "RADIAN") {
+ IFCImporter::LogWarn("expected base unit for angles to be radian");
+ }
+ }
+ }
+ else if(const IfcConversionBasedUnit* const convu = unit.ToPtr<IfcConversionBasedUnit>()) {
+
+ if(convu->UnitType == "PLANEANGLEUNIT") {
+ try {
+ conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>();
+ ConvertUnit(*convu->ConversionFactor->UnitComponent,conv);
+ IFCImporter::LogDebug("got units used for angles");
+ }
+ catch(std::bad_cast&) {
+ IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL");
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv)
{
- try {
- const EXPRESS::ENTITY& e = dt.To<ENTITY>();
-
- const IfcNamedUnit& unit = e.ResolveSelect<IfcNamedUnit>(conv.db);
- if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") {
- return;
- }
-
- ConvertUnit(unit,conv);
- }
- catch(std::bad_cast&) {
- // not entity, somehow
- IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity");
- }
+ try {
+ const EXPRESS::ENTITY& e = dt.To<ENTITY>();
+
+ const IfcNamedUnit& unit = e.ResolveSelect<IfcNamedUnit>(conv.db);
+ if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") {
+ return;
+ }
+
+ ConvertUnit(unit,conv);
+ }
+ catch(std::bad_cast&) {
+ // not entity, somehow
+ IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity");
+ }
}
// ------------------------------------------------------------------------------------------------
void SetUnits(ConversionData& conv)
{
- // see if we can determine the coordinate space used to express.
- for(size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i ) {
- ConvertUnit(*conv.proj.UnitsInContext->Units[i],conv);
- }
+ // see if we can determine the coordinate space used to express.
+ for(size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i ) {
+ ConvertUnit(*conv.proj.UnitsInContext->Units[i],conv);
+ }
}
// ------------------------------------------------------------------------------------------------
void SetCoordinateSpace(ConversionData& conv)
{
- const IfcRepresentationContext* fav = NULL;
- BOOST_FOREACH(const IfcRepresentationContext& v, conv.proj.RepresentationContexts) {
- fav = &v;
- // Model should be the most suitable type of context, hence ignore the others
- if (v.ContextType && v.ContextType.Get() == "Model") {
- break;
- }
- }
- if (fav) {
- if(const IfcGeometricRepresentationContext* const geo = fav->ToPtr<IfcGeometricRepresentationContext>()) {
- ConvertAxisPlacement(conv.wcs, *geo->WorldCoordinateSystem, conv);
- IFCImporter::LogDebug("got world coordinate system");
- }
- }
+ const IfcRepresentationContext* fav = NULL;
+ for(const IfcRepresentationContext& v : conv.proj.RepresentationContexts) {
+ fav = &v;
+ // Model should be the most suitable type of context, hence ignore the others
+ if (v.ContextType && v.ContextType.Get() == "Model") {
+ break;
+ }
+ }
+ if (fav) {
+ if(const IfcGeometricRepresentationContext* const geo = fav->ToPtr<IfcGeometricRepresentationContext>()) {
+ ConvertAxisPlacement(conv.wcs, *geo->WorldCoordinateSystem, conv);
+ IFCImporter::LogDebug("got world coordinate system");
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ResolveObjectPlacement(aiMatrix4x4& m, const IfcObjectPlacement& place, ConversionData& conv)
{
- if (const IfcLocalPlacement* const local = place.ToPtr<IfcLocalPlacement>()){
- IfcMatrix4 tmp;
- ConvertAxisPlacement(tmp, *local->RelativePlacement, conv);
-
- m = static_cast<aiMatrix4x4>(tmp);
-
- if (local->PlacementRelTo) {
- aiMatrix4x4 tmp;
- ResolveObjectPlacement(tmp,local->PlacementRelTo.Get(),conv);
- m = tmp * m;
- }
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName());
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-void GetAbsTransform(aiMatrix4x4& out, const aiNode* nd, ConversionData& conv)
-{
- aiMatrix4x4 t;
- if (nd->mParent) {
- GetAbsTransform(t,nd->mParent,conv);
- }
- out = t*nd->mTransformation;
+ if (const IfcLocalPlacement* const local = place.ToPtr<IfcLocalPlacement>()){
+ IfcMatrix4 tmp;
+ ConvertAxisPlacement(tmp, *local->RelativePlacement, conv);
+
+ m = static_cast<aiMatrix4x4>(tmp);
+
+ if (local->PlacementRelTo) {
+ aiMatrix4x4 tmp;
+ ResolveObjectPlacement(tmp,local->PlacementRelTo.Get(),conv);
+ m = tmp * m;
+ }
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName());
+ }
}
// ------------------------------------------------------------------------------------------------
-bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, ConversionData& conv)
+bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv)
{
- // insert a custom node here, the cartesian transform operator is simply a conventional transformation matrix
- std::auto_ptr<aiNode> nd(new aiNode());
- nd->mName.Set("IfcMappedItem");
-
- // handle the Cartesian operator
- IfcMatrix4 m;
- ConvertTransformOperator(m, *mapped.MappingTarget);
-
- IfcMatrix4 msrc;
- ConvertAxisPlacement(msrc,*mapped.MappingSource->MappingOrigin,conv);
-
- msrc = m*msrc;
-
- std::vector<unsigned int> meshes;
- const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0;
- if (conv.apply_openings) {
- IfcMatrix4 minv = msrc;
- minv.Inverse();
- BOOST_FOREACH(TempOpening& open,*conv.apply_openings){
- open.Transform(minv);
- }
- }
-
- const IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation;
-
- bool got = false;
- BOOST_FOREACH(const IfcRepresentationItem& item, repr.Items) {
- if(!ProcessRepresentationItem(item,meshes,conv)) {
- IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated");
- }
- else got = true;
- }
-
- if (!got) {
- return false;
- }
-
- AssignAddedMeshes(meshes,nd.get(),conv);
- if (conv.collect_openings) {
-
- // if this pass serves us only to collect opening geometry,
- // make sure we transform the TempMesh's which we need to
- // preserve as well.
- if(const size_t diff = conv.collect_openings->size() - old_openings) {
- for(size_t i = 0; i < diff; ++i) {
- (*conv.collect_openings)[old_openings+i].Transform(msrc);
- }
- }
- }
-
- nd->mTransformation = nd_src->mTransformation * static_cast<aiMatrix4x4>( msrc );
- subnodes_src.push_back(nd.release());
-
- return true;
+ // insert a custom node here, the cartesian transform operator is simply a conventional transformation matrix
+ std::unique_ptr<aiNode> nd(new aiNode());
+ nd->mName.Set("IfcMappedItem");
+
+ // handle the Cartesian operator
+ IfcMatrix4 m;
+ ConvertTransformOperator(m, *mapped.MappingTarget);
+
+ IfcMatrix4 msrc;
+ ConvertAxisPlacement(msrc,*mapped.MappingSource->MappingOrigin,conv);
+
+ msrc = m*msrc;
+
+ std::vector<unsigned int> meshes;
+ const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0;
+ if (conv.apply_openings) {
+ IfcMatrix4 minv = msrc;
+ minv.Inverse();
+ for(TempOpening& open :*conv.apply_openings){
+ open.Transform(minv);
+ }
+ }
+
+ unsigned int localmatid = ProcessMaterials(mapped.GetID(),matid,conv,false);
+ const IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation;
+
+ bool got = false;
+ for(const IfcRepresentationItem& item : repr.Items) {
+ if(!ProcessRepresentationItem(item,localmatid,meshes,conv)) {
+ IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated");
+ }
+ else got = true;
+ }
+
+ if (!got) {
+ return false;
+ }
+
+ AssignAddedMeshes(meshes,nd.get(),conv);
+ if (conv.collect_openings) {
+
+ // if this pass serves us only to collect opening geometry,
+ // make sure we transform the TempMesh's which we need to
+ // preserve as well.
+ if(const size_t diff = conv.collect_openings->size() - old_openings) {
+ for(size_t i = 0; i < diff; ++i) {
+ (*conv.collect_openings)[old_openings+i].Transform(msrc);
+ }
+ }
+ }
+
+ nd->mTransformation = nd_src->mTransformation * static_cast<aiMatrix4x4>( msrc );
+ subnodes_src.push_back(nd.release());
+
+ return true;
}
// ------------------------------------------------------------------------------------------------
struct RateRepresentationPredicate {
- int Rate(const IfcRepresentation* r) const {
- // the smaller, the better
-
- if (! r->RepresentationIdentifier) {
- // neutral choice if no extra information is specified
- return 0;
- }
-
-
- const std::string& name = r->RepresentationIdentifier.Get();
- if (name == "MappedRepresentation") {
- if (!r->Items.empty()) {
- // take the first item and base our choice on it
- const IfcMappedItem* const m = r->Items.front()->ToPtr<IfcMappedItem>();
- if (m) {
- return Rate(m->MappingSource->MappedRepresentation);
- }
- }
- return 100;
- }
-
- return Rate(name);
- }
-
- int Rate(const std::string& r) const {
-
-
- if (r == "SolidModel") {
- return -3;
- }
-
- // give strong preference to extruded geometry.
- if (r == "SweptSolid") {
- return -10;
- }
-
- if (r == "Clipping") {
- return -5;
- }
-
- // 'Brep' is difficult to get right due to possible voids in the
- // polygon boundaries, so take it only if we are forced to (i.e.
- // if the only alternative is (non-clipping) boolean operations,
- // which are not supported at all).
- if (r == "Brep") {
- return -2;
- }
-
- // Curves, bounding boxes - those will most likely not be loaded
- // as we can't make any use out of this data. So consider them
- // last.
- if (r == "BoundingBox" || r == "Curve2D") {
- return 100;
- }
- return 0;
- }
-
- bool operator() (const IfcRepresentation* a, const IfcRepresentation* b) const {
- return Rate(a) < Rate(b);
- }
+ int Rate(const IfcRepresentation* r) const {
+ // the smaller, the better
+
+ if (! r->RepresentationIdentifier) {
+ // neutral choice if no extra information is specified
+ return 0;
+ }
+
+
+ const std::string& name = r->RepresentationIdentifier.Get();
+ if (name == "MappedRepresentation") {
+ if (!r->Items.empty()) {
+ // take the first item and base our choice on it
+ const IfcMappedItem* const m = r->Items.front()->ToPtr<IfcMappedItem>();
+ if (m) {
+ return Rate(m->MappingSource->MappedRepresentation);
+ }
+ }
+ return 100;
+ }
+
+ return Rate(name);
+ }
+
+ int Rate(const std::string& r) const {
+
+
+ if (r == "SolidModel") {
+ return -3;
+ }
+
+ // give strong preference to extruded geometry.
+ if (r == "SweptSolid") {
+ return -10;
+ }
+
+ if (r == "Clipping") {
+ return -5;
+ }
+
+ // 'Brep' is difficult to get right due to possible voids in the
+ // polygon boundaries, so take it only if we are forced to (i.e.
+ // if the only alternative is (non-clipping) boolean operations,
+ // which are not supported at all).
+ if (r == "Brep") {
+ return -2;
+ }
+
+ // Curves, bounding boxes - those will most likely not be loaded
+ // as we can't make any use out of this data. So consider them
+ // last.
+ if (r == "BoundingBox" || r == "Curve2D") {
+ return 100;
+ }
+ return 0;
+ }
+
+ bool operator() (const IfcRepresentation* a, const IfcRepresentation* b) const {
+ return Rate(a) < Rate(b);
+ }
};
// ------------------------------------------------------------------------------------------------
void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector< aiNode* >& subnodes, ConversionData& conv)
{
- if(!el.Representation) {
- return;
- }
- std::vector<unsigned int> meshes;
- // we want only one representation type, so bring them in a suitable order (i.e try those
- // that look as if we could read them quickly at first). This way of reading
- // representation is relatively generic and allows the concrete implementations
- // for the different representation types to make some sensible choices what
- // to load and what not to load.
- const STEP::ListOf< STEP::Lazy< IfcRepresentation >, 1, 0 >& src = el.Representation.Get()->Representations;
- std::vector<const IfcRepresentation*> repr_ordered(src.size());
- std::copy(src.begin(),src.end(),repr_ordered.begin());
- std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate());
- BOOST_FOREACH(const IfcRepresentation* repr, repr_ordered) {
- bool res = false;
- BOOST_FOREACH(const IfcRepresentationItem& item, repr->Items) {
- if(const IfcMappedItem* const geo = item.ToPtr<IfcMappedItem>()) {
- res = ProcessMappedItem(*geo,nd,subnodes,conv) || res;
- }
- else {
- res = ProcessRepresentationItem(item,meshes,conv) || res;
- }
- }
- // if we got something meaningful at this point, skip any further representations
- if(res) {
- break;
- }
- }
- AssignAddedMeshes(meshes,nd,conv);
+ if(!el.Representation) {
+ return;
+ }
+
+ // extract Color from metadata, if present
+ unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits<uint32_t>::max(), conv, false);
+ std::vector<unsigned int> meshes;
+
+ // we want only one representation type, so bring them in a suitable order (i.e try those
+ // that look as if we could read them quickly at first). This way of reading
+ // representation is relatively generic and allows the concrete implementations
+ // for the different representation types to make some sensible choices what
+ // to load and what not to load.
+ const STEP::ListOf< STEP::Lazy< IfcRepresentation >, 1, 0 >& src = el.Representation.Get()->Representations;
+ std::vector<const IfcRepresentation*> repr_ordered(src.size());
+ std::copy(src.begin(),src.end(),repr_ordered.begin());
+ std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate());
+ for(const IfcRepresentation* repr : repr_ordered) {
+ bool res = false;
+ for(const IfcRepresentationItem& item : repr->Items) {
+ if(const IfcMappedItem* const geo = item.ToPtr<IfcMappedItem>()) {
+ res = ProcessMappedItem(*geo,nd,subnodes,matid,conv) || res;
+ }
+ else {
+ res = ProcessRepresentationItem(item,matid,meshes,conv) || res;
+ }
+ }
+ // if we got something meaningful at this point, skip any further representations
+ if(res) {
+ break;
+ }
+ }
+ AssignAddedMeshes(meshes,nd,conv);
}
typedef std::map<std::string, std::string> Metadata;
// ------------------------------------------------------------------------------------------------
-void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
- const std::string& prefix = "",
- unsigned int nest = 0)
+void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
+ const std::string& prefix = "",
+ unsigned int nest = 0)
{
- BOOST_FOREACH(const IfcProperty& property, set) {
- const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
- if (const IfcPropertySingleValue* const singleValue = property.ToPtr<IfcPropertySingleValue>()) {
- if (singleValue->NominalValue) {
- if (const EXPRESS::STRING* str = singleValue->NominalValue.Get()->ToPtr<EXPRESS::STRING>()) {
- std::string value = static_cast<std::string>(*str);
- properties[key]=value;
- }
- else if (const EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::REAL>()) {
- float value = static_cast<float>(*val);
- std::stringstream s;
- s << value;
- properties[key]=s.str();
- }
- else if (const EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::INTEGER>()) {
- int64_t value = static_cast<int64_t>(*val);
- std::stringstream s;
- s << value;
- properties[key]=s.str();
- }
- }
- }
- else if (const IfcPropertyListValue* const listValue = property.ToPtr<IfcPropertyListValue>()) {
- std::stringstream ss;
- ss << "[";
- unsigned index=0;
- BOOST_FOREACH(const IfcValue::Out& v, listValue->ListValues) {
- if (!v) continue;
- if (const EXPRESS::STRING* str = v->ToPtr<EXPRESS::STRING>()) {
- std::string value = static_cast<std::string>(*str);
- ss << "'" << value << "'";
- }
- else if (const EXPRESS::REAL* val = v->ToPtr<EXPRESS::REAL>()) {
- float value = static_cast<float>(*val);
- ss << value;
- }
- else if (const EXPRESS::INTEGER* val = v->ToPtr<EXPRESS::INTEGER>()) {
- int64_t value = static_cast<int64_t>(*val);
- ss << value;
- }
- if (index+1<listValue->ListValues.size()) {
- ss << ",";
- }
- index++;
- }
- ss << "]";
- properties[key]=ss.str();
- }
- else if (const IfcComplexProperty* const complexProp = property.ToPtr<IfcComplexProperty>()) {
- if(nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities
- IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property.");
- }
- else {
- ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
- }
- }
- else {
- properties[key]="";
- }
- }
+ for(const IfcProperty& property : set) {
+ const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
+ if (const IfcPropertySingleValue* const singleValue = property.ToPtr<IfcPropertySingleValue>()) {
+ if (singleValue->NominalValue) {
+ if (const EXPRESS::STRING* str = singleValue->NominalValue.Get()->ToPtr<EXPRESS::STRING>()) {
+ std::string value = static_cast<std::string>(*str);
+ properties[key]=value;
+ }
+ else if (const EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::REAL>()) {
+ float value = static_cast<float>(*val);
+ std::stringstream s;
+ s << value;
+ properties[key]=s.str();
+ }
+ else if (const EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::INTEGER>()) {
+ int64_t value = static_cast<int64_t>(*val);
+ std::stringstream s;
+ s << value;
+ properties[key]=s.str();
+ }
+ }
+ }
+ else if (const IfcPropertyListValue* const listValue = property.ToPtr<IfcPropertyListValue>()) {
+ std::stringstream ss;
+ ss << "[";
+ unsigned index=0;
+ for(const IfcValue::Out& v : listValue->ListValues) {
+ if (!v) continue;
+ if (const EXPRESS::STRING* str = v->ToPtr<EXPRESS::STRING>()) {
+ std::string value = static_cast<std::string>(*str);
+ ss << "'" << value << "'";
+ }
+ else if (const EXPRESS::REAL* val = v->ToPtr<EXPRESS::REAL>()) {
+ float value = static_cast<float>(*val);
+ ss << value;
+ }
+ else if (const EXPRESS::INTEGER* val = v->ToPtr<EXPRESS::INTEGER>()) {
+ int64_t value = static_cast<int64_t>(*val);
+ ss << value;
+ }
+ if (index+1<listValue->ListValues.size()) {
+ ss << ",";
+ }
+ index++;
+ }
+ ss << "]";
+ properties[key]=ss.str();
+ }
+ else if (const IfcComplexProperty* const complexProp = property.ToPtr<IfcComplexProperty>()) {
+ if(nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities
+ IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property.");
+ }
+ else {
+ ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
+ }
+ }
+ else {
+ properties[key]="";
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties)
+void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties)
{
- if (const IfcRelDefinesByProperties* const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr<IfcRelDefinesByProperties>()) {
- if (const IfcPropertySet* const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr<IfcPropertySet>()) {
- ProcessMetadata(set->HasProperties, conv, properties);
- }
- }
+ if (const IfcRelDefinesByProperties* const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr<IfcRelDefinesByProperties>()) {
+ if (const IfcPropertySet* const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr<IfcPropertySet>()) {
+ ProcessMetadata(set->HasProperties, conv, properties);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, ConversionData& conv, std::vector<TempOpening>* collect_openings = NULL)
{
- const STEP::DB::RefMap& refs = conv.db.GetRefs();
-
- // skip over space and annotation nodes - usually, these have no meaning in Assimp's context
- if(conv.settings.skipSpaceRepresentations) {
- if(const IfcSpace* const space = el.ToPtr<IfcSpace>()) {
- IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
- return NULL;
- }
- }
-
- if(conv.settings.skipAnnotations) {
- if(const IfcAnnotation* const ann = el.ToPtr<IfcAnnotation>()) {
- IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings");
- return NULL;
- }
- }
-
- // add an output node for this spatial structure
- std::auto_ptr<aiNode> nd(new aiNode());
- nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
- nd->mParent = parent;
-
- conv.already_processed.insert(el.GetID());
-
- // check for node metadata
- STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
- if (children.first!=refs.end()) {
- Metadata properties;
- if (children.first==children.second) {
- // handles single property set
- ProcessMetadata((*children.first).second, conv, properties);
- }
- else {
- // handles multiple property sets (currently all property sets are merged,
- // which may not be the best solution in the long run)
- for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) {
- ProcessMetadata((*it).second, conv, properties);
- }
- }
-
- if (!properties.empty()) {
- aiMetadata* data = new aiMetadata();
- data->mNumProperties = properties.size();
- data->mKeys = new aiString[data->mNumProperties]();
- data->mValues = new aiMetadataEntry[data->mNumProperties]();
-
- unsigned int index = 0;
- BOOST_FOREACH(const Metadata::value_type& kv, properties)
- data->Set(index++, kv.first, aiString(kv.second));
-
- nd->mMetaData = data;
- }
- }
-
- if(el.ObjectPlacement) {
- ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv);
- }
-
- std::vector<TempOpening> openings;
-
- IfcMatrix4 myInv;
- bool didinv = false;
-
- // convert everything contained directly within this structure,
- // this may result in more nodes.
- std::vector< aiNode* > subnodes;
- try {
- // locate aggregates and 'contained-in-here'-elements of this spatial structure and add them in recursively
- // on our way, collect openings in *this* element
- STEP::DB::RefMapRange range = refs.equal_range(el.GetID());
-
- for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
- // skip over meshes that have already been processed before. This is strictly necessary
- // because the reverse indices also include references contained in argument lists and
- // therefore every element has a back-reference hold by its parent.
- if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) {
- continue;
- }
- const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);
-
- // handle regularly-contained elements
- if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
- if(cont->RelatingStructure->GetID() != el.GetID()) {
- continue;
- }
- BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) {
- if(const IfcOpeningElement* const open = pro.ToPtr<IfcOpeningElement>()) {
- // IfcOpeningElement is handled below. Sadly we can't use it here as is:
- // The docs say that opening elements are USUALLY attached to building storey,
- // but we want them for the building elements to which they belong.
- continue;
- }
-
- aiNode* const ndnew = ProcessSpatialStructure(nd.get(),pro,conv,NULL);
- if(ndnew) {
- subnodes.push_back( ndnew );
- }
- }
- }
- // handle openings, which we collect in a list rather than adding them to the node graph
- else if(const IfcRelVoidsElement* const fills = obj->ToPtr<IfcRelVoidsElement>()) {
- if(fills->RelatingBuildingElement->GetID() == el.GetID()) {
- const IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement;
-
- // move opening elements to a separate node since they are semantically different than elements that are just 'contained'
- std::auto_ptr<aiNode> nd_aggr(new aiNode());
- nd_aggr->mName.Set("$RelVoidsElement");
- nd_aggr->mParent = nd.get();
-
- nd_aggr->mTransformation = nd->mTransformation;
-
- std::vector<TempOpening> openings_local;
- aiNode* const ndnew = ProcessSpatialStructure( nd_aggr.get(),open, conv,&openings_local);
- if (ndnew) {
-
- nd_aggr->mNumChildren = 1;
- nd_aggr->mChildren = new aiNode*[1]();
-
-
- nd_aggr->mChildren[0] = ndnew;
-
- if(openings_local.size()) {
- if (!didinv) {
- myInv = aiMatrix4x4(nd->mTransformation ).Inverse();
- didinv = true;
- }
-
- // we need all openings to be in the local space of *this* node, so transform them
- BOOST_FOREACH(TempOpening& op,openings_local) {
- op.Transform( myInv*nd_aggr->mChildren[0]->mTransformation);
- openings.push_back(op);
- }
- }
- subnodes.push_back( nd_aggr.release() );
- }
- }
- }
- }
-
- for(;range.first != range.second; ++range.first) {
- // see note in loop above
- if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) {
- continue;
- }
- if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
- if(aggr->RelatingObject->GetID() != el.GetID()) {
- continue;
- }
-
- // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
- std::auto_ptr<aiNode> nd_aggr(new aiNode());
- nd_aggr->mName.Set("$RelAggregates");
- nd_aggr->mParent = nd.get();
-
- nd_aggr->mTransformation = nd->mTransformation;
-
- nd_aggr->mChildren = new aiNode*[aggr->RelatedObjects.size()]();
- BOOST_FOREACH(const IfcObjectDefinition& def, aggr->RelatedObjects) {
- if(const IfcProduct* const prod = def.ToPtr<IfcProduct>()) {
-
- aiNode* const ndnew = ProcessSpatialStructure(nd_aggr.get(),*prod,conv,NULL);
- if(ndnew) {
- nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
- }
- }
- }
-
- subnodes.push_back( nd_aggr.release() );
- }
- }
-
- conv.collect_openings = collect_openings;
- if(!conv.collect_openings) {
- conv.apply_openings = &openings;
- }
-
- ProcessProductRepresentation(el,nd.get(),subnodes,conv);
- conv.apply_openings = conv.collect_openings = NULL;
-
- if (subnodes.size()) {
- nd->mChildren = new aiNode*[subnodes.size()]();
- BOOST_FOREACH(aiNode* nd2, subnodes) {
- nd->mChildren[nd->mNumChildren++] = nd2;
- nd2->mParent = nd.get();
- }
- }
- }
- catch(...) {
- // it hurts, but I don't want to pull boost::ptr_vector into -noboost only for these few spots here
- std::for_each(subnodes.begin(),subnodes.end(),delete_fun<aiNode>());
- throw;
- }
-
- ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end());
- conv.already_processed.erase(conv.already_processed.find(el.GetID()));
- return nd.release();
+ const STEP::DB::RefMap& refs = conv.db.GetRefs();
+
+ // skip over space and annotation nodes - usually, these have no meaning in Assimp's context
+ bool skipGeometry = false;
+ if(conv.settings.skipSpaceRepresentations) {
+ if(el.ToPtr<IfcSpace>()) {
+ IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
+ skipGeometry = true;
+ }
+ }
+
+ if(conv.settings.skipAnnotations) {
+ if(el.ToPtr<IfcAnnotation>()) {
+ IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings");
+ return NULL;
+ }
+ }
+
+ // add an output node for this spatial structure
+ std::unique_ptr<aiNode> nd(new aiNode());
+ nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
+ nd->mParent = parent;
+
+ conv.already_processed.insert(el.GetID());
+
+ // check for node metadata
+ STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
+ if (children.first!=refs.end()) {
+ Metadata properties;
+ if (children.first==children.second) {
+ // handles single property set
+ ProcessMetadata((*children.first).second, conv, properties);
+ }
+ else {
+ // handles multiple property sets (currently all property sets are merged,
+ // which may not be the best solution in the long run)
+ for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) {
+ ProcessMetadata((*it).second, conv, properties);
+ }
+ }
+
+ if (!properties.empty()) {
+ aiMetadata* data = new aiMetadata();
+ data->mNumProperties = properties.size();
+ data->mKeys = new aiString[data->mNumProperties]();
+ data->mValues = new aiMetadataEntry[data->mNumProperties]();
+
+ unsigned int index = 0;
+ for(const Metadata::value_type& kv : properties)
+ data->Set(index++, kv.first, aiString(kv.second));
+
+ nd->mMetaData = data;
+ }
+ }
+
+ if(el.ObjectPlacement) {
+ ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv);
+ }
+
+ std::vector<TempOpening> openings;
+
+ IfcMatrix4 myInv;
+ bool didinv = false;
+
+ // convert everything contained directly within this structure,
+ // this may result in more nodes.
+ std::vector< aiNode* > subnodes;
+ try {
+ // locate aggregates and 'contained-in-here'-elements of this spatial structure and add them in recursively
+ // on our way, collect openings in *this* element
+ STEP::DB::RefMapRange range = refs.equal_range(el.GetID());
+
+ for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
+ // skip over meshes that have already been processed before. This is strictly necessary
+ // because the reverse indices also include references contained in argument lists and
+ // therefore every element has a back-reference hold by its parent.
+ if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) {
+ continue;
+ }
+ const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);
+
+ // handle regularly-contained elements
+ if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
+ if(cont->RelatingStructure->GetID() != el.GetID()) {
+ continue;
+ }
+ for(const IfcProduct& pro : cont->RelatedElements) {
+ if(pro.ToPtr<IfcOpeningElement>()) {
+ // IfcOpeningElement is handled below. Sadly we can't use it here as is:
+ // The docs say that opening elements are USUALLY attached to building storey,
+ // but we want them for the building elements to which they belong.
+ continue;
+ }
+
+ aiNode* const ndnew = ProcessSpatialStructure(nd.get(),pro,conv,NULL);
+ if(ndnew) {
+ subnodes.push_back( ndnew );
+ }
+ }
+ }
+ // handle openings, which we collect in a list rather than adding them to the node graph
+ else if(const IfcRelVoidsElement* const fills = obj->ToPtr<IfcRelVoidsElement>()) {
+ if(fills->RelatingBuildingElement->GetID() == el.GetID()) {
+ const IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement;
+
+ // move opening elements to a separate node since they are semantically different than elements that are just 'contained'
+ std::unique_ptr<aiNode> nd_aggr(new aiNode());
+ nd_aggr->mName.Set("$RelVoidsElement");
+ nd_aggr->mParent = nd.get();
+
+ nd_aggr->mTransformation = nd->mTransformation;
+
+ std::vector<TempOpening> openings_local;
+ aiNode* const ndnew = ProcessSpatialStructure( nd_aggr.get(),open, conv,&openings_local);
+ if (ndnew) {
+
+ nd_aggr->mNumChildren = 1;
+ nd_aggr->mChildren = new aiNode*[1]();
+
+
+ nd_aggr->mChildren[0] = ndnew;
+
+ if(openings_local.size()) {
+ if (!didinv) {
+ myInv = aiMatrix4x4(nd->mTransformation ).Inverse();
+ didinv = true;
+ }
+
+ // we need all openings to be in the local space of *this* node, so transform them
+ for(TempOpening& op :openings_local) {
+ op.Transform( myInv*nd_aggr->mChildren[0]->mTransformation);
+ openings.push_back(op);
+ }
+ }
+ subnodes.push_back( nd_aggr.release() );
+ }
+ }
+ }
+ }
+
+ for(;range.first != range.second; ++range.first) {
+ // see note in loop above
+ if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) {
+ continue;
+ }
+ if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
+ if(aggr->RelatingObject->GetID() != el.GetID()) {
+ continue;
+ }
+
+ // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
+ std::unique_ptr<aiNode> nd_aggr(new aiNode());
+ nd_aggr->mName.Set("$RelAggregates");
+ nd_aggr->mParent = nd.get();
+
+ nd_aggr->mTransformation = nd->mTransformation;
+
+ nd_aggr->mChildren = new aiNode*[aggr->RelatedObjects.size()]();
+ for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
+ if(const IfcProduct* const prod = def.ToPtr<IfcProduct>()) {
+
+ aiNode* const ndnew = ProcessSpatialStructure(nd_aggr.get(),*prod,conv,NULL);
+ if(ndnew) {
+ nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
+ }
+ }
+ }
+
+ subnodes.push_back( nd_aggr.release() );
+ }
+ }
+
+ conv.collect_openings = collect_openings;
+ if(!conv.collect_openings) {
+ conv.apply_openings = &openings;
+ }
+
+ if (!skipGeometry) {
+ ProcessProductRepresentation(el,nd.get(),subnodes,conv);
+ conv.apply_openings = conv.collect_openings = NULL;
+ }
+
+ if (subnodes.size()) {
+ nd->mChildren = new aiNode*[subnodes.size()]();
+ for(aiNode* nd2 : subnodes) {
+ nd->mChildren[nd->mNumChildren++] = nd2;
+ nd2->mParent = nd.get();
+ }
+ }
+ }
+ catch(...) {
+ // it hurts, but I don't want to pull boost::ptr_vector into -noboost only for these few spots here
+ std::for_each(subnodes.begin(),subnodes.end(),delete_fun<aiNode>());
+ throw;
+ }
+
+ ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end());
+ conv.already_processed.erase(conv.already_processed.find(el.GetID()));
+ return nd.release();
}
// ------------------------------------------------------------------------------------------------
void ProcessSpatialStructures(ConversionData& conv)
{
- // XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX)
-
-
- // process all products in the file. it is reasonable to assume that a
- // file that is relevant for us contains at least a site or a building.
- const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType();
-
- ai_assert(map.find("ifcsite") != map.end());
- const STEP::DB::ObjectSet* range = &map.find("ifcsite")->second;
-
- if (range->empty()) {
- ai_assert(map.find("ifcbuilding") != map.end());
- range = &map.find("ifcbuilding")->second;
- if (range->empty()) {
- // no site, no building - fail;
- IFCImporter::ThrowException("no root element found (expected IfcBuilding or preferably IfcSite)");
- }
- }
-
-
- BOOST_FOREACH(const STEP::LazyObject* lz, *range) {
- const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
- if(!prod) {
- continue;
- }
- IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));
-
- // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT
- const STEP::DB::RefMap& refs = conv.db.GetRefs();
- STEP::DB::RefMapRange range = refs.equal_range(conv.proj.GetID());
- for(;range.first != range.second; ++range.first) {
- if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
-
- BOOST_FOREACH(const IfcObjectDefinition& def, aggr->RelatedObjects) {
- // comparing pointer values is not sufficient, we would need to cast them to the same type first
- // as there is multiple inheritance in the game.
- if (def.GetID() == prod->GetID()) {
- IFCImporter::LogDebug("selecting this spatial structure as root structure");
- // got it, this is the primary site.
- conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
- return;
- }
- }
-
- }
- }
- }
-
-
- IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite");
- BOOST_FOREACH(const STEP::LazyObject* lz, *range) {
- const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
- if(!prod) {
- continue;
- }
-
- conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
- return;
- }
-
- IFCImporter::ThrowException("failed to determine primary site element");
+ // XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX)
+
+
+ // process all products in the file. it is reasonable to assume that a
+ // file that is relevant for us contains at least a site or a building.
+ const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType();
+
+ ai_assert(map.find("ifcsite") != map.end());
+ const STEP::DB::ObjectSet* range = &map.find("ifcsite")->second;
+
+ if (range->empty()) {
+ ai_assert(map.find("ifcbuilding") != map.end());
+ range = &map.find("ifcbuilding")->second;
+ if (range->empty()) {
+ // no site, no building - fail;
+ IFCImporter::ThrowException("no root element found (expected IfcBuilding or preferably IfcSite)");
+ }
+ }
+
+
+ for(const STEP::LazyObject* lz : *range) {
+ const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
+ if(!prod) {
+ continue;
+ }
+ IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));
+
+ // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT
+ const STEP::DB::RefMap& refs = conv.db.GetRefs();
+ STEP::DB::RefMapRange range = refs.equal_range(conv.proj.GetID());
+ for(;range.first != range.second; ++range.first) {
+ if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
+
+ for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
+ // comparing pointer values is not sufficient, we would need to cast them to the same type first
+ // as there is multiple inheritance in the game.
+ if (def.GetID() == prod->GetID()) {
+ IFCImporter::LogDebug("selecting this spatial structure as root structure");
+ // got it, this is the primary site.
+ conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
+ return;
+ }
+ }
+
+ }
+ }
+ }
+
+
+ IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite");
+ for(const STEP::LazyObject* lz : *range) {
+ const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
+ if(!prod) {
+ continue;
+ }
+
+ conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
+ return;
+ }
+
+ IFCImporter::ThrowException("failed to determine primary site element");
}
// ------------------------------------------------------------------------------------------------
void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined)
{
- // combined is the parent's absolute transformation matrix
- const aiMatrix4x4 old = start->mTransformation;
+ // combined is the parent's absolute transformation matrix
+ const aiMatrix4x4 old = start->mTransformation;
- if (!combined.IsIdentity()) {
- start->mTransformation = aiMatrix4x4(combined).Inverse() * start->mTransformation;
- }
+ if (!combined.IsIdentity()) {
+ start->mTransformation = aiMatrix4x4(combined).Inverse() * start->mTransformation;
+ }
- // All nodes store absolute transformations right now, so we need to make them relative
- for (unsigned int i = 0; i < start->mNumChildren; ++i) {
- MakeTreeRelative(start->mChildren[i],old);
- }
+ // All nodes store absolute transformations right now, so we need to make them relative
+ for (unsigned int i = 0; i < start->mNumChildren; ++i) {
+ MakeTreeRelative(start->mChildren[i],old);
+ }
}
// ------------------------------------------------------------------------------------------------
void MakeTreeRelative(ConversionData& conv)
{
- MakeTreeRelative(conv.out->mRootNode,IfcMatrix4());
+ MakeTreeRelative(conv.out->mRootNode,IfcMatrix4());
}
} // !anon
diff --git a/src/3rdparty/assimp/code/IFCLoader.h b/src/3rdparty/assimp/code/IFCLoader.h
index 2aeda9977..e301a329d 100644
--- a/src/3rdparty/assimp/code/IFCLoader.h
+++ b/src/3rdparty/assimp/code/IFCLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,17 +47,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "LogAux.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;
- }
+namespace Assimp {
- namespace STEP {
- class DB;
- }
+ // 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;
+ }
+
+ namespace STEP {
+ class DB;
+ }
// -------------------------------------------------------------------------------------------
@@ -70,61 +70,61 @@ namespace Assimp {
class IFCImporter : public BaseImporter, public LogFunctions<IFCImporter>
{
public:
- IFCImporter();
- ~IFCImporter();
+ IFCImporter();
+ ~IFCImporter();
public:
- // --------------------
- bool CanRead( const std::string& pFile,
- IOSystem* pIOHandler,
- bool checkSig
- ) const;
+ // --------------------
+ bool CanRead( const std::string& pFile,
+ IOSystem* pIOHandler,
+ bool checkSig
+ ) const;
protected:
- // --------------------
- const aiImporterDesc* GetInfo () const;
+ // --------------------
+ const aiImporterDesc* GetInfo () const;
- // --------------------
- void SetupProperties(const Importer* pImp);
+ // --------------------
+ void SetupProperties(const Importer* pImp);
- // --------------------
- void InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler
- );
+ // --------------------
+ void InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler
+ );
private:
-public:
+public:
+
+
+ // loader settings, publicly accessible via their corresponding AI_CONFIG constants
+ struct Settings
+ {
+ Settings()
+ : skipSpaceRepresentations()
+ , skipCurveRepresentations()
+ , useCustomTriangulation()
+ , skipAnnotations()
+ , conicSamplingAngle(10.f)
+ {}
- // loader settings, publicly accessible via their corresponding AI_CONFIG constants
- struct Settings
- {
- Settings()
- : skipSpaceRepresentations()
- , skipCurveRepresentations()
- , useCustomTriangulation()
- , skipAnnotations()
- , conicSamplingAngle(10.f)
- {}
+ bool skipSpaceRepresentations;
+ bool skipCurveRepresentations;
+ bool useCustomTriangulation;
+ bool skipAnnotations;
+ float conicSamplingAngle;
+ };
- bool skipSpaceRepresentations;
- bool skipCurveRepresentations;
- bool useCustomTriangulation;
- bool skipAnnotations;
- float conicSamplingAngle;
- };
-
-
private:
- Settings settings;
+ Settings settings;
}; // !class IFCImporter
diff --git a/src/3rdparty/assimp/code/IFCMaterial.cpp b/src/3rdparty/assimp/code/IFCMaterial.cpp
index 4708cdd84..7525db089 100644
--- a/src/3rdparty/assimp/code/IFCMaterial.cpp
+++ b/src/3rdparty/assimp/code/IFCMaterial.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,135 +42,162 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of conversion routines to convert IFC materials to aiMaterial
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
+#include <limits>
+#include <assimp/material.h>
namespace Assimp {
- namespace IFC {
+ namespace IFC {
// ------------------------------------------------------------------------------------------------
int ConvertShadingMode(const std::string& name)
{
- if (name == "BLINN") {
- return aiShadingMode_Blinn;
- }
- else if (name == "FLAT" || name == "NOTDEFINED") {
- return aiShadingMode_NoShading;
- }
- else if (name == "PHONG") {
- return aiShadingMode_Phong;
- }
- IFCImporter::LogWarn("shading mode "+name+" not recognized by Assimp, using Phong instead");
- return aiShadingMode_Phong;
+ if (name == "BLINN") {
+ return aiShadingMode_Blinn;
+ }
+ else if (name == "FLAT" || name == "NOTDEFINED") {
+ return aiShadingMode_NoShading;
+ }
+ else if (name == "PHONG") {
+ return aiShadingMode_Phong;
+ }
+ IFCImporter::LogWarn("shading mode "+name+" not recognized by Assimp, using Phong instead");
+ return aiShadingMode_Phong;
}
// ------------------------------------------------------------------------------------------------
-void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionData& conv)
+void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionData& conv)
{
- aiString name;
- name.Set((surf->Name? surf->Name.Get() : "IfcSurfaceStyle_Unnamed"));
- mat->AddProperty(&name,AI_MATKEY_NAME);
-
- // now see which kinds of surface information are present
- BOOST_FOREACH(boost::shared_ptr< const IFC::IfcSurfaceStyleElementSelect > sel2, surf->Styles) {
- if (const IFC::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleShading>(conv.db)) {
- aiColor4D col_base,col;
-
- ConvertColor(col_base, shade->SurfaceColour);
- mat->AddProperty(&col_base,1, AI_MATKEY_COLOR_DIFFUSE);
-
- if (const IFC::IfcSurfaceStyleRendering* ren = shade->ToPtr<IFC::IfcSurfaceStyleRendering>()) {
-
- if (ren->Transparency) {
- const float t = 1.f-static_cast<float>(ren->Transparency.Get());
- mat->AddProperty(&t,1, AI_MATKEY_OPACITY);
- }
-
- if (ren->DiffuseColour) {
- ConvertColor(col, *ren->DiffuseColour.Get(),conv,&col_base);
- mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
- }
-
- if (ren->SpecularColour) {
- ConvertColor(col, *ren->SpecularColour.Get(),conv,&col_base);
- mat->AddProperty(&col,1, AI_MATKEY_COLOR_SPECULAR);
- }
-
- if (ren->TransmissionColour) {
- ConvertColor(col, *ren->TransmissionColour.Get(),conv,&col_base);
- mat->AddProperty(&col,1, AI_MATKEY_COLOR_TRANSPARENT);
- }
-
- if (ren->ReflectionColour) {
- ConvertColor(col, *ren->ReflectionColour.Get(),conv,&col_base);
- mat->AddProperty(&col,1, AI_MATKEY_COLOR_REFLECTIVE);
- }
-
- const int shading = (ren->SpecularHighlight && ren->SpecularColour)?ConvertShadingMode(ren->ReflectanceMethod):static_cast<int>(aiShadingMode_Gouraud);
- mat->AddProperty(&shading,1, AI_MATKEY_SHADING_MODEL);
-
- if (ren->SpecularHighlight) {
- if(const EXPRESS::REAL* rt = ren->SpecularHighlight.Get()->ToPtr<EXPRESS::REAL>()) {
- // at this point we don't distinguish between the two distinct ways of
- // specifying highlight intensities. leave this to the user.
- const float e = static_cast<float>(*rt);
- mat->AddProperty(&e,1,AI_MATKEY_SHININESS);
- }
- else {
- IFCImporter::LogWarn("unexpected type error, SpecularHighlight should be a REAL");
- }
- }
- }
- } /*
- else if (const IFC::IfcSurfaceStyleWithTextures* tex = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleWithTextures>(conv.db)) {
- // XXX
- } */
- }
+ aiString name;
+ name.Set((surf->Name? surf->Name.Get() : "IfcSurfaceStyle_Unnamed"));
+ mat->AddProperty(&name,AI_MATKEY_NAME);
+
+ // now see which kinds of surface information are present
+ for(std::shared_ptr< const IFC::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) {
+ if (const IFC::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleShading>(conv.db)) {
+ aiColor4D col_base,col;
+
+ ConvertColor(col_base, shade->SurfaceColour);
+ mat->AddProperty(&col_base,1, AI_MATKEY_COLOR_DIFFUSE);
+
+ if (const IFC::IfcSurfaceStyleRendering* ren = shade->ToPtr<IFC::IfcSurfaceStyleRendering>()) {
+
+ if (ren->Transparency) {
+ const float t = 1.f-static_cast<float>(ren->Transparency.Get());
+ mat->AddProperty(&t,1, AI_MATKEY_OPACITY);
+ }
+
+ if (ren->DiffuseColour) {
+ ConvertColor(col, *ren->DiffuseColour.Get(),conv,&col_base);
+ mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
+ }
+
+ if (ren->SpecularColour) {
+ ConvertColor(col, *ren->SpecularColour.Get(),conv,&col_base);
+ mat->AddProperty(&col,1, AI_MATKEY_COLOR_SPECULAR);
+ }
+
+ if (ren->TransmissionColour) {
+ ConvertColor(col, *ren->TransmissionColour.Get(),conv,&col_base);
+ mat->AddProperty(&col,1, AI_MATKEY_COLOR_TRANSPARENT);
+ }
+
+ if (ren->ReflectionColour) {
+ ConvertColor(col, *ren->ReflectionColour.Get(),conv,&col_base);
+ mat->AddProperty(&col,1, AI_MATKEY_COLOR_REFLECTIVE);
+ }
+
+ const int shading = (ren->SpecularHighlight && ren->SpecularColour)?ConvertShadingMode(ren->ReflectanceMethod):static_cast<int>(aiShadingMode_Gouraud);
+ mat->AddProperty(&shading,1, AI_MATKEY_SHADING_MODEL);
+
+ if (ren->SpecularHighlight) {
+ if(const EXPRESS::REAL* rt = ren->SpecularHighlight.Get()->ToPtr<EXPRESS::REAL>()) {
+ // at this point we don't distinguish between the two distinct ways of
+ // specifying highlight intensities. leave this to the user.
+ const float e = static_cast<float>(*rt);
+ mat->AddProperty(&e,1,AI_MATKEY_SHININESS);
+ }
+ else {
+ IFCImporter::LogWarn("unexpected type error, SpecularHighlight should be a REAL");
+ }
+ }
+ }
+ } /*
+ else if (const IFC::IfcSurfaceStyleWithTextures* tex = sel2->ResolveSelectPtr<IFC::IfcSurfaceStyleWithTextures>(conv.db)) {
+ // XXX
+ } */
+ }
}
// ------------------------------------------------------------------------------------------------
-unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, ConversionData& conv)
+unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat)
{
- if (conv.materials.empty()) {
- aiString name;
- std::auto_ptr<aiMaterial> mat(new aiMaterial());
-
- name.Set("<IFCDefault>");
- mat->AddProperty(&name,AI_MATKEY_NAME);
-
- const aiColor4D col = aiColor4D(0.6f,0.6f,0.6f,1.0f);
- mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
-
- conv.materials.push_back(mat.release());
- }
-
- STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(item.GetID());
- for(;range.first != range.second; ++range.first) {
- if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::IfcStyledItem>()) {
- BOOST_FOREACH(const IFC::IfcPresentationStyleAssignment& as, styled->Styles) {
- BOOST_FOREACH(boost::shared_ptr<const IFC::IfcPresentationStyleSelect> sel, as.Styles) {
-
- if (const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db)) {
- const std::string side = static_cast<std::string>(surf->Side);
- if (side != "BOTH") {
- IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side);
- }
-
- std::auto_ptr<aiMaterial> mat(new aiMaterial());
-
- FillMaterial(mat.get(),surf,conv);
-
- conv.materials.push_back(mat.release());
- return conv.materials.size()-1;
- }
- }
- }
- }
- }
- return 0;
+ STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(id);
+ for(;range.first != range.second; ++range.first) {
+ if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::IfcStyledItem>()) {
+ for(const IFC::IfcPresentationStyleAssignment& as : styled->Styles) {
+ for(std::shared_ptr<const IFC::IfcPresentationStyleSelect> sel : as.Styles) {
+
+ if( const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::IfcSurfaceStyle>(conv.db) ) {
+ // try to satisfy from cache
+ ConversionData::MaterialCache::iterator mit = conv.cached_materials.find(surf);
+ if( mit != conv.cached_materials.end() )
+ return mit->second;
+
+ // not found, create new material
+ const std::string side = static_cast<std::string>(surf->Side);
+ if( side != "BOTH" ) {
+ IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side);
+ }
+
+ std::unique_ptr<aiMaterial> mat(new aiMaterial());
+
+ FillMaterial(mat.get(), surf, conv);
+
+ conv.materials.push_back(mat.release());
+ unsigned int matindex = conv.materials.size() - 1;
+ conv.cached_materials[surf] = matindex;
+ return matindex;
+ }
+ }
+ }
+ }
+ }
+
+ // no local material defined. If there's global one, use that instead
+ if( prevMatId != std::numeric_limits<uint32_t>::max() )
+ return prevMatId;
+
+ // we're still here - create an default material if required, or simply fail otherwise
+ if( !forceDefaultMat )
+ return std::numeric_limits<uint32_t>::max();
+
+ aiString name;
+ name.Set("<IFCDefault>");
+ // ConvertColorToString( color, name);
+
+ // look if there's already a default material with this base color
+ for( size_t a = 0; a < conv.materials.size(); ++a )
+ {
+ aiString mname;
+ conv.materials[a]->Get(AI_MATKEY_NAME, mname);
+ if( name == mname )
+ return (unsigned int)a;
+ }
+
+ // we're here, yet - no default material with suitable color available. Generate one
+ std::unique_ptr<aiMaterial> mat(new aiMaterial());
+ mat->AddProperty(&name,AI_MATKEY_NAME);
+
+ const aiColor4D col = aiColor4D( 0.6f, 0.6f, 0.6f, 1.0f); // aiColor4D( color.r, color.g, color.b, 1.0f);
+ mat->AddProperty(&col,1, AI_MATKEY_COLOR_DIFFUSE);
+
+ conv.materials.push_back(mat.release());
+ return (unsigned int) conv.materials.size() - 1;
}
} // ! IFC
diff --git a/src/3rdparty/assimp/code/IFCOpenings.cpp b/src/3rdparty/assimp/code/IFCOpenings.cpp
index 850403d3b..51ea14314 100644
--- a/src/3rdparty/assimp/code/IFCOpenings.cpp
+++ b/src/3rdparty/assimp/code/IFCOpenings.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2010, 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
+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
@@ -23,27 +23,26 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file IFCOpenings.cpp
- * @brief Implements a subset of Ifc CSG operations for pouring
+ * @brief Implements a subset of Ifc CSG operations for pouring
* holes for windows and doors into walls.
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
@@ -56,21 +55,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iterator>
namespace Assimp {
- namespace IFC {
+ namespace IFC {
- using ClipperLib::ulong64;
- // XXX use full -+ range ...
- const ClipperLib::long64 max_ulong64 = 1518500249; // clipper.cpp / hiRange var
+ using ClipperLib::ulong64;
+ // XXX use full -+ range ...
+ const ClipperLib::long64 max_ulong64 = 1518500249; // clipper.cpp / hiRange var
- //#define to_int64(p) (static_cast<ulong64>( std::max( 0., std::min( static_cast<IfcFloat>((p)), 1.) ) * max_ulong64 ))
+ //#define to_int64(p) (static_cast<ulong64>( std::max( 0., std::min( static_cast<IfcFloat>((p)), 1.) ) * max_ulong64 ))
#define to_int64(p) (static_cast<ulong64>(static_cast<IfcFloat>((p) ) * max_ulong64 ))
#define from_int64(p) (static_cast<IfcFloat>((p)) / max_ulong64)
#define one_vec (IfcVector2(static_cast<IfcFloat>(1.0),static_cast<IfcFloat>(1.0)))
- // fallback method to generate wall openings
- bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
- TempMesh& curmesh);
+ // fallback method to generate wall openings
+ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
+ TempMesh& curmesh);
typedef std::pair< IfcVector2, IfcVector2 > BoundingBox;
@@ -78,95 +77,95 @@ typedef std::map<IfcVector2,size_t,XYSorter> XYSortedField;
// ------------------------------------------------------------------------------------------------
-void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& field,
- const std::vector< BoundingBox >& bbs,
- std::vector<IfcVector2>& out)
+void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField& field,
+ const std::vector< BoundingBox >& bbs,
+ std::vector<IfcVector2>& out)
{
- if (!(pmin.x-pmax.x) || !(pmin.y-pmax.y)) {
- return;
- }
-
- IfcFloat xs = 1e10, xe = 1e10;
- bool found = false;
-
- // Search along the x-axis until we find an opening
- XYSortedField::iterator start = field.begin();
- for(; start != field.end(); ++start) {
- const BoundingBox& bb = bbs[(*start).second];
- if(bb.first.x >= pmax.x) {
- break;
- }
-
- if (bb.second.x > pmin.x && bb.second.y > pmin.y && bb.first.y < pmax.y) {
- xs = bb.first.x;
- xe = bb.second.x;
- found = true;
- break;
- }
- }
-
- if (!found) {
- // the rectangle [pmin,pend] is opaque, fill it
- out.push_back(pmin);
- out.push_back(IfcVector2(pmin.x,pmax.y));
- out.push_back(pmax);
- out.push_back(IfcVector2(pmax.x,pmin.y));
- return;
- }
-
- xs = std::max(pmin.x,xs);
- xe = std::min(pmax.x,xe);
-
- // see if there's an offset to fill at the top of our quad
- if (xs - pmin.x) {
- out.push_back(pmin);
- out.push_back(IfcVector2(pmin.x,pmax.y));
- out.push_back(IfcVector2(xs,pmax.y));
- out.push_back(IfcVector2(xs,pmin.y));
- }
-
- // search along the y-axis for all openings that overlap xs and our quad
- IfcFloat ylast = pmin.y;
- found = false;
- for(; start != field.end(); ++start) {
- const BoundingBox& bb = bbs[(*start).second];
- if (bb.first.x > xs || bb.first.y >= pmax.y) {
- break;
- }
-
- if (bb.second.y > ylast) {
-
- found = true;
- const IfcFloat ys = std::max(bb.first.y,pmin.y), ye = std::min(bb.second.y,pmax.y);
- if (ys - ylast > 0.0f) {
- QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,ys) ,field,bbs,out);
- }
-
- // the following are the window vertices
-
- /*wnd.push_back(IfcVector2(xs,ys));
- wnd.push_back(IfcVector2(xs,ye));
- wnd.push_back(IfcVector2(xe,ye));
- wnd.push_back(IfcVector2(xe,ys));*/
- ylast = ye;
- }
- }
- if (!found) {
- // the rectangle [pmin,pend] is opaque, fill it
- out.push_back(IfcVector2(xs,pmin.y));
- out.push_back(IfcVector2(xs,pmax.y));
- out.push_back(IfcVector2(xe,pmax.y));
- out.push_back(IfcVector2(xe,pmin.y));
- return;
- }
- if (ylast < pmax.y) {
- QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,pmax.y) ,field,bbs,out);
- }
-
- // now for the whole rest
- if (pmax.x-xe) {
- QuadrifyPart(IfcVector2(xe,pmin.y), pmax ,field,bbs,out);
- }
+ if (!(pmin.x-pmax.x) || !(pmin.y-pmax.y)) {
+ return;
+ }
+
+ IfcFloat xs = 1e10, xe = 1e10;
+ bool found = false;
+
+ // Search along the x-axis until we find an opening
+ XYSortedField::iterator start = field.begin();
+ for(; start != field.end(); ++start) {
+ const BoundingBox& bb = bbs[(*start).second];
+ if(bb.first.x >= pmax.x) {
+ break;
+ }
+
+ if (bb.second.x > pmin.x && bb.second.y > pmin.y && bb.first.y < pmax.y) {
+ xs = bb.first.x;
+ xe = bb.second.x;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ // the rectangle [pmin,pend] is opaque, fill it
+ out.push_back(pmin);
+ out.push_back(IfcVector2(pmin.x,pmax.y));
+ out.push_back(pmax);
+ out.push_back(IfcVector2(pmax.x,pmin.y));
+ return;
+ }
+
+ xs = std::max(pmin.x,xs);
+ xe = std::min(pmax.x,xe);
+
+ // see if there's an offset to fill at the top of our quad
+ if (xs - pmin.x) {
+ out.push_back(pmin);
+ out.push_back(IfcVector2(pmin.x,pmax.y));
+ out.push_back(IfcVector2(xs,pmax.y));
+ out.push_back(IfcVector2(xs,pmin.y));
+ }
+
+ // search along the y-axis for all openings that overlap xs and our quad
+ IfcFloat ylast = pmin.y;
+ found = false;
+ for(; start != field.end(); ++start) {
+ const BoundingBox& bb = bbs[(*start).second];
+ if (bb.first.x > xs || bb.first.y >= pmax.y) {
+ break;
+ }
+
+ if (bb.second.y > ylast) {
+
+ found = true;
+ const IfcFloat ys = std::max(bb.first.y,pmin.y), ye = std::min(bb.second.y,pmax.y);
+ if (ys - ylast > 0.0f) {
+ QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,ys) ,field,bbs,out);
+ }
+
+ // the following are the window vertices
+
+ /*wnd.push_back(IfcVector2(xs,ys));
+ wnd.push_back(IfcVector2(xs,ye));
+ wnd.push_back(IfcVector2(xe,ye));
+ wnd.push_back(IfcVector2(xe,ys));*/
+ ylast = ye;
+ }
+ }
+ if (!found) {
+ // the rectangle [pmin,pend] is opaque, fill it
+ out.push_back(IfcVector2(xs,pmin.y));
+ out.push_back(IfcVector2(xs,pmax.y));
+ out.push_back(IfcVector2(xe,pmax.y));
+ out.push_back(IfcVector2(xe,pmin.y));
+ return;
+ }
+ if (ylast < pmax.y) {
+ QuadrifyPart( IfcVector2(xs,ylast), IfcVector2(xe,pmax.y) ,field,bbs,out);
+ }
+
+ // now for the whole rest
+ if (pmax.x-xe) {
+ QuadrifyPart(IfcVector2(xe,pmin.y), pmax ,field,bbs,out);
+ }
}
typedef std::vector<IfcVector2> Contour;
@@ -174,1571 +173,1558 @@ typedef std::vector<bool> SkipList; // should probably use int for performance r
struct ProjectedWindowContour
{
- Contour contour;
- BoundingBox bb;
- SkipList skiplist;
- bool is_rectangular;
+ Contour contour;
+ BoundingBox bb;
+ SkipList skiplist;
+ bool is_rectangular;
- ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular)
- : contour(contour)
- , bb(bb)
- , is_rectangular(is_rectangular)
- {}
+ ProjectedWindowContour(const Contour& contour, const BoundingBox& bb, bool is_rectangular)
+ : contour(contour)
+ , bb(bb)
+ , is_rectangular(is_rectangular)
+ {}
- bool IsInvalid() const {
- return contour.empty();
- }
+ bool IsInvalid() const {
+ return contour.empty();
+ }
- void FlagInvalid() {
- contour.clear();
- }
+ void FlagInvalid() {
+ contour.clear();
+ }
- void PrepareSkiplist() {
- skiplist.resize(contour.size(),false);
- }
+ void PrepareSkiplist() {
+ skiplist.resize(contour.size(),false);
+ }
};
typedef std::vector< ProjectedWindowContour > ContourVector;
// ------------------------------------------------------------------------------------------------
-bool BoundingBoxesOverlapping( const BoundingBox &ibb, const BoundingBox &bb )
+bool BoundingBoxesOverlapping( const BoundingBox &ibb, const BoundingBox &bb )
{
- // count the '=' case as non-overlapping but as adjacent to each other
- return ibb.first.x < bb.second.x && ibb.second.x > bb.first.x &&
- ibb.first.y < bb.second.y && ibb.second.y > bb.first.y;
+ // count the '=' case as non-overlapping but as adjacent to each other
+ return ibb.first.x < bb.second.x && ibb.second.x > bb.first.x &&
+ ibb.first.y < bb.second.y && ibb.second.y > bb.first.y;
}
// ------------------------------------------------------------------------------------------------
bool IsDuplicateVertex(const IfcVector2& vv, const std::vector<IfcVector2>& temp_contour)
{
- // sanity check for duplicate vertices
- BOOST_FOREACH(const IfcVector2& cp, temp_contour) {
- if ((cp-vv).SquareLength() < 1e-5f) {
- return true;
- }
- }
- return false;
+ // sanity check for duplicate vertices
+ for(const IfcVector2& cp : temp_contour) {
+ if ((cp-vv).SquareLength() < 1e-5f) {
+ return true;
+ }
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
-void ExtractVerticesFromClipper(const ClipperLib::Polygon& poly, std::vector<IfcVector2>& temp_contour,
- bool filter_duplicates = false)
+void ExtractVerticesFromClipper(const ClipperLib::Polygon& poly, std::vector<IfcVector2>& temp_contour,
+ bool filter_duplicates = false)
{
- temp_contour.clear();
- BOOST_FOREACH(const ClipperLib::IntPoint& point, poly) {
- IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
- vv = std::max(vv,IfcVector2());
- vv = std::min(vv,one_vec);
-
- if (!filter_duplicates || !IsDuplicateVertex(vv, temp_contour)) {
- temp_contour.push_back(vv);
- }
- }
+ temp_contour.clear();
+ for(const ClipperLib::IntPoint& point : poly) {
+ IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
+ vv = std::max(vv,IfcVector2());
+ vv = std::min(vv,one_vec);
+
+ if (!filter_duplicates || !IsDuplicateVertex(vv, temp_contour)) {
+ temp_contour.push_back(vv);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
{
- IfcVector2 newbb_min, newbb_max;
- MinMaxChooser<IfcVector2>()(newbb_min, newbb_max);
+ IfcVector2 newbb_min, newbb_max;
+ MinMaxChooser<IfcVector2>()(newbb_min, newbb_max);
- BOOST_FOREACH(const ClipperLib::IntPoint& point, poly) {
- IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
+ for(const ClipperLib::IntPoint& point : poly) {
+ IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y));
- // sanity rounding
- vv = std::max(vv,IfcVector2());
- vv = std::min(vv,one_vec);
+ // sanity rounding
+ vv = std::max(vv,IfcVector2());
+ vv = std::min(vv,one_vec);
- newbb_min = std::min(newbb_min,vv);
- newbb_max = std::max(newbb_max,vv);
- }
- return BoundingBox(newbb_min, newbb_max);
+ newbb_min = std::min(newbb_min,vv);
+ newbb_max = std::max(newbb_max,vv);
+ }
+ return BoundingBox(newbb_min, newbb_max);
}
// ------------------------------------------------------------------------------------------------
void InsertWindowContours(const ContourVector& contours,
- const std::vector<TempOpening>& openings,
- TempMesh& curmesh)
+ const std::vector<TempOpening>& /*openings*/,
+ TempMesh& curmesh)
{
- // fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
- for(size_t i = 0; i < contours.size();++i) {
- const BoundingBox& bb = contours[i].bb;
- const std::vector<IfcVector2>& contour = contours[i].contour;
- if(contour.empty()) {
- continue;
- }
-
- // check if we need to do it at all - many windows just fit perfectly into their quadratic holes,
- // i.e. their contours *are* already their bounding boxes.
- if (contour.size() == 4) {
- std::set<IfcVector2,XYSorter> verts;
- for(size_t n = 0; n < 4; ++n) {
- verts.insert(contour[n]);
- }
- const std::set<IfcVector2,XYSorter>::const_iterator end = verts.end();
- if (verts.find(bb.first)!=end && verts.find(bb.second)!=end
- && verts.find(IfcVector2(bb.first.x,bb.second.y))!=end
- && verts.find(IfcVector2(bb.second.x,bb.first.y))!=end
- ) {
- continue;
- }
- }
-
- const IfcFloat diag = (bb.first-bb.second).Length();
- const IfcFloat epsilon = diag/1000.f;
-
- // walk through all contour points and find those that lie on the BB corner
- size_t last_hit = -1, very_first_hit = -1;
- IfcVector2 edge;
- for(size_t n = 0, e=0, size = contour.size();; n=(n+1)%size, ++e) {
-
- // sanity checking
- if (e == size*2) {
- IFCImporter::LogError("encountered unexpected topology while generating window contour");
- break;
- }
-
- const IfcVector2& v = contour[n];
-
- bool hit = false;
- if (std::fabs(v.x-bb.first.x)<epsilon) {
- edge.x = bb.first.x;
- hit = true;
- }
- else if (std::fabs(v.x-bb.second.x)<epsilon) {
- edge.x = bb.second.x;
- hit = true;
- }
-
- if (std::fabs(v.y-bb.first.y)<epsilon) {
- edge.y = bb.first.y;
- hit = true;
- }
- else if (std::fabs(v.y-bb.second.y)<epsilon) {
- edge.y = bb.second.y;
- hit = true;
- }
-
- if (hit) {
- if (last_hit != (size_t)-1) {
-
- const size_t old = curmesh.verts.size();
- size_t cnt = last_hit > n ? size-(last_hit-n) : n-last_hit;
- for(size_t a = last_hit, e = 0; e <= cnt; a=(a+1)%size, ++e) {
- // hack: this is to fix cases where opening contours are self-intersecting.
- // Clipper doesn't produce such polygons, but as soon as we're back in
- // our brave new floating-point world, very small distances are consumed
- // by the maximum available precision, leading to self-intersecting
- // polygons. This fix makes concave windows fail even worse, but
- // anyway, fail is fail.
- if ((contour[a] - edge).SquareLength() > diag*diag*0.7) {
- continue;
- }
- curmesh.verts.push_back(IfcVector3(contour[a].x, contour[a].y, 0.0f));
- }
-
- if (edge != contour[last_hit]) {
-
- IfcVector2 corner = edge;
-
- if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
- corner.x = bb.first.x;
- }
- else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
- corner.x = bb.second.x;
- }
-
- if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
- corner.y = bb.first.y;
- }
- else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
- corner.y = bb.second.y;
- }
-
- curmesh.verts.push_back(IfcVector3(corner.x, corner.y, 0.0f));
- }
- else if (cnt == 1) {
- // avoid degenerate polygons (also known as lines or points)
- curmesh.verts.erase(curmesh.verts.begin()+old,curmesh.verts.end());
- }
-
- if (const size_t d = curmesh.verts.size()-old) {
- curmesh.vertcnt.push_back(d);
- std::reverse(curmesh.verts.rbegin(),curmesh.verts.rbegin()+d);
- }
- if (n == very_first_hit) {
- break;
- }
- }
- else {
- very_first_hit = n;
- }
-
- last_hit = n;
- }
- }
- }
+ // fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
+ for(size_t i = 0; i < contours.size();++i) {
+ const BoundingBox& bb = contours[i].bb;
+ const std::vector<IfcVector2>& contour = contours[i].contour;
+ if(contour.empty()) {
+ continue;
+ }
+
+ // check if we need to do it at all - many windows just fit perfectly into their quadratic holes,
+ // i.e. their contours *are* already their bounding boxes.
+ if (contour.size() == 4) {
+ std::set<IfcVector2,XYSorter> verts;
+ for(size_t n = 0; n < 4; ++n) {
+ verts.insert(contour[n]);
+ }
+ const std::set<IfcVector2,XYSorter>::const_iterator end = verts.end();
+ if (verts.find(bb.first)!=end && verts.find(bb.second)!=end
+ && verts.find(IfcVector2(bb.first.x,bb.second.y))!=end
+ && verts.find(IfcVector2(bb.second.x,bb.first.y))!=end
+ ) {
+ continue;
+ }
+ }
+
+ const IfcFloat diag = (bb.first-bb.second).Length();
+ const IfcFloat epsilon = diag/1000.f;
+
+ // walk through all contour points and find those that lie on the BB corner
+ size_t last_hit = -1, very_first_hit = -1;
+ IfcVector2 edge;
+ for(size_t n = 0, e=0, size = contour.size();; n=(n+1)%size, ++e) {
+
+ // sanity checking
+ if (e == size*2) {
+ IFCImporter::LogError("encountered unexpected topology while generating window contour");
+ break;
+ }
+
+ const IfcVector2& v = contour[n];
+
+ bool hit = false;
+ if (std::fabs(v.x-bb.first.x)<epsilon) {
+ edge.x = bb.first.x;
+ hit = true;
+ }
+ else if (std::fabs(v.x-bb.second.x)<epsilon) {
+ edge.x = bb.second.x;
+ hit = true;
+ }
+
+ if (std::fabs(v.y-bb.first.y)<epsilon) {
+ edge.y = bb.first.y;
+ hit = true;
+ }
+ else if (std::fabs(v.y-bb.second.y)<epsilon) {
+ edge.y = bb.second.y;
+ hit = true;
+ }
+
+ if (hit) {
+ if (last_hit != (size_t)-1) {
+
+ const size_t old = curmesh.verts.size();
+ size_t cnt = last_hit > n ? size-(last_hit-n) : n-last_hit;
+ for(size_t a = last_hit, e = 0; e <= cnt; a=(a+1)%size, ++e) {
+ // hack: this is to fix cases where opening contours are self-intersecting.
+ // Clipper doesn't produce such polygons, but as soon as we're back in
+ // our brave new floating-point world, very small distances are consumed
+ // by the maximum available precision, leading to self-intersecting
+ // polygons. This fix makes concave windows fail even worse, but
+ // anyway, fail is fail.
+ if ((contour[a] - edge).SquareLength() > diag*diag*0.7) {
+ continue;
+ }
+ curmesh.verts.push_back(IfcVector3(contour[a].x, contour[a].y, 0.0f));
+ }
+
+ if (edge != contour[last_hit]) {
+
+ IfcVector2 corner = edge;
+
+ if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
+ corner.x = bb.first.x;
+ }
+ else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
+ corner.x = bb.second.x;
+ }
+
+ if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
+ corner.y = bb.first.y;
+ }
+ else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
+ corner.y = bb.second.y;
+ }
+
+ curmesh.verts.push_back(IfcVector3(corner.x, corner.y, 0.0f));
+ }
+ else if (cnt == 1) {
+ // avoid degenerate polygons (also known as lines or points)
+ curmesh.verts.erase(curmesh.verts.begin()+old,curmesh.verts.end());
+ }
+
+ if (const size_t d = curmesh.verts.size()-old) {
+ curmesh.vertcnt.push_back(d);
+ std::reverse(curmesh.verts.rbegin(),curmesh.verts.rbegin()+d);
+ }
+ if (n == very_first_hit) {
+ break;
+ }
+ }
+ else {
+ very_first_hit = n;
+ }
+
+ last_hit = n;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-void MergeWindowContours (const std::vector<IfcVector2>& a,
- const std::vector<IfcVector2>& b,
- ClipperLib::ExPolygons& out)
+void MergeWindowContours (const std::vector<IfcVector2>& a,
+ const std::vector<IfcVector2>& b,
+ ClipperLib::ExPolygons& out)
{
- out.clear();
+ out.clear();
- ClipperLib::Clipper clipper;
- ClipperLib::Polygon clip;
+ ClipperLib::Clipper clipper;
+ ClipperLib::Polygon clip;
- BOOST_FOREACH(const IfcVector2& pip, a) {
- clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
+ for(const IfcVector2& pip : a) {
+ clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
- if (ClipperLib::Orientation(clip)) {
- std::reverse(clip.begin(), clip.end());
- }
+ if (ClipperLib::Orientation(clip)) {
+ std::reverse(clip.begin(), clip.end());
+ }
- clipper.AddPolygon(clip, ClipperLib::ptSubject);
- clip.clear();
+ clipper.AddPolygon(clip, ClipperLib::ptSubject);
+ clip.clear();
- BOOST_FOREACH(const IfcVector2& pip, b) {
- clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
+ for(const IfcVector2& pip : b) {
+ clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
- if (ClipperLib::Orientation(clip)) {
- std::reverse(clip.begin(), clip.end());
- }
+ if (ClipperLib::Orientation(clip)) {
+ std::reverse(clip.begin(), clip.end());
+ }
- clipper.AddPolygon(clip, ClipperLib::ptSubject);
- clipper.Execute(ClipperLib::ctUnion, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
+ clipper.AddPolygon(clip, ClipperLib::ptSubject);
+ clipper.Execute(ClipperLib::ctUnion, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
}
// ------------------------------------------------------------------------------------------------
// Subtract a from b
-void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
- const std::vector<IfcVector2>& b,
- ClipperLib::ExPolygons& out)
+void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
+ const std::vector<IfcVector2>& b,
+ ClipperLib::ExPolygons& out)
{
- out.clear();
+ out.clear();
- ClipperLib::Clipper clipper;
- ClipperLib::Polygon clip;
+ ClipperLib::Clipper clipper;
+ ClipperLib::Polygon clip;
- BOOST_FOREACH(const IfcVector2& pip, a) {
- clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
+ for(const IfcVector2& pip : a) {
+ clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
- if (ClipperLib::Orientation(clip)) {
- std::reverse(clip.begin(), clip.end());
- }
+ if (ClipperLib::Orientation(clip)) {
+ std::reverse(clip.begin(), clip.end());
+ }
- clipper.AddPolygon(clip, ClipperLib::ptClip);
- clip.clear();
+ clipper.AddPolygon(clip, ClipperLib::ptClip);
+ clip.clear();
- BOOST_FOREACH(const IfcVector2& pip, b) {
- clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
+ for(const IfcVector2& pip : b) {
+ clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
- if (ClipperLib::Orientation(clip)) {
- std::reverse(clip.begin(), clip.end());
- }
+ if (ClipperLib::Orientation(clip)) {
+ std::reverse(clip.begin(), clip.end());
+ }
- clipper.AddPolygon(clip, ClipperLib::ptSubject);
- clipper.Execute(ClipperLib::ctDifference, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
+ clipper.AddPolygon(clip, ClipperLib::ptSubject);
+ clipper.Execute(ClipperLib::ctDifference, out,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
}
// ------------------------------------------------------------------------------------------------
void CleanupWindowContour(ProjectedWindowContour& window)
{
- std::vector<IfcVector2> scratch;
- std::vector<IfcVector2>& contour = window.contour;
+ std::vector<IfcVector2> scratch;
+ std::vector<IfcVector2>& contour = window.contour;
- ClipperLib::Polygon subject;
- ClipperLib::Clipper clipper;
- ClipperLib::ExPolygons clipped;
+ ClipperLib::Polygon subject;
+ ClipperLib::Clipper clipper;
+ ClipperLib::ExPolygons clipped;
- BOOST_FOREACH(const IfcVector2& pip, contour) {
- subject.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
+ for(const IfcVector2& pip : contour) {
+ subject.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
- clipper.AddPolygon(subject,ClipperLib::ptSubject);
- clipper.Execute(ClipperLib::ctUnion,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
+ clipper.AddPolygon(subject,ClipperLib::ptSubject);
+ clipper.Execute(ClipperLib::ctUnion,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
- // This should yield only one polygon or something went wrong
- if (clipped.size() != 1) {
+ // This should yield only one polygon or something went wrong
+ if (clipped.size() != 1) {
- // Empty polygon? drop the contour altogether
- if(clipped.empty()) {
- IFCImporter::LogError("error during polygon clipping, window contour is degenerate");
- window.FlagInvalid();
- return;
- }
+ // Empty polygon? drop the contour altogether
+ if(clipped.empty()) {
+ IFCImporter::LogError("error during polygon clipping, window contour is degenerate");
+ window.FlagInvalid();
+ return;
+ }
- // Else: take the first only
- IFCImporter::LogError("error during polygon clipping, window contour is not convex");
- }
+ // Else: take the first only
+ IFCImporter::LogError("error during polygon clipping, window contour is not convex");
+ }
- ExtractVerticesFromClipper(clipped[0].outer, scratch);
- // Assume the bounding box doesn't change during this operation
+ ExtractVerticesFromClipper(clipped[0].outer, scratch);
+ // Assume the bounding box doesn't change during this operation
}
// ------------------------------------------------------------------------------------------------
void CleanupWindowContours(ContourVector& contours)
{
- // Use PolyClipper to clean up window contours
- try {
- BOOST_FOREACH(ProjectedWindowContour& window, contours) {
- CleanupWindowContour(window);
- }
- }
- catch (const char* sx) {
- IFCImporter::LogError("error during polygon clipping, window shape may be wrong: (Clipper: "
- + std::string(sx) + ")");
- }
+ // Use PolyClipper to clean up window contours
+ try {
+ for(ProjectedWindowContour& window : contours) {
+ CleanupWindowContour(window);
+ }
+ }
+ catch (const char* sx) {
+ IFCImporter::LogError("error during polygon clipping, window shape may be wrong: (Clipper: "
+ + std::string(sx) + ")");
+ }
}
// ------------------------------------------------------------------------------------------------
void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh& curmesh)
{
- std::vector<IfcVector3> vold;
- std::vector<unsigned int> iold;
-
- vold.reserve(curmesh.verts.size());
- iold.reserve(curmesh.vertcnt.size());
-
- // Fix the outer contour using polyclipper
- try {
-
- ClipperLib::Polygon subject;
- ClipperLib::Clipper clipper;
- ClipperLib::ExPolygons clipped;
-
- ClipperLib::Polygon clip;
- clip.reserve(contour_flat.size());
- BOOST_FOREACH(const IfcVector2& pip, contour_flat) {
- clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
-
- if (!ClipperLib::Orientation(clip)) {
- std::reverse(clip.begin(), clip.end());
- }
-
- // We need to run polyclipper on every single polygon -- we can't run it one all
- // of them at once or it would merge them all together which would undo all
- // previous steps
- subject.reserve(4);
- size_t index = 0;
- size_t countdown = 0;
- BOOST_FOREACH(const IfcVector3& pip, curmesh.verts) {
- if (!countdown) {
- countdown = curmesh.vertcnt[index++];
- if (!countdown) {
- continue;
- }
- }
- subject.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- if (--countdown == 0) {
- if (!ClipperLib::Orientation(subject)) {
- std::reverse(subject.begin(), subject.end());
- }
-
- clipper.AddPolygon(subject,ClipperLib::ptSubject);
- clipper.AddPolygon(clip,ClipperLib::ptClip);
-
- clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
-
- BOOST_FOREACH(const ClipperLib::ExPolygon& ex, clipped) {
- iold.push_back(ex.outer.size());
- BOOST_FOREACH(const ClipperLib::IntPoint& point, ex.outer) {
- vold.push_back(IfcVector3(
- from_int64(point.X),
- from_int64(point.Y),
- 0.0f));
- }
- }
-
- subject.clear();
- clipped.clear();
- clipper.Clear();
- }
- }
- }
- catch (const char* sx) {
- IFCImporter::LogError("Ifc: error during polygon clipping, wall contour line may be wrong: (Clipper: "
- + std::string(sx) + ")");
-
- return;
- }
-
- // swap data arrays
- std::swap(vold,curmesh.verts);
- std::swap(iold,curmesh.vertcnt);
+ std::vector<IfcVector3> vold;
+ std::vector<unsigned int> iold;
+
+ vold.reserve(curmesh.verts.size());
+ iold.reserve(curmesh.vertcnt.size());
+
+ // Fix the outer contour using polyclipper
+ try {
+
+ ClipperLib::Polygon subject;
+ ClipperLib::Clipper clipper;
+ ClipperLib::ExPolygons clipped;
+
+ ClipperLib::Polygon clip;
+ clip.reserve(contour_flat.size());
+ for(const IfcVector2& pip : contour_flat) {
+ clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
+
+ if (!ClipperLib::Orientation(clip)) {
+ std::reverse(clip.begin(), clip.end());
+ }
+
+ // We need to run polyclipper on every single polygon -- we can't run it one all
+ // of them at once or it would merge them all together which would undo all
+ // previous steps
+ subject.reserve(4);
+ size_t index = 0;
+ size_t countdown = 0;
+ for(const IfcVector3& pip : curmesh.verts) {
+ if (!countdown) {
+ countdown = curmesh.vertcnt[index++];
+ if (!countdown) {
+ continue;
+ }
+ }
+ subject.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ if (--countdown == 0) {
+ if (!ClipperLib::Orientation(subject)) {
+ std::reverse(subject.begin(), subject.end());
+ }
+
+ clipper.AddPolygon(subject,ClipperLib::ptSubject);
+ clipper.AddPolygon(clip,ClipperLib::ptClip);
+
+ clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero);
+
+ for(const ClipperLib::ExPolygon& ex : clipped) {
+ iold.push_back(ex.outer.size());
+ for(const ClipperLib::IntPoint& point : ex.outer) {
+ vold.push_back(IfcVector3(
+ from_int64(point.X),
+ from_int64(point.Y),
+ 0.0f));
+ }
+ }
+
+ subject.clear();
+ clipped.clear();
+ clipper.Clear();
+ }
+ }
+ }
+ catch (const char* sx) {
+ IFCImporter::LogError("Ifc: error during polygon clipping, wall contour line may be wrong: (Clipper: "
+ + std::string(sx) + ")");
+
+ return;
+ }
+
+ // swap data arrays
+ std::swap(vold,curmesh.verts);
+ std::swap(iold,curmesh.vertcnt);
}
typedef std::vector<TempOpening*> OpeningRefs;
typedef std::vector<OpeningRefs > OpeningRefVector;
typedef std::vector<std::pair<
- ContourVector::const_iterator,
- Contour::const_iterator>
-> ContourRefVector;
+ ContourVector::const_iterator,
+ Contour::const_iterator>
+> ContourRefVector;
// ------------------------------------------------------------------------------------------------
bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
{
- // TODO: I'm pretty sure there is a much more compact way to check this
- const IfcFloat epsilon = 1e-5f;
- return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
- (std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
- (std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
- (std::fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
+ // TODO: I'm pretty sure there is a much more compact way to check this
+ const IfcFloat epsilon = 1e-5f;
+ return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
+ (std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
+ (std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
+ (std::fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
}
// ------------------------------------------------------------------------------------------------
// Check if m0,m1 intersects n0,n1 assuming same ordering of the points in the line segments
// output the intersection points on n0,n1
-bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
- const IfcVector2& m0, const IfcVector2& m1,
- IfcVector2& out0, IfcVector2& out1)
+bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
+ const IfcVector2& m0, const IfcVector2& m1,
+ IfcVector2& out0, IfcVector2& out1)
{
- const IfcVector2& n0_to_n1 = n1 - n0;
-
- const IfcVector2& n0_to_m0 = m0 - n0;
- const IfcVector2& n1_to_m1 = m1 - n1;
-
- const IfcVector2& n0_to_m1 = m1 - n0;
-
- const IfcFloat e = 1e-5f;
- const IfcFloat smalle = 1e-9f;
-
- static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
-
- if (!(n0_to_m0.SquareLength() < e*e || std::fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
- return false;
- }
-
- if (!(n1_to_m1.SquareLength() < e*e || std::fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
- return false;
- }
-
- IfcFloat s0;
- IfcFloat s1;
-
- // pick the axis with the higher absolute difference so the result
- // is more accurate. Since we cannot guarantee that the axis with
- // the higher absolute difference is big enough as to avoid
- // divisions by zero, the case 0/0 ~ infinity is detected and
- // handled separately.
- if(std::fabs(n0_to_n1.x) > std::fabs(n0_to_n1.y)) {
- s0 = n0_to_m0.x / n0_to_n1.x;
- s1 = n0_to_m1.x / n0_to_n1.x;
-
- if (std::fabs(s0) == inf && std::fabs(n0_to_m0.x) < smalle) {
- s0 = 0.;
- }
- if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
- s1 = 0.;
- }
- }
- else {
- s0 = n0_to_m0.y / n0_to_n1.y;
- s1 = n0_to_m1.y / n0_to_n1.y;
-
- if (std::fabs(s0) == inf && std::fabs(n0_to_m0.y) < smalle) {
- s0 = 0.;
- }
- if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
- s1 = 0.;
- }
- }
-
- if (s1 < s0) {
- std::swap(s1,s0);
- }
-
- s0 = std::max(0.0,s0);
- s1 = std::max(0.0,s1);
-
- s0 = std::min(1.0,s0);
- s1 = std::min(1.0,s1);
-
- if (std::fabs(s1-s0) < e) {
- return false;
- }
-
- out0 = n0 + s0 * n0_to_n1;
- out1 = n0 + s1 * n0_to_n1;
-
- return true;
+ const IfcVector2 n0_to_n1 = n1 - n0;
+
+ const IfcVector2 n0_to_m0 = m0 - n0;
+ const IfcVector2 n1_to_m1 = m1 - n1;
+
+ const IfcVector2 n0_to_m1 = m1 - n0;
+
+ const IfcFloat e = 1e-5f;
+ const IfcFloat smalle = 1e-9f;
+
+ static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
+
+ if (!(n0_to_m0.SquareLength() < e*e || std::fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
+ return false;
+ }
+
+ if (!(n1_to_m1.SquareLength() < e*e || std::fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
+ return false;
+ }
+
+ IfcFloat s0;
+ IfcFloat s1;
+
+ // pick the axis with the higher absolute difference so the result
+ // is more accurate. Since we cannot guarantee that the axis with
+ // the higher absolute difference is big enough as to avoid
+ // divisions by zero, the case 0/0 ~ infinity is detected and
+ // handled separately.
+ if(std::fabs(n0_to_n1.x) > std::fabs(n0_to_n1.y)) {
+ s0 = n0_to_m0.x / n0_to_n1.x;
+ s1 = n0_to_m1.x / n0_to_n1.x;
+
+ if (std::fabs(s0) == inf && std::fabs(n0_to_m0.x) < smalle) {
+ s0 = 0.;
+ }
+ if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
+ s1 = 0.;
+ }
+ }
+ else {
+ s0 = n0_to_m0.y / n0_to_n1.y;
+ s1 = n0_to_m1.y / n0_to_n1.y;
+
+ if (std::fabs(s0) == inf && std::fabs(n0_to_m0.y) < smalle) {
+ s0 = 0.;
+ }
+ if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
+ s1 = 0.;
+ }
+ }
+
+ if (s1 < s0) {
+ std::swap(s1,s0);
+ }
+
+ s0 = std::max(0.0,s0);
+ s1 = std::max(0.0,s1);
+
+ s0 = std::min(1.0,s0);
+ s1 = std::min(1.0,s1);
+
+ if (std::fabs(s1-s0) < e) {
+ return false;
+ }
+
+ out0 = n0 + s0 * n0_to_n1;
+ out1 = n0 + s1 * n0_to_n1;
+
+ return true;
}
// ------------------------------------------------------------------------------------------------
void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours)
{
- const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(1e-8);
- const BoundingBox& bb = (*current).bb;
-
- // What is to be done here is to populate the skip lists for the contour
- // and to add necessary padding points when needed.
- SkipList& skiplist = (*current).skiplist;
-
- // First step to find possible adjacent contours is to check for adjacent bounding
- // boxes. If the bounding boxes are not adjacent, the contours lines cannot possibly be.
- for (ContourVector::const_iterator it = contours.begin(), end = contours.end(); it != end; ++it) {
- if ((*it).IsInvalid()) {
- continue;
- }
-
- // this left here to make clear we also run on the current contour
- // to check for overlapping contour segments (which can happen due
- // to projection artifacts).
- //if(it == current) {
- // continue;
- //}
-
- const bool is_me = it == current;
-
- const BoundingBox& ibb = (*it).bb;
-
- // Assumption: the bounding boxes are pairwise disjoint or identical
- ai_assert(is_me || !BoundingBoxesOverlapping(bb, ibb));
-
- if (is_me || BoundingBoxesAdjacent(bb, ibb)) {
-
- // Now do a each-against-everyone check for intersecting contour
- // lines. This obviously scales terribly, but in typical real
- // world Ifc files it will not matter since most windows that
- // are adjacent to each others are rectangular anyway.
-
- Contour& ncontour = (*current).contour;
- const Contour& mcontour = (*it).contour;
-
- for (size_t n = 0; n < ncontour.size(); ++n) {
- const IfcVector2& n0 = ncontour[n];
- const IfcVector2& n1 = ncontour[(n+1) % ncontour.size()];
-
- for (size_t m = 0, mend = (is_me ? n : mcontour.size()); m < mend; ++m) {
- ai_assert(&mcontour != &ncontour || m < n);
-
- const IfcVector2& m0 = mcontour[m];
- const IfcVector2& m1 = mcontour[(m+1) % mcontour.size()];
-
- IfcVector2 isect0, isect1;
- if (IntersectingLineSegments(n0,n1, m0, m1, isect0, isect1)) {
-
- if ((isect0 - n0).SquareLength() > sqlen_epsilon) {
- ++n;
-
- ncontour.insert(ncontour.begin() + n, isect0);
- skiplist.insert(skiplist.begin() + n, true);
- }
- else {
- skiplist[n] = true;
- }
-
- if ((isect1 - n1).SquareLength() > sqlen_epsilon) {
- ++n;
-
- ncontour.insert(ncontour.begin() + n, isect1);
- skiplist.insert(skiplist.begin() + n, false);
- }
- }
- }
- }
- }
- }
+ const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(1e-8);
+ const BoundingBox& bb = (*current).bb;
+
+ // What is to be done here is to populate the skip lists for the contour
+ // and to add necessary padding points when needed.
+ SkipList& skiplist = (*current).skiplist;
+
+ // First step to find possible adjacent contours is to check for adjacent bounding
+ // boxes. If the bounding boxes are not adjacent, the contours lines cannot possibly be.
+ for (ContourVector::const_iterator it = contours.begin(), end = contours.end(); it != end; ++it) {
+ if ((*it).IsInvalid()) {
+ continue;
+ }
+
+ // this left here to make clear we also run on the current contour
+ // to check for overlapping contour segments (which can happen due
+ // to projection artifacts).
+ //if(it == current) {
+ // continue;
+ //}
+
+ const bool is_me = it == current;
+
+ const BoundingBox& ibb = (*it).bb;
+
+ // Assumption: the bounding boxes are pairwise disjoint or identical
+ ai_assert(is_me || !BoundingBoxesOverlapping(bb, ibb));
+
+ if (is_me || BoundingBoxesAdjacent(bb, ibb)) {
+
+ // Now do a each-against-everyone check for intersecting contour
+ // lines. This obviously scales terribly, but in typical real
+ // world Ifc files it will not matter since most windows that
+ // are adjacent to each others are rectangular anyway.
+
+ Contour& ncontour = (*current).contour;
+ const Contour& mcontour = (*it).contour;
+
+ for (size_t n = 0; n < ncontour.size(); ++n) {
+ const IfcVector2& n0 = ncontour[n];
+ const IfcVector2& n1 = ncontour[(n+1) % ncontour.size()];
+
+ for (size_t m = 0, mend = (is_me ? n : mcontour.size()); m < mend; ++m) {
+ ai_assert(&mcontour != &ncontour || m < n);
+
+ const IfcVector2& m0 = mcontour[m];
+ const IfcVector2& m1 = mcontour[(m+1) % mcontour.size()];
+
+ IfcVector2 isect0, isect1;
+ if (IntersectingLineSegments(n0,n1, m0, m1, isect0, isect1)) {
+
+ if ((isect0 - n0).SquareLength() > sqlen_epsilon) {
+ ++n;
+
+ ncontour.insert(ncontour.begin() + n, isect0);
+ skiplist.insert(skiplist.begin() + n, true);
+ }
+ else {
+ skiplist[n] = true;
+ }
+
+ if ((isect1 - n1).SquareLength() > sqlen_epsilon) {
+ ++n;
+
+ ncontour.insert(ncontour.begin() + n, isect1);
+ skiplist.insert(skiplist.begin() + n, false);
+ }
+ }
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
{
- const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
- return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
+ const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
+ return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
}
// ------------------------------------------------------------------------------------------------
void FindBorderContours(ContourVector::iterator current)
{
- const IfcFloat border_epsilon_upper = static_cast<IfcFloat>(1-1e-4);
- const IfcFloat border_epsilon_lower = static_cast<IfcFloat>(1e-4);
-
- bool outer_border = false;
- bool start_on_outer_border = false;
-
- SkipList& skiplist = (*current).skiplist;
- IfcVector2 last_proj_point;
-
- const Contour::const_iterator cbegin = (*current).contour.begin(), cend = (*current).contour.end();
-
- for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
- const IfcVector2& proj_point = *cit;
-
- // Check if this connection is along the outer boundary of the projection
- // plane. In such a case we better drop it because such 'edges' should
- // not have any geometry to close them (think of door openings).
- if (proj_point.x <= border_epsilon_lower || proj_point.x >= border_epsilon_upper ||
- proj_point.y <= border_epsilon_lower || proj_point.y >= border_epsilon_upper) {
-
- if (outer_border) {
- ai_assert(cit != cbegin);
- if (LikelyBorder(proj_point - last_proj_point)) {
- skiplist[std::distance(cbegin, cit) - 1] = true;
- }
- }
- else if (cit == cbegin) {
- start_on_outer_border = true;
- }
-
- outer_border = true;
- }
- else {
- outer_border = false;
- }
-
- last_proj_point = proj_point;
- }
-
- // handle last segment
- if (outer_border && start_on_outer_border) {
- const IfcVector2& proj_point = *cbegin;
- if (LikelyBorder(proj_point - last_proj_point)) {
- skiplist[skiplist.size()-1] = true;
- }
- }
+ const IfcFloat border_epsilon_upper = static_cast<IfcFloat>(1-1e-4);
+ const IfcFloat border_epsilon_lower = static_cast<IfcFloat>(1e-4);
+
+ bool outer_border = false;
+ bool start_on_outer_border = false;
+
+ SkipList& skiplist = (*current).skiplist;
+ IfcVector2 last_proj_point;
+
+ const Contour::const_iterator cbegin = (*current).contour.begin(), cend = (*current).contour.end();
+
+ for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
+ const IfcVector2& proj_point = *cit;
+
+ // Check if this connection is along the outer boundary of the projection
+ // plane. In such a case we better drop it because such 'edges' should
+ // not have any geometry to close them (think of door openings).
+ if (proj_point.x <= border_epsilon_lower || proj_point.x >= border_epsilon_upper ||
+ proj_point.y <= border_epsilon_lower || proj_point.y >= border_epsilon_upper) {
+
+ if (outer_border) {
+ ai_assert(cit != cbegin);
+ if (LikelyBorder(proj_point - last_proj_point)) {
+ skiplist[std::distance(cbegin, cit) - 1] = true;
+ }
+ }
+ else if (cit == cbegin) {
+ start_on_outer_border = true;
+ }
+
+ outer_border = true;
+ }
+ else {
+ outer_border = false;
+ }
+
+ last_proj_point = proj_point;
+ }
+
+ // handle last segment
+ if (outer_border && start_on_outer_border) {
+ const IfcVector2& proj_point = *cbegin;
+ if (LikelyBorder(proj_point - last_proj_point)) {
+ skiplist[skiplist.size()-1] = true;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta)
{
- vdelta.x = std::fabs(vdelta.x);
- vdelta.y = std::fabs(vdelta.y);
- return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
+ vdelta.x = std::fabs(vdelta.x);
+ vdelta.y = std::fabs(vdelta.y);
+ return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
}
// ------------------------------------------------------------------------------------------------
void FindLikelyCrossingLines(ContourVector::iterator current)
{
- SkipList& skiplist = (*current).skiplist;
- IfcVector2 last_proj_point;
-
- const Contour::const_iterator cbegin = (*current).contour.begin(), cend = (*current).contour.end();
- for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
- const IfcVector2& proj_point = *cit;
-
- if (cit != cbegin) {
- IfcVector2 vdelta = proj_point - last_proj_point;
- if (LikelyDiagonal(vdelta)) {
- skiplist[std::distance(cbegin, cit) - 1] = true;
- }
- }
-
- last_proj_point = proj_point;
- }
-
- // handle last segment
- if (LikelyDiagonal(*cbegin - last_proj_point)) {
- skiplist[skiplist.size()-1] = true;
- }
+ SkipList& skiplist = (*current).skiplist;
+ IfcVector2 last_proj_point;
+
+ const Contour::const_iterator cbegin = (*current).contour.begin(), cend = (*current).contour.end();
+ for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
+ const IfcVector2& proj_point = *cit;
+
+ if (cit != cbegin) {
+ IfcVector2 vdelta = proj_point - last_proj_point;
+ if (LikelyDiagonal(vdelta)) {
+ skiplist[std::distance(cbegin, cit) - 1] = true;
+ }
+ }
+
+ last_proj_point = proj_point;
+ }
+
+ // handle last segment
+ if (LikelyDiagonal(*cbegin - last_proj_point)) {
+ skiplist[skiplist.size()-1] = true;
+ }
}
// ------------------------------------------------------------------------------------------------
-size_t CloseWindows(ContourVector& contours,
- const IfcMatrix4& minv,
- OpeningRefVector& contours_to_openings,
- TempMesh& curmesh)
+size_t CloseWindows(ContourVector& contours,
+ const IfcMatrix4& minv,
+ OpeningRefVector& contours_to_openings,
+ TempMesh& curmesh)
{
- size_t closed = 0;
- // For all contour points, check if one of the assigned openings does
- // already have points assigned to it. In this case, assume this is
- // the other side of the wall and generate connections between
- // the two holes in order to close the window.
-
- // All this gets complicated by the fact that contours may pertain to
- // multiple openings(due to merging of adjacent or overlapping openings).
- // The code is based on the assumption that this happens symmetrically
- // on both sides of the wall. If it doesn't (which would be a bug anyway)
- // wrong geometry may be generated.
- for (ContourVector::iterator it = contours.begin(), end = contours.end(); it != end; ++it) {
- if ((*it).IsInvalid()) {
- continue;
- }
- OpeningRefs& refs = contours_to_openings[std::distance(contours.begin(), it)];
-
- bool has_other_side = false;
- BOOST_FOREACH(const TempOpening* opening, refs) {
- if(!opening->wallPoints.empty()) {
- has_other_side = true;
- break;
- }
- }
-
- if (has_other_side) {
-
- ContourRefVector adjacent_contours;
-
- // prepare a skiplist for this contour. The skiplist is used to
- // eliminate unwanted contour lines for adjacent windows and
- // those bordering the outer frame.
- (*it).PrepareSkiplist();
-
- FindAdjacentContours(it, contours);
- FindBorderContours(it);
-
- // if the window is the result of a finite union or intersection of rectangles,
- // there shouldn't be any crossing or diagonal lines in it. Such lines would
- // be artifacts caused by numerical inaccuracies or other bugs in polyclipper
- // and our own code. Since rectangular openings are by far the most frequent
- // case, it is worth filtering for this corner case.
- if((*it).is_rectangular) {
- FindLikelyCrossingLines(it);
- }
-
- ai_assert((*it).skiplist.size() == (*it).contour.size());
-
- SkipList::const_iterator skipbegin = (*it).skiplist.begin();
-
- curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4);
- curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size());
-
- // XXX this algorithm is really a bit inefficient - both in terms
- // of constant factor and of asymptotic runtime.
- std::vector<bool>::const_iterator skipit = skipbegin;
-
- IfcVector3 start0;
- IfcVector3 start1;
-
- IfcVector2 last_proj;
- //const IfcVector2& first_proj;
-
- const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
-
- bool drop_this_edge = false;
- for (Contour::const_iterator cit = cbegin; cit != cend; ++cit, drop_this_edge = *skipit++) {
- const IfcVector2& proj_point = *cit;
-
- // Locate the closest opposite point. This should be a good heuristic to
- // connect only the points that are really intended to be connected.
- IfcFloat best = static_cast<IfcFloat>(1e10);
- IfcVector3 bestv;
-
- /* debug code to check for unwanted diagonal lines in window contours
- if (cit != cbegin) {
- const IfcVector2& vdelta = proj_point - last_proj;
- if (std::fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
- //continue;
- }
- } */
-
- const IfcVector3& world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
-
- last_proj = proj_point;
-
- BOOST_FOREACH(const TempOpening* opening, refs) {
- BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) {
- const IfcFloat sqdist = (world_point - other).SquareLength();
-
- if (sqdist < best) {
- // avoid self-connections
- if(sqdist < 1e-5) {
- continue;
- }
-
- bestv = other;
- best = sqdist;
- }
- }
- }
-
- if (drop_this_edge) {
- curmesh.verts.pop_back();
- curmesh.verts.pop_back();
- }
- else {
- curmesh.verts.push_back(cit == cbegin ? world_point : bestv);
- curmesh.verts.push_back(cit == cbegin ? bestv : world_point);
-
- curmesh.vertcnt.push_back(4);
- ++closed;
- }
-
- if (cit == cbegin) {
- start0 = world_point;
- start1 = bestv;
- continue;
- }
-
- curmesh.verts.push_back(world_point);
- curmesh.verts.push_back(bestv);
-
- if (cit == cend - 1) {
- drop_this_edge = *skipit;
-
- // Check if the final connection (last to first element) is itself
- // a border edge that needs to be dropped.
- if (drop_this_edge) {
- --closed;
- curmesh.vertcnt.pop_back();
- curmesh.verts.pop_back();
- curmesh.verts.pop_back();
- }
- else {
- curmesh.verts.push_back(start1);
- curmesh.verts.push_back(start0);
- }
- }
- }
- /*
- BOOST_FOREACH(TempOpening* opening, refs) {
- //opening->wallPoints.clear();
- }*/
-
- }
- else {
-
- const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
- BOOST_FOREACH(TempOpening* opening, refs) {
- ai_assert(opening->wallPoints.empty());
- opening->wallPoints.reserve(opening->wallPoints.capacity() + (*it).contour.size());
- for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
-
- const IfcVector2& proj_point = *cit;
- opening->wallPoints.push_back(minv * IfcVector3(proj_point.x,proj_point.y,0.0f));
- }
- }
- }
- }
- return closed;
+ size_t closed = 0;
+ // For all contour points, check if one of the assigned openings does
+ // already have points assigned to it. In this case, assume this is
+ // the other side of the wall and generate connections between
+ // the two holes in order to close the window.
+
+ // All this gets complicated by the fact that contours may pertain to
+ // multiple openings(due to merging of adjacent or overlapping openings).
+ // The code is based on the assumption that this happens symmetrically
+ // on both sides of the wall. If it doesn't (which would be a bug anyway)
+ // wrong geometry may be generated.
+ for (ContourVector::iterator it = contours.begin(), end = contours.end(); it != end; ++it) {
+ if ((*it).IsInvalid()) {
+ continue;
+ }
+ OpeningRefs& refs = contours_to_openings[std::distance(contours.begin(), it)];
+
+ bool has_other_side = false;
+ for(const TempOpening* opening : refs) {
+ if(!opening->wallPoints.empty()) {
+ has_other_side = true;
+ break;
+ }
+ }
+
+ if (has_other_side) {
+
+ ContourRefVector adjacent_contours;
+
+ // prepare a skiplist for this contour. The skiplist is used to
+ // eliminate unwanted contour lines for adjacent windows and
+ // those bordering the outer frame.
+ (*it).PrepareSkiplist();
+
+ FindAdjacentContours(it, contours);
+ FindBorderContours(it);
+
+ // if the window is the result of a finite union or intersection of rectangles,
+ // there shouldn't be any crossing or diagonal lines in it. Such lines would
+ // be artifacts caused by numerical inaccuracies or other bugs in polyclipper
+ // and our own code. Since rectangular openings are by far the most frequent
+ // case, it is worth filtering for this corner case.
+ if((*it).is_rectangular) {
+ FindLikelyCrossingLines(it);
+ }
+
+ ai_assert((*it).skiplist.size() == (*it).contour.size());
+
+ SkipList::const_iterator skipbegin = (*it).skiplist.begin();
+
+ curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4);
+ curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size());
+
+ // compare base poly normal and contour normal to detect if we need to reverse the face winding
+ IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal( curmesh.verts.data(), curmesh.vertcnt.front());
+ std::vector<IfcVector3> worldSpaceContourVtx( it->contour.size());
+ for( size_t a = 0; a < it->contour.size(); ++a )
+ worldSpaceContourVtx[a] = minv * IfcVector3( it->contour[a].x, it->contour[a].y, 0.0);
+ IfcVector3 contourNormal = TempMesh::ComputePolygonNormal( worldSpaceContourVtx.data(), worldSpaceContourVtx.size());
+ bool reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0;
+
+ // XXX this algorithm is really a bit inefficient - both in terms
+ // of constant factor and of asymptotic runtime.
+ std::vector<bool>::const_iterator skipit = skipbegin;
+
+ IfcVector3 start0;
+ IfcVector3 start1;
+
+ const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
+
+ bool drop_this_edge = false;
+ for (Contour::const_iterator cit = cbegin; cit != cend; ++cit, drop_this_edge = *skipit++) {
+ const IfcVector2& proj_point = *cit;
+
+ // Locate the closest opposite point. This should be a good heuristic to
+ // connect only the points that are really intended to be connected.
+ IfcFloat best = static_cast<IfcFloat>(1e10);
+ IfcVector3 bestv;
+
+ const IfcVector3 world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f);
+
+ for(const TempOpening* opening : refs) {
+ for(const IfcVector3& other : opening->wallPoints) {
+ const IfcFloat sqdist = (world_point - other).SquareLength();
+
+ if (sqdist < best) {
+ // avoid self-connections
+ if(sqdist < 1e-5) {
+ continue;
+ }
+
+ bestv = other;
+ best = sqdist;
+ }
+ }
+ }
+
+ if (drop_this_edge) {
+ curmesh.verts.pop_back();
+ curmesh.verts.pop_back();
+ }
+ else {
+ curmesh.verts.push_back(((cit == cbegin) != reverseCountourFaces) ? world_point : bestv);
+ curmesh.verts.push_back(((cit == cbegin) != reverseCountourFaces) ? bestv : world_point);
+
+ curmesh.vertcnt.push_back(4);
+ ++closed;
+ }
+
+ if (cit == cbegin) {
+ start0 = world_point;
+ start1 = bestv;
+ continue;
+ }
+
+ curmesh.verts.push_back(reverseCountourFaces ? bestv : world_point);
+ curmesh.verts.push_back(reverseCountourFaces ? world_point : bestv);
+
+ if (cit == cend - 1) {
+ drop_this_edge = *skipit;
+
+ // Check if the final connection (last to first element) is itself
+ // a border edge that needs to be dropped.
+ if (drop_this_edge) {
+ --closed;
+ curmesh.vertcnt.pop_back();
+ curmesh.verts.pop_back();
+ curmesh.verts.pop_back();
+ }
+ else {
+ curmesh.verts.push_back(reverseCountourFaces ? start0 : start1);
+ curmesh.verts.push_back(reverseCountourFaces ? start1 : start0);
+ }
+ }
+ }
+ }
+ else {
+
+ const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end();
+ for(TempOpening* opening : refs) {
+ ai_assert(opening->wallPoints.empty());
+ opening->wallPoints.reserve(opening->wallPoints.capacity() + (*it).contour.size());
+ for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) {
+
+ const IfcVector2& proj_point = *cit;
+ opening->wallPoints.push_back(minv * IfcVector3(proj_point.x,proj_point.y,0.0f));
+ }
+ }
+ }
+ }
+ return closed;
}
// ------------------------------------------------------------------------------------------------
void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh)
{
- ai_assert(curmesh.IsEmpty());
-
- std::vector<IfcVector2> quads;
- quads.reserve(bbs.size()*4);
-
- // sort openings by x and y axis as a preliminiary to the QuadrifyPart() algorithm
- XYSortedField field;
- for (std::vector<BoundingBox>::const_iterator it = bbs.begin(); it != bbs.end(); ++it) {
- if (field.find((*it).first) != field.end()) {
- IFCImporter::LogWarn("constraint failure during generation of wall openings, results may be faulty");
- }
- field[(*it).first] = std::distance(bbs.begin(),it);
- }
-
- QuadrifyPart(IfcVector2(),one_vec,field,bbs,quads);
- ai_assert(!(quads.size() % 4));
-
- curmesh.vertcnt.resize(quads.size()/4,4);
- curmesh.verts.reserve(quads.size());
- BOOST_FOREACH(const IfcVector2& v2, quads) {
- curmesh.verts.push_back(IfcVector3(v2.x, v2.y, static_cast<IfcFloat>(0.0)));
- }
+ ai_assert(curmesh.IsEmpty());
+
+ std::vector<IfcVector2> quads;
+ quads.reserve(bbs.size()*4);
+
+ // sort openings by x and y axis as a preliminiary to the QuadrifyPart() algorithm
+ XYSortedField field;
+ for (std::vector<BoundingBox>::const_iterator it = bbs.begin(); it != bbs.end(); ++it) {
+ if (field.find((*it).first) != field.end()) {
+ IFCImporter::LogWarn("constraint failure during generation of wall openings, results may be faulty");
+ }
+ field[(*it).first] = std::distance(bbs.begin(),it);
+ }
+
+ QuadrifyPart(IfcVector2(),one_vec,field,bbs,quads);
+ ai_assert(!(quads.size() % 4));
+
+ curmesh.vertcnt.resize(quads.size()/4,4);
+ curmesh.verts.reserve(quads.size());
+ for(const IfcVector2& v2 : quads) {
+ curmesh.verts.push_back(IfcVector3(v2.x, v2.y, static_cast<IfcFloat>(0.0)));
+ }
}
// ------------------------------------------------------------------------------------------------
void Quadrify(const ContourVector& contours, TempMesh& curmesh)
{
- std::vector<BoundingBox> bbs;
- bbs.reserve(contours.size());
+ std::vector<BoundingBox> bbs;
+ bbs.reserve(contours.size());
- BOOST_FOREACH(const ContourVector::value_type& val, contours) {
- bbs.push_back(val.bb);
- }
+ for(const ContourVector::value_type& val : contours) {
+ bbs.push_back(val.bb);
+ }
- Quadrify(bbs, curmesh);
+ Quadrify(bbs, curmesh);
}
// ------------------------------------------------------------------------------------------------
-IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh& in_mesh,
- bool &ok, IfcVector3& nor_out)
+IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh& in_mesh,
+ bool &ok, IfcVector3& nor_out)
{
- const std::vector<IfcVector3>& in_verts = in_mesh.verts;
- ok = true;
+ const std::vector<IfcVector3>& in_verts = in_mesh.verts;
+ ok = true;
- IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(in_mesh, ok, nor_out));
- if(!ok) {
- return IfcMatrix4();
- }
+ IfcMatrix4 m = IfcMatrix4(DerivePlaneCoordinateSpace(in_mesh, ok, nor_out));
+ if(!ok) {
+ return IfcMatrix4();
+ }
#ifdef ASSIMP_BUILD_DEBUG
- const IfcFloat det = m.Determinant();
- ai_assert(std::fabs(det-1) < 1e-5);
+ const IfcFloat det = m.Determinant();
+ ai_assert(std::fabs(det-1) < 1e-5);
#endif
- IfcFloat zcoord = 0;
- out_contour.reserve(in_verts.size());
-
-
- IfcVector3 vmin, vmax;
- MinMaxChooser<IfcVector3>()(vmin, vmax);
-
- // Project all points into the new coordinate system, collect min/max verts on the way
- BOOST_FOREACH(const IfcVector3& x, in_verts) {
- const IfcVector3& vv = m * x;
- // keep Z offset in the plane coordinate system. Ignoring precision issues
- // (which are present, of course), this should be the same value for
- // all polygon vertices (assuming the polygon is planar).
-
- // XXX this should be guarded, but we somehow need to pick a suitable
- // epsilon
- // if(coord != -1.0f) {
- // assert(std::fabs(coord - vv.z) < 1e-3f);
- // }
- zcoord += vv.z;
- vmin = std::min(vv, vmin);
- vmax = std::max(vv, vmax);
-
- out_contour.push_back(IfcVector2(vv.x,vv.y));
- }
-
- zcoord /= in_verts.size();
-
- // Further improve the projection by mapping the entire working set into
- // [0,1] range. This gives us a consistent data range so all epsilons
- // used below can be constants.
- vmax -= vmin;
- BOOST_FOREACH(IfcVector2& vv, out_contour) {
- vv.x = (vv.x - vmin.x) / vmax.x;
- vv.y = (vv.y - vmin.y) / vmax.y;
-
- // sanity rounding
- vv = std::max(vv,IfcVector2());
- vv = std::min(vv,one_vec);
- }
-
- IfcMatrix4 mult;
- mult.a1 = static_cast<IfcFloat>(1.0) / vmax.x;
- mult.b2 = static_cast<IfcFloat>(1.0) / vmax.y;
-
- mult.a4 = -vmin.x * mult.a1;
- mult.b4 = -vmin.y * mult.b2;
- mult.c4 = -zcoord;
- m = mult * m;
-
- // debug code to verify correctness
+ IfcFloat zcoord = 0;
+ out_contour.reserve(in_verts.size());
+
+
+ IfcVector3 vmin, vmax;
+ MinMaxChooser<IfcVector3>()(vmin, vmax);
+
+ // Project all points into the new coordinate system, collect min/max verts on the way
+ for(const IfcVector3& x : in_verts) {
+ const IfcVector3 vv = m * x;
+ // keep Z offset in the plane coordinate system. Ignoring precision issues
+ // (which are present, of course), this should be the same value for
+ // all polygon vertices (assuming the polygon is planar).
+
+ // XXX this should be guarded, but we somehow need to pick a suitable
+ // epsilon
+ // if(coord != -1.0f) {
+ // assert(std::fabs(coord - vv.z) < 1e-3f);
+ // }
+ zcoord += vv.z;
+ vmin = std::min(vv, vmin);
+ vmax = std::max(vv, vmax);
+
+ out_contour.push_back(IfcVector2(vv.x,vv.y));
+ }
+
+ zcoord /= in_verts.size();
+
+ // Further improve the projection by mapping the entire working set into
+ // [0,1] range. This gives us a consistent data range so all epsilons
+ // used below can be constants.
+ vmax -= vmin;
+ for(IfcVector2& vv : out_contour) {
+ vv.x = (vv.x - vmin.x) / vmax.x;
+ vv.y = (vv.y - vmin.y) / vmax.y;
+
+ // sanity rounding
+ vv = std::max(vv,IfcVector2());
+ vv = std::min(vv,one_vec);
+ }
+
+ IfcMatrix4 mult;
+ mult.a1 = static_cast<IfcFloat>(1.0) / vmax.x;
+ mult.b2 = static_cast<IfcFloat>(1.0) / vmax.y;
+
+ mult.a4 = -vmin.x * mult.a1;
+ mult.b4 = -vmin.y * mult.b2;
+ mult.c4 = -zcoord;
+ m = mult * m;
+
+ // debug code to verify correctness
#ifdef ASSIMP_BUILD_DEBUG
- std::vector<IfcVector2> out_contour2;
- BOOST_FOREACH(const IfcVector3& x, in_verts) {
- const IfcVector3& vv = m * x;
+ std::vector<IfcVector2> out_contour2;
+ for(const IfcVector3& x : in_verts) {
+ const IfcVector3& vv = m * x;
- out_contour2.push_back(IfcVector2(vv.x,vv.y));
- ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
- }
+ out_contour2.push_back(IfcVector2(vv.x,vv.y));
+ ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
+ }
- for(size_t i = 0; i < out_contour.size(); ++i) {
- ai_assert((out_contour[i]-out_contour2[i]).SquareLength() < 1e-6);
- }
+ for(size_t i = 0; i < out_contour.size(); ++i) {
+ ai_assert((out_contour[i]-out_contour2[i]).SquareLength() < 1e-6);
+ }
#endif
- return m;
+ return m;
}
// ------------------------------------------------------------------------------------------------
bool GenerateOpenings(std::vector<TempOpening>& openings,
- const std::vector<IfcVector3>& nors,
- TempMesh& curmesh,
- bool check_intersection,
- bool generate_connection_geometry,
- const IfcVector3& wall_extrusion_axis)
+ const std::vector<IfcVector3>& nors,
+ TempMesh& curmesh,
+ bool check_intersection,
+ bool generate_connection_geometry,
+ const IfcVector3& wall_extrusion_axis)
{
- OpeningRefVector contours_to_openings;
-
- // Try to derive a solid base plane within the current surface for use as
- // working coordinate system. Map all vertices onto this plane and
- // rescale them to [0,1] range. This normalization means all further
- // epsilons need not be scaled.
- bool ok = true;
-
- std::vector<IfcVector2> contour_flat;
-
- IfcVector3 nor;
- const IfcMatrix4& m = ProjectOntoPlane(contour_flat, curmesh, ok, nor);
- if(!ok) {
- return false;
- }
-
- // Obtain inverse transform for getting back to world space later on
- const IfcMatrix4 minv = IfcMatrix4(m).Inverse();
-
- // Compute bounding boxes for all 2D openings in projection space
- ContourVector contours;
-
- std::vector<IfcVector2> temp_contour;
- std::vector<IfcVector2> temp_contour2;
-
- IfcVector3 wall_extrusion_axis_norm = wall_extrusion_axis;
- wall_extrusion_axis_norm.Normalize();
-
- BOOST_FOREACH(TempOpening& opening,openings) {
-
- // extrusionDir may be 0,0,0 on case where the opening mesh is not an
- // IfcExtrudedAreaSolid but something else (i.e. a brep)
- IfcVector3 norm_extrusion_dir = opening.extrusionDir;
- if (norm_extrusion_dir.SquareLength() > 1e-10) {
- norm_extrusion_dir.Normalize();
- }
- else {
- norm_extrusion_dir = IfcVector3();
- }
-
- TempMesh* profile_data = opening.profileMesh.get();
- bool is_2d_source = false;
- if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
-
- if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
- // horizontal extrusion
- if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- profile_data = opening.profileMesh2D.get();
- is_2d_source = true;
- }
- else {
- //continue;
- }
- }
- else {
- // vertical extrusion
- if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
- continue;
- }
- continue;
- }
- }
- std::vector<IfcVector3> profile_verts = profile_data->verts;
- std::vector<unsigned int> profile_vertcnts = profile_data->vertcnt;
- if(profile_verts.size() <= 2) {
- continue;
- }
-
- // The opening meshes are real 3D meshes so skip over all faces
- // clearly facing into the wrong direction. Also, we need to check
- // whether the meshes do actually intersect the base surface plane.
- // This is done by recording minimum and maximum values for the
- // d component of the plane equation for all polys and checking
- // against surface d.
-
- // Use the sign of the dot product of the face normal to the plane
- // normal to determine to which side of the difference mesh a
- // triangle belongs. Get independent bounding boxes and vertex
- // sets for both sides and take the better one (we can't just
- // take both - this would likely cause major screwup of vertex
- // winding, producing errors as late as in CloseWindows()).
- IfcFloat dmin, dmax;
- MinMaxChooser<IfcFloat>()(dmin,dmax);
-
- temp_contour.clear();
- temp_contour2.clear();
-
- IfcVector2 vpmin,vpmax;
- MinMaxChooser<IfcVector2>()(vpmin,vpmax);
-
- IfcVector2 vpmin2,vpmax2;
- MinMaxChooser<IfcVector2>()(vpmin2,vpmax2);
-
- for (size_t f = 0, vi_total = 0, fend = profile_vertcnts.size(); f < fend; ++f) {
-
- bool side_flag = true;
- if (!is_2d_source) {
- const IfcVector3& face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^
- (profile_verts[vi_total+1] - profile_verts[vi_total])).Normalize();
+ OpeningRefVector contours_to_openings;
+
+ // Try to derive a solid base plane within the current surface for use as
+ // working coordinate system. Map all vertices onto this plane and
+ // rescale them to [0,1] range. This normalization means all further
+ // epsilons need not be scaled.
+ bool ok = true;
+
+ std::vector<IfcVector2> contour_flat;
+
+ IfcVector3 nor;
+ const IfcMatrix4 m = ProjectOntoPlane(contour_flat, curmesh, ok, nor);
+ if(!ok) {
+ return false;
+ }
+
+ // Obtain inverse transform for getting back to world space later on
+ const IfcMatrix4 minv = IfcMatrix4(m).Inverse();
+
+ // Compute bounding boxes for all 2D openings in projection space
+ ContourVector contours;
+
+ std::vector<IfcVector2> temp_contour;
+ std::vector<IfcVector2> temp_contour2;
+
+ IfcVector3 wall_extrusion_axis_norm = wall_extrusion_axis;
+ wall_extrusion_axis_norm.Normalize();
+
+ for(TempOpening& opening :openings) {
+
+ // extrusionDir may be 0,0,0 on case where the opening mesh is not an
+ // IfcExtrudedAreaSolid but something else (i.e. a brep)
+ IfcVector3 norm_extrusion_dir = opening.extrusionDir;
+ if (norm_extrusion_dir.SquareLength() > 1e-10) {
+ norm_extrusion_dir.Normalize();
+ }
+ else {
+ norm_extrusion_dir = IfcVector3();
+ }
+
+ TempMesh* profile_data = opening.profileMesh.get();
+ bool is_2d_source = false;
+ if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
+
+ if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
+ // horizontal extrusion
+ if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
+ profile_data = opening.profileMesh2D.get();
+ is_2d_source = true;
+ }
+ }
+ else {
+ // vertical extrusion
+ if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
+ profile_data = opening.profileMesh2D.get();
+ is_2d_source = true;
+ }
+ }
+ }
+ std::vector<IfcVector3> profile_verts = profile_data->verts;
+ std::vector<unsigned int> profile_vertcnts = profile_data->vertcnt;
+ if(profile_verts.size() <= 2) {
+ continue;
+ }
+
+ // The opening meshes are real 3D meshes so skip over all faces
+ // clearly facing into the wrong direction. Also, we need to check
+ // whether the meshes do actually intersect the base surface plane.
+ // This is done by recording minimum and maximum values for the
+ // d component of the plane equation for all polys and checking
+ // against surface d.
+
+ // Use the sign of the dot product of the face normal to the plane
+ // normal to determine to which side of the difference mesh a
+ // triangle belongs. Get independent bounding boxes and vertex
+ // sets for both sides and take the better one (we can't just
+ // take both - this would likely cause major screwup of vertex
+ // winding, producing errors as late as in CloseWindows()).
+ IfcFloat dmin, dmax;
+ MinMaxChooser<IfcFloat>()(dmin,dmax);
+
+ temp_contour.clear();
+ temp_contour2.clear();
+
+ IfcVector2 vpmin,vpmax;
+ MinMaxChooser<IfcVector2>()(vpmin,vpmax);
+
+ IfcVector2 vpmin2,vpmax2;
+ MinMaxChooser<IfcVector2>()(vpmin2,vpmax2);
+
+ for (size_t f = 0, vi_total = 0, fend = profile_vertcnts.size(); f < fend; ++f) {
+
+ bool side_flag = true;
+ if (!is_2d_source) {
+ const IfcVector3 face_nor = ((profile_verts[vi_total+2] - profile_verts[vi_total]) ^
+ (profile_verts[vi_total+1] - profile_verts[vi_total])).Normalize();
const IfcFloat abs_dot_face_nor = std::abs(nor * face_nor);
- if (abs_dot_face_nor < 0.9) {
- vi_total += profile_vertcnts[f];
- continue;
- }
-
- side_flag = nor * face_nor > 0;
- }
-
- for (unsigned int vi = 0, vend = profile_vertcnts[f]; vi < vend; ++vi, ++vi_total) {
- const IfcVector3& x = profile_verts[vi_total];
-
- const IfcVector3& v = m * x;
- IfcVector2 vv(v.x, v.y);
-
- //if(check_intersection) {
- dmin = std::min(dmin, v.z);
- dmax = std::max(dmax, v.z);
- //}
-
- // sanity rounding
- vv = std::max(vv,IfcVector2());
- vv = std::min(vv,one_vec);
-
- if(side_flag) {
- vpmin = std::min(vpmin,vv);
- vpmax = std::max(vpmax,vv);
- }
- else {
- vpmin2 = std::min(vpmin2,vv);
- vpmax2 = std::max(vpmax2,vv);
- }
-
- std::vector<IfcVector2>& store = side_flag ? temp_contour : temp_contour2;
-
- if (!IsDuplicateVertex(vv, store)) {
- store.push_back(vv);
- }
- }
- }
-
- if (temp_contour2.size() > 2) {
- ai_assert(!is_2d_source);
- const IfcVector2 area = vpmax-vpmin;
- const IfcVector2 area2 = vpmax2-vpmin2;
- if (temp_contour.size() <= 2 || std::fabs(area2.x * area2.y) > std::fabs(area.x * area.y)) {
- temp_contour.swap(temp_contour2);
-
- vpmax = vpmax2;
- vpmin = vpmin2;
- }
- }
- if(temp_contour.size() <= 2) {
- continue;
- }
-
- // TODO: This epsilon may be too large
- const IfcFloat epsilon = std::fabs(dmax-dmin) * 0.0001;
- if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) {
- continue;
- }
-
- BoundingBox bb = BoundingBox(vpmin,vpmax);
-
- // Skip over very small openings - these are likely projection errors
- // (i.e. they don't belong to this side of the wall)
- if(std::fabs(vpmax.x - vpmin.x) * std::fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
- continue;
- }
- std::vector<TempOpening*> joined_openings(1, &opening);
-
- bool is_rectangle = temp_contour.size() == 4;
-
- // See if this BB intersects or is in close adjacency to any other BB we have so far.
- for (ContourVector::iterator it = contours.begin(); it != contours.end(); ) {
- const BoundingBox& ibb = (*it).bb;
-
- if (BoundingBoxesOverlapping(ibb, bb)) {
-
- if (!(*it).is_rectangular) {
- is_rectangle = false;
- }
-
- const std::vector<IfcVector2>& other = (*it).contour;
- ClipperLib::ExPolygons poly;
-
- // First check whether subtracting the old contour (to which ibb belongs)
- // from the new contour (to which bb belongs) yields an updated bb which
- // no longer overlaps ibb
- MakeDisjunctWindowContours(other, temp_contour, poly);
- if(poly.size() == 1) {
-
- const BoundingBox& newbb = GetBoundingBox(poly[0].outer);
- if (!BoundingBoxesOverlapping(ibb, newbb )) {
- // Good guy bounding box
- bb = newbb ;
-
- ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
- continue;
- }
- }
-
- // Take these two overlapping contours and try to merge them. If they
- // overlap (which should not happen, but in fact happens-in-the-real-
- // world [tm] ), resume using a single contour and a single bounding box.
- MergeWindowContours(temp_contour, other, poly);
-
- if (poly.size() > 1) {
- return TryAddOpenings_Poly2Tri(openings, nors, curmesh);
- }
- else if (poly.size() == 0) {
- IFCImporter::LogWarn("ignoring duplicate opening");
- temp_contour.clear();
- break;
- }
- else {
- IFCImporter::LogDebug("merging overlapping openings");
- ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
-
- // Generate the union of the bounding boxes
- bb.first = std::min(bb.first, ibb.first);
- bb.second = std::max(bb.second, ibb.second);
-
- // Update contour-to-opening tables accordingly
- if (generate_connection_geometry) {
- std::vector<TempOpening*>& t = contours_to_openings[std::distance(contours.begin(),it)];
- joined_openings.insert(joined_openings.end(), t.begin(), t.end());
-
- contours_to_openings.erase(contours_to_openings.begin() + std::distance(contours.begin(),it));
- }
-
- contours.erase(it);
-
- // Restart from scratch because the newly formed BB might now
- // overlap any other BB which its constituent BBs didn't
- // previously overlap.
- it = contours.begin();
- continue;
- }
- }
- ++it;
- }
-
- if(!temp_contour.empty()) {
- if (generate_connection_geometry) {
- contours_to_openings.push_back(std::vector<TempOpening*>(
- joined_openings.begin(),
- joined_openings.end()));
- }
-
- contours.push_back(ProjectedWindowContour(temp_contour, bb, is_rectangle));
- }
- }
-
- // Check if we still have any openings left - it may well be that this is
- // not the cause, for example if all the opening candidates don't intersect
- // this surface or point into a direction perpendicular to it.
- if (contours.empty()) {
- return false;
- }
-
- curmesh.Clear();
-
- // Generate a base subdivision into quads to accommodate the given list
- // of window bounding boxes.
- Quadrify(contours,curmesh);
-
- // Run a sanity cleanup pass on the window contours to avoid generating
- // artifacts during the contour generation phase later on.
- CleanupWindowContours(contours);
-
- // Previously we reduced all windows to rectangular AABBs in projection
- // space, now it is time to fill the gaps between the BBs and the real
- // window openings.
- InsertWindowContours(contours,openings, curmesh);
-
- // Clip the entire outer contour of our current result against the real
- // outer contour of the surface. This is necessary because the result
- // of the Quadrify() algorithm is always a square area spanning
- // over [0,1]^2 (i.e. entire projection space).
- CleanupOuterContour(contour_flat, curmesh);
-
- // Undo the projection and get back to world (or local object) space
- BOOST_FOREACH(IfcVector3& v3, curmesh.verts) {
- v3 = minv * v3;
- }
-
- // Generate window caps to connect the symmetric openings on both sides
- // of the wall.
- if (generate_connection_geometry) {
- CloseWindows(contours, minv, contours_to_openings, curmesh);
- }
- return true;
+ if (abs_dot_face_nor < 0.9) {
+ vi_total += profile_vertcnts[f];
+ continue;
+ }
+
+ side_flag = nor * face_nor > 0;
+ }
+
+ for (unsigned int vi = 0, vend = profile_vertcnts[f]; vi < vend; ++vi, ++vi_total) {
+ const IfcVector3& x = profile_verts[vi_total];
+
+ const IfcVector3 v = m * x;
+ IfcVector2 vv(v.x, v.y);
+
+ //if(check_intersection) {
+ dmin = std::min(dmin, v.z);
+ dmax = std::max(dmax, v.z);
+ //}
+
+ // sanity rounding
+ vv = std::max(vv,IfcVector2());
+ vv = std::min(vv,one_vec);
+
+ if(side_flag) {
+ vpmin = std::min(vpmin,vv);
+ vpmax = std::max(vpmax,vv);
+ }
+ else {
+ vpmin2 = std::min(vpmin2,vv);
+ vpmax2 = std::max(vpmax2,vv);
+ }
+
+ std::vector<IfcVector2>& store = side_flag ? temp_contour : temp_contour2;
+
+ if (!IsDuplicateVertex(vv, store)) {
+ store.push_back(vv);
+ }
+ }
+ }
+
+ if (temp_contour2.size() > 2) {
+ ai_assert(!is_2d_source);
+ const IfcVector2 area = vpmax-vpmin;
+ const IfcVector2 area2 = vpmax2-vpmin2;
+ if (temp_contour.size() <= 2 || std::fabs(area2.x * area2.y) > std::fabs(area.x * area.y)) {
+ temp_contour.swap(temp_contour2);
+
+ vpmax = vpmax2;
+ vpmin = vpmin2;
+ }
+ }
+ if(temp_contour.size() <= 2) {
+ continue;
+ }
+
+ // TODO: This epsilon may be too large
+ const IfcFloat epsilon = std::fabs(dmax-dmin) * 0.0001;
+ if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) {
+ continue;
+ }
+
+ BoundingBox bb = BoundingBox(vpmin,vpmax);
+
+ // Skip over very small openings - these are likely projection errors
+ // (i.e. they don't belong to this side of the wall)
+ if(std::fabs(vpmax.x - vpmin.x) * std::fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
+ continue;
+ }
+ std::vector<TempOpening*> joined_openings(1, &opening);
+
+ bool is_rectangle = temp_contour.size() == 4;
+
+ // See if this BB intersects or is in close adjacency to any other BB we have so far.
+ for (ContourVector::iterator it = contours.begin(); it != contours.end(); ) {
+ const BoundingBox& ibb = (*it).bb;
+
+ if (BoundingBoxesOverlapping(ibb, bb)) {
+
+ if (!(*it).is_rectangular) {
+ is_rectangle = false;
+ }
+
+ const std::vector<IfcVector2>& other = (*it).contour;
+ ClipperLib::ExPolygons poly;
+
+ // First check whether subtracting the old contour (to which ibb belongs)
+ // from the new contour (to which bb belongs) yields an updated bb which
+ // no longer overlaps ibb
+ MakeDisjunctWindowContours(other, temp_contour, poly);
+ if(poly.size() == 1) {
+
+ const BoundingBox newbb = GetBoundingBox(poly[0].outer);
+ if (!BoundingBoxesOverlapping(ibb, newbb )) {
+ // Good guy bounding box
+ bb = newbb ;
+
+ ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
+ continue;
+ }
+ }
+
+ // Take these two overlapping contours and try to merge them. If they
+ // overlap (which should not happen, but in fact happens-in-the-real-
+ // world [tm] ), resume using a single contour and a single bounding box.
+ MergeWindowContours(temp_contour, other, poly);
+
+ if (poly.size() > 1) {
+ return TryAddOpenings_Poly2Tri(openings, nors, curmesh);
+ }
+ else if (poly.size() == 0) {
+ IFCImporter::LogWarn("ignoring duplicate opening");
+ temp_contour.clear();
+ break;
+ }
+ else {
+ IFCImporter::LogDebug("merging overlapping openings");
+ ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
+
+ // Generate the union of the bounding boxes
+ bb.first = std::min(bb.first, ibb.first);
+ bb.second = std::max(bb.second, ibb.second);
+
+ // Update contour-to-opening tables accordingly
+ if (generate_connection_geometry) {
+ std::vector<TempOpening*>& t = contours_to_openings[std::distance(contours.begin(),it)];
+ joined_openings.insert(joined_openings.end(), t.begin(), t.end());
+
+ contours_to_openings.erase(contours_to_openings.begin() + std::distance(contours.begin(),it));
+ }
+
+ contours.erase(it);
+
+ // Restart from scratch because the newly formed BB might now
+ // overlap any other BB which its constituent BBs didn't
+ // previously overlap.
+ it = contours.begin();
+ continue;
+ }
+ }
+ ++it;
+ }
+
+ if(!temp_contour.empty()) {
+ if (generate_connection_geometry) {
+ contours_to_openings.push_back(std::vector<TempOpening*>(
+ joined_openings.begin(),
+ joined_openings.end()));
+ }
+
+ contours.push_back(ProjectedWindowContour(temp_contour, bb, is_rectangle));
+ }
+ }
+
+ // Check if we still have any openings left - it may well be that this is
+ // not the cause, for example if all the opening candidates don't intersect
+ // this surface or point into a direction perpendicular to it.
+ if (contours.empty()) {
+ return false;
+ }
+
+ curmesh.Clear();
+
+ // Generate a base subdivision into quads to accommodate the given list
+ // of window bounding boxes.
+ Quadrify(contours,curmesh);
+
+ // Run a sanity cleanup pass on the window contours to avoid generating
+ // artifacts during the contour generation phase later on.
+ CleanupWindowContours(contours);
+
+ // Previously we reduced all windows to rectangular AABBs in projection
+ // space, now it is time to fill the gaps between the BBs and the real
+ // window openings.
+ InsertWindowContours(contours,openings, curmesh);
+
+ // Clip the entire outer contour of our current result against the real
+ // outer contour of the surface. This is necessary because the result
+ // of the Quadrify() algorithm is always a square area spanning
+ // over [0,1]^2 (i.e. entire projection space).
+ CleanupOuterContour(contour_flat, curmesh);
+
+ // Undo the projection and get back to world (or local object) space
+ for(IfcVector3& v3 : curmesh.verts) {
+ v3 = minv * v3;
+ }
+
+ // Generate window caps to connect the symmetric openings on both sides
+ // of the wall.
+ if (generate_connection_geometry) {
+ CloseWindows(contours, minv, contours_to_openings, curmesh);
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
- TempMesh& curmesh)
+bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
+ TempMesh& curmesh)
{
- IFCImporter::LogWarn("forced to use poly2tri fallback method to generate wall openings");
- std::vector<IfcVector3>& out = curmesh.verts;
+ IFCImporter::LogWarn("forced to use poly2tri fallback method to generate wall openings");
+ std::vector<IfcVector3>& out = curmesh.verts;
- bool result = false;
-
- // Try to derive a solid base plane within the current surface for use as
- // working coordinate system.
- bool ok;
- IfcVector3 nor;
- const IfcMatrix3& m = DerivePlaneCoordinateSpace(curmesh, ok, nor);
- if (!ok) {
- return false;
- }
-
- const IfcMatrix3 minv = IfcMatrix3(m).Inverse();
-
-
- IfcFloat coord = -1;
+ bool result = false;
- std::vector<IfcVector2> contour_flat;
- contour_flat.reserve(out.size());
+ // Try to derive a solid base plane within the current surface for use as
+ // working coordinate system.
+ bool ok;
+ IfcVector3 nor;
+ const IfcMatrix3 m = DerivePlaneCoordinateSpace(curmesh, ok, nor);
+ if (!ok) {
+ return false;
+ }
- IfcVector2 vmin, vmax;
- MinMaxChooser<IfcVector2>()(vmin, vmax);
-
- // Move all points into the new coordinate system, collecting min/max verts on the way
- BOOST_FOREACH(IfcVector3& x, out) {
- const IfcVector3 vv = m * x;
+ const IfcMatrix3 minv = IfcMatrix3(m).Inverse();
- // keep Z offset in the plane coordinate system. Ignoring precision issues
- // (which are present, of course), this should be the same value for
- // all polygon vertices (assuming the polygon is planar).
+ IfcFloat coord = -1;
- // XXX this should be guarded, but we somehow need to pick a suitable
- // epsilon
- // if(coord != -1.0f) {
- // assert(std::fabs(coord - vv.z) < 1e-3f);
- // }
-
- coord = vv.z;
-
- vmin = std::min(IfcVector2(vv.x, vv.y), vmin);
- vmax = std::max(IfcVector2(vv.x, vv.y), vmax);
-
- contour_flat.push_back(IfcVector2(vv.x,vv.y));
- }
-
- // With the current code in DerivePlaneCoordinateSpace,
- // vmin,vmax should always be the 0...1 rectangle (+- numeric inaccuracies)
- // but here we won't rely on this.
-
- vmax -= vmin;
-
- // If this happens then the projection must have been wrong.
- assert(vmax.Length());
-
- ClipperLib::ExPolygons clipped;
- ClipperLib::Polygons holes_union;
-
-
- IfcVector3 wall_extrusion;
- bool do_connections = false, first = true;
-
- try {
-
- ClipperLib::Clipper clipper_holes;
- size_t c = 0;
-
- BOOST_FOREACH(const TempOpening& t,openings) {
- const IfcVector3& outernor = nors[c++];
- const IfcFloat dot = nor * outernor;
- if (std::fabs(dot)<1.f-1e-6f) {
- continue;
- }
-
- const std::vector<IfcVector3>& va = t.profileMesh->verts;
- if(va.size() <= 2) {
- continue;
- }
-
- std::vector<IfcVector2> contour;
+ std::vector<IfcVector2> contour_flat;
+ contour_flat.reserve(out.size());
- BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) {
- IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
-
- const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
- if (first) {
- first = false;
- if (dot > 0.f) {
- do_connections = true;
- wall_extrusion = t.extrusionDir;
- if (is_extruded_side) {
- wall_extrusion = - wall_extrusion;
- }
- }
- }
+ IfcVector2 vmin, vmax;
+ MinMaxChooser<IfcVector2>()(vmin, vmax);
- // XXX should not be necessary - but it is. Why? For precision reasons?
- vv = is_extruded_side ? vv_extr : vv;
- contour.push_back(IfcVector2(vv.x,vv.y));
- }
+ // Move all points into the new coordinate system, collecting min/max verts on the way
+ for(IfcVector3& x : out) {
+ const IfcVector3 vv = m * x;
- ClipperLib::Polygon hole;
- BOOST_FOREACH(IfcVector2& pip, contour) {
- pip.x = (pip.x - vmin.x) / vmax.x;
- pip.y = (pip.y - vmin.y) / vmax.y;
-
- hole.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
-
- if (!ClipperLib::Orientation(hole)) {
- std::reverse(hole.begin(), hole.end());
- // assert(ClipperLib::Orientation(hole));
- }
-
- /*ClipperLib::Polygons pol_temp(1), pol_temp2(1);
- pol_temp[0] = hole;
-
- ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
- hole = pol_temp2[0];*/
-
- clipper_holes.AddPolygon(hole,ClipperLib::ptSubject);
- }
-
- clipper_holes.Execute(ClipperLib::ctUnion,holes_union,
- ClipperLib::pftNonZero,
- ClipperLib::pftNonZero);
-
- if (holes_union.empty()) {
- return false;
- }
-
- // Now that we have the big union of all holes, subtract it from the outer contour
- // to obtain the final polygon to feed into the triangulator.
- {
- ClipperLib::Polygon poly;
- BOOST_FOREACH(IfcVector2& pip, contour_flat) {
- pip.x = (pip.x - vmin.x) / vmax.x;
- pip.y = (pip.y - vmin.y) / vmax.y;
-
- poly.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
- }
-
- if (ClipperLib::Orientation(poly)) {
- std::reverse(poly.begin(), poly.end());
- }
- clipper_holes.Clear();
- clipper_holes.AddPolygon(poly,ClipperLib::ptSubject);
-
- clipper_holes.AddPolygons(holes_union,ClipperLib::ptClip);
- clipper_holes.Execute(ClipperLib::ctDifference,clipped,
- ClipperLib::pftNonZero,
- ClipperLib::pftNonZero);
- }
-
- }
- catch (const char* sx) {
- IFCImporter::LogError("Ifc: error during polygon clipping, skipping openings for this face: (Clipper: "
- + std::string(sx) + ")");
-
- return false;
- }
-
- std::vector<IfcVector3> old_verts;
- std::vector<unsigned int> old_vertcnt;
-
- old_verts.swap(curmesh.verts);
- old_vertcnt.swap(curmesh.vertcnt);
-
-
- // add connection geometry to close the adjacent 'holes' for the openings
- // this should only be done from one side of the wall or the polygons
- // would be emitted twice.
- if (false && do_connections) {
-
- std::vector<IfcVector3> tmpvec;
- BOOST_FOREACH(ClipperLib::Polygon& opening, holes_union) {
-
- assert(ClipperLib::Orientation(opening));
-
- tmpvec.clear();
-
- BOOST_FOREACH(ClipperLib::IntPoint& point, opening) {
-
- tmpvec.push_back( minv * IfcVector3(
- vmin.x + from_int64(point.X) * vmax.x,
- vmin.y + from_int64(point.Y) * vmax.y,
- coord));
- }
-
- for(size_t i = 0, size = tmpvec.size(); i < size; ++i) {
- const size_t next = (i+1)%size;
-
- curmesh.vertcnt.push_back(4);
-
- const IfcVector3& in_world = tmpvec[i];
- const IfcVector3& next_world = tmpvec[next];
-
- // Assumptions: no 'partial' openings, wall thickness roughly the same across the wall
- curmesh.verts.push_back(in_world);
- curmesh.verts.push_back(in_world+wall_extrusion);
- curmesh.verts.push_back(next_world+wall_extrusion);
- curmesh.verts.push_back(next_world);
- }
- }
- }
-
- std::vector< std::vector<p2t::Point*> > contours;
- BOOST_FOREACH(ClipperLib::ExPolygon& clip, clipped) {
-
- contours.clear();
-
- // Build the outer polygon contour line for feeding into poly2tri
- std::vector<p2t::Point*> contour_points;
- BOOST_FOREACH(ClipperLib::IntPoint& point, clip.outer) {
- contour_points.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) );
- }
-
- p2t::CDT* cdt ;
- try {
- // Note: this relies on custom modifications in poly2tri to raise runtime_error's
- // instead if assertions. These failures are not debug only, they can actually
- // happen in production use if the input data is broken. An assertion would be
- // inappropriate.
- cdt = new p2t::CDT(contour_points);
- }
- catch(const std::exception& e) {
- IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
- + std::string(e.what()) + ")");
- continue;
- }
-
-
- // Build the poly2tri inner contours for all holes we got from ClipperLib
- BOOST_FOREACH(ClipperLib::Polygon& opening, clip.holes) {
-
- contours.push_back(std::vector<p2t::Point*>());
- std::vector<p2t::Point*>& contour = contours.back();
-
- BOOST_FOREACH(ClipperLib::IntPoint& point, opening) {
- contour.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) );
- }
-
- cdt->AddHole(contour);
- }
-
- try {
- // Note: See above
- cdt->Triangulate();
- }
- catch(const std::exception& e) {
- IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
- + std::string(e.what()) + ")");
- continue;
- }
-
- const std::vector<p2t::Triangle*>& tris = cdt->GetTriangles();
-
- // Collect the triangles we just produced
- BOOST_FOREACH(p2t::Triangle* tri, tris) {
- for(int i = 0; i < 3; ++i) {
-
- const IfcVector2& v = IfcVector2(
- static_cast<IfcFloat>( tri->GetPoint(i)->x ),
- static_cast<IfcFloat>( tri->GetPoint(i)->y )
- );
-
- assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0);
- const IfcVector3 v3 = minv * IfcVector3(vmin.x + v.x * vmax.x, vmin.y + v.y * vmax.y,coord) ;
-
- curmesh.verts.push_back(v3);
- }
- curmesh.vertcnt.push_back(3);
- }
-
- result = true;
- }
-
- if (!result) {
- // revert -- it's a shame, but better than nothing
- curmesh.verts.insert(curmesh.verts.end(),old_verts.begin(), old_verts.end());
- curmesh.vertcnt.insert(curmesh.vertcnt.end(),old_vertcnt.begin(), old_vertcnt.end());
-
- IFCImporter::LogError("Ifc: revert, could not generate openings for this wall");
- }
-
- return result;
+ // keep Z offset in the plane coordinate system. Ignoring precision issues
+ // (which are present, of course), this should be the same value for
+ // all polygon vertices (assuming the polygon is planar).
+
+
+ // XXX this should be guarded, but we somehow need to pick a suitable
+ // epsilon
+ // if(coord != -1.0f) {
+ // assert(std::fabs(coord - vv.z) < 1e-3f);
+ // }
+
+ coord = vv.z;
+
+ vmin = std::min(IfcVector2(vv.x, vv.y), vmin);
+ vmax = std::max(IfcVector2(vv.x, vv.y), vmax);
+
+ contour_flat.push_back(IfcVector2(vv.x,vv.y));
+ }
+
+ // With the current code in DerivePlaneCoordinateSpace,
+ // vmin,vmax should always be the 0...1 rectangle (+- numeric inaccuracies)
+ // but here we won't rely on this.
+
+ vmax -= vmin;
+
+ // If this happens then the projection must have been wrong.
+ assert(vmax.Length());
+
+ ClipperLib::ExPolygons clipped;
+ ClipperLib::Polygons holes_union;
+
+
+ IfcVector3 wall_extrusion;
+ bool do_connections = false, first = true;
+
+ try {
+
+ ClipperLib::Clipper clipper_holes;
+ size_t c = 0;
+
+ for(const TempOpening& t :openings) {
+ const IfcVector3& outernor = nors[c++];
+ const IfcFloat dot = nor * outernor;
+ if (std::fabs(dot)<1.f-1e-6f) {
+ continue;
+ }
+
+ const std::vector<IfcVector3>& va = t.profileMesh->verts;
+ if(va.size() <= 2) {
+ continue;
+ }
+
+ std::vector<IfcVector2> contour;
+
+ for(const IfcVector3& xx : t.profileMesh->verts) {
+ IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
+
+ const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
+ if (first) {
+ first = false;
+ if (dot > 0.f) {
+ do_connections = true;
+ wall_extrusion = t.extrusionDir;
+ if (is_extruded_side) {
+ wall_extrusion = - wall_extrusion;
+ }
+ }
+ }
+
+ // XXX should not be necessary - but it is. Why? For precision reasons?
+ vv = is_extruded_side ? vv_extr : vv;
+ contour.push_back(IfcVector2(vv.x,vv.y));
+ }
+
+ ClipperLib::Polygon hole;
+ for(IfcVector2& pip : contour) {
+ pip.x = (pip.x - vmin.x) / vmax.x;
+ pip.y = (pip.y - vmin.y) / vmax.y;
+
+ hole.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
+
+ if (!ClipperLib::Orientation(hole)) {
+ std::reverse(hole.begin(), hole.end());
+ // assert(ClipperLib::Orientation(hole));
+ }
+
+ /*ClipperLib::Polygons pol_temp(1), pol_temp2(1);
+ pol_temp[0] = hole;
+
+ ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
+ hole = pol_temp2[0];*/
+
+ clipper_holes.AddPolygon(hole,ClipperLib::ptSubject);
+ }
+
+ clipper_holes.Execute(ClipperLib::ctUnion,holes_union,
+ ClipperLib::pftNonZero,
+ ClipperLib::pftNonZero);
+
+ if (holes_union.empty()) {
+ return false;
+ }
+
+ // Now that we have the big union of all holes, subtract it from the outer contour
+ // to obtain the final polygon to feed into the triangulator.
+ {
+ ClipperLib::Polygon poly;
+ for(IfcVector2& pip : contour_flat) {
+ pip.x = (pip.x - vmin.x) / vmax.x;
+ pip.y = (pip.y - vmin.y) / vmax.y;
+
+ poly.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+ }
+
+ if (ClipperLib::Orientation(poly)) {
+ std::reverse(poly.begin(), poly.end());
+ }
+ clipper_holes.Clear();
+ clipper_holes.AddPolygon(poly,ClipperLib::ptSubject);
+
+ clipper_holes.AddPolygons(holes_union,ClipperLib::ptClip);
+ clipper_holes.Execute(ClipperLib::ctDifference,clipped,
+ ClipperLib::pftNonZero,
+ ClipperLib::pftNonZero);
+ }
+
+ }
+ catch (const char* sx) {
+ IFCImporter::LogError("Ifc: error during polygon clipping, skipping openings for this face: (Clipper: "
+ + std::string(sx) + ")");
+
+ return false;
+ }
+
+ std::vector<IfcVector3> old_verts;
+ std::vector<unsigned int> old_vertcnt;
+
+ old_verts.swap(curmesh.verts);
+ old_vertcnt.swap(curmesh.vertcnt);
+
+
+ // add connection geometry to close the adjacent 'holes' for the openings
+ // this should only be done from one side of the wall or the polygons
+ // would be emitted twice.
+ if (false && do_connections) {
+
+ std::vector<IfcVector3> tmpvec;
+ for(ClipperLib::Polygon& opening : holes_union) {
+
+ assert(ClipperLib::Orientation(opening));
+
+ tmpvec.clear();
+
+ for(ClipperLib::IntPoint& point : opening) {
+
+ tmpvec.push_back( minv * IfcVector3(
+ vmin.x + from_int64(point.X) * vmax.x,
+ vmin.y + from_int64(point.Y) * vmax.y,
+ coord));
+ }
+
+ for(size_t i = 0, size = tmpvec.size(); i < size; ++i) {
+ const size_t next = (i+1)%size;
+
+ curmesh.vertcnt.push_back(4);
+
+ const IfcVector3& in_world = tmpvec[i];
+ const IfcVector3& next_world = tmpvec[next];
+
+ // Assumptions: no 'partial' openings, wall thickness roughly the same across the wall
+ curmesh.verts.push_back(in_world);
+ curmesh.verts.push_back(in_world+wall_extrusion);
+ curmesh.verts.push_back(next_world+wall_extrusion);
+ curmesh.verts.push_back(next_world);
+ }
+ }
+ }
+
+ std::vector< std::vector<p2t::Point*> > contours;
+ for(ClipperLib::ExPolygon& clip : clipped) {
+
+ contours.clear();
+
+ // Build the outer polygon contour line for feeding into poly2tri
+ std::vector<p2t::Point*> contour_points;
+ for(ClipperLib::IntPoint& point : clip.outer) {
+ contour_points.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) );
+ }
+
+ p2t::CDT* cdt ;
+ try {
+ // Note: this relies on custom modifications in poly2tri to raise runtime_error's
+ // instead if assertions. These failures are not debug only, they can actually
+ // happen in production use if the input data is broken. An assertion would be
+ // inappropriate.
+ cdt = new p2t::CDT(contour_points);
+ }
+ catch(const std::exception& e) {
+ IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
+ + std::string(e.what()) + ")");
+ continue;
+ }
+
+
+ // Build the poly2tri inner contours for all holes we got from ClipperLib
+ for(ClipperLib::Polygon& opening : clip.holes) {
+
+ contours.push_back(std::vector<p2t::Point*>());
+ std::vector<p2t::Point*>& contour = contours.back();
+
+ for(ClipperLib::IntPoint& point : opening) {
+ contour.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) );
+ }
+
+ cdt->AddHole(contour);
+ }
+
+ try {
+ // Note: See above
+ cdt->Triangulate();
+ }
+ catch(const std::exception& e) {
+ IFCImporter::LogError("Ifc: error during polygon triangulation, skipping some openings: (poly2tri: "
+ + std::string(e.what()) + ")");
+ continue;
+ }
+
+ const std::vector<p2t::Triangle*> tris = cdt->GetTriangles();
+
+ // Collect the triangles we just produced
+ for(p2t::Triangle* tri : tris) {
+ for(int i = 0; i < 3; ++i) {
+
+ const IfcVector2 v = IfcVector2(
+ static_cast<IfcFloat>( tri->GetPoint(i)->x ),
+ static_cast<IfcFloat>( tri->GetPoint(i)->y )
+ );
+
+ assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0);
+ const IfcVector3 v3 = minv * IfcVector3(vmin.x + v.x * vmax.x, vmin.y + v.y * vmax.y,coord) ;
+
+ curmesh.verts.push_back(v3);
+ }
+ curmesh.vertcnt.push_back(3);
+ }
+
+ result = true;
+ }
+
+ if (!result) {
+ // revert -- it's a shame, but better than nothing
+ curmesh.verts.insert(curmesh.verts.end(),old_verts.begin(), old_verts.end());
+ curmesh.vertcnt.insert(curmesh.vertcnt.end(),old_vertcnt.begin(), old_vertcnt.end());
+
+ IFCImporter::LogError("Ifc: revert, could not generate openings for this wall");
+ }
+
+ return result;
}
- } // ! IFC
+ } // ! IFC
} // ! Assimp
#undef to_int64
#undef from_int64
#undef one_vec
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/IFCProfile.cpp b/src/3rdparty/assimp/code/IFCProfile.cpp
index 78f038145..01b9008e4 100644
--- a/src/3rdparty/assimp/code/IFCProfile.cpp
+++ b/src/3rdparty/assimp/code/IFCProfile.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,145 +42,145 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Read profile and curves entities from IFC files
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
namespace Assimp {
- namespace IFC {
+ namespace IFC {
// ------------------------------------------------------------------------------------------------
void ProcessPolyLine(const IfcPolyline& def, TempMesh& meshout, ConversionData& /*conv*/)
{
- // this won't produce a valid mesh, it just spits out a list of vertices
- IfcVector3 t;
- BOOST_FOREACH(const IfcCartesianPoint& cp, def.Points) {
- ConvertCartesianPoint(t,cp);
- meshout.verts.push_back(t);
- }
- meshout.vertcnt.push_back(meshout.verts.size());
+ // this won't produce a valid mesh, it just spits out a list of vertices
+ IfcVector3 t;
+ for(const IfcCartesianPoint& cp : def.Points) {
+ ConvertCartesianPoint(t,cp);
+ meshout.verts.push_back(t);
+ }
+ meshout.vertcnt.push_back(meshout.verts.size());
}
// ------------------------------------------------------------------------------------------------
bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& conv)
{
- boost::scoped_ptr<const Curve> cv(Curve::Convert(curve,conv));
- if (!cv) {
- IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is " + curve.GetClassName());
- return false;
- }
-
- // we must have a bounded curve at this point
- if (const BoundedCurve* bc = dynamic_cast<const BoundedCurve*>(cv.get())) {
- try {
- bc->SampleDiscrete(meshout);
- }
- catch(const CurveError& cv) {
- IFCImporter::LogError(cv.s+ " (error occurred while processing curve)");
- return false;
- }
- meshout.vertcnt.push_back(meshout.verts.size());
- return true;
- }
-
- IFCImporter::LogError("cannot use unbounded curve as profile");
- return false;
+ std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv));
+ if (!cv) {
+ IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is " + curve.GetClassName());
+ return false;
+ }
+
+ // we must have a bounded curve at this point
+ if (const BoundedCurve* bc = dynamic_cast<const BoundedCurve*>(cv.get())) {
+ try {
+ bc->SampleDiscrete(meshout);
+ }
+ catch(const CurveError& cv) {
+ IFCImporter::LogError(cv.s+ " (error occurred while processing curve)");
+ return false;
+ }
+ meshout.vertcnt.push_back(meshout.verts.size());
+ return true;
+ }
+
+ IFCImporter::LogError("cannot use unbounded curve as profile");
+ return false;
}
// ------------------------------------------------------------------------------------------------
void ProcessClosedProfile(const IfcArbitraryClosedProfileDef& def, TempMesh& meshout, ConversionData& conv)
{
- ProcessCurve(def.OuterCurve,meshout,conv);
+ ProcessCurve(def.OuterCurve,meshout,conv);
}
// ------------------------------------------------------------------------------------------------
void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout, ConversionData& conv)
{
- ProcessCurve(def.Curve,meshout,conv);
+ ProcessCurve(def.Curve,meshout,conv);
}
// ------------------------------------------------------------------------------------------------
-void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
+void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
{
- if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
- const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
-
- meshout.verts.reserve(meshout.verts.size()+4);
- meshout.verts.push_back( IfcVector3( x, y, 0.f ));
- meshout.verts.push_back( IfcVector3(-x, y, 0.f ));
- meshout.verts.push_back( IfcVector3(-x,-y, 0.f ));
- meshout.verts.push_back( IfcVector3( x,-y, 0.f ));
- meshout.vertcnt.push_back(4);
- }
- else if( const IfcCircleProfileDef* const circle = def.ToPtr<IfcCircleProfileDef>()) {
- if( const IfcCircleHollowProfileDef* const hollow = def.ToPtr<IfcCircleHollowProfileDef>()) {
- // TODO
- }
- const size_t segments = 32;
- const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius;
-
- meshout.verts.reserve(segments);
-
- IfcFloat angle = 0.f;
- for(size_t i = 0; i < segments; ++i, angle += delta) {
+ if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
+ const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
+
+ meshout.verts.reserve(meshout.verts.size()+4);
+ meshout.verts.push_back( IfcVector3( x, y, 0.f ));
+ meshout.verts.push_back( IfcVector3(-x, y, 0.f ));
+ meshout.verts.push_back( IfcVector3(-x,-y, 0.f ));
+ meshout.verts.push_back( IfcVector3( x,-y, 0.f ));
+ meshout.vertcnt.push_back(4);
+ }
+ else if( const IfcCircleProfileDef* const circle = def.ToPtr<IfcCircleProfileDef>()) {
+ if(def.ToPtr<IfcCircleHollowProfileDef>()) {
+ // TODO
+ }
+ const size_t segments = 32;
+ const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius;
+
+ meshout.verts.reserve(segments);
+
+ IfcFloat angle = 0.f;
+ for(size_t i = 0; i < segments; ++i, angle += delta) {
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
- }
-
- meshout.vertcnt.push_back(segments);
- }
- else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
- // construct simplified IBeam shape
- const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2;
- const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2;
-
- meshout.verts.reserve(12);
- meshout.verts.push_back(IfcVector3(0,0,0));
- meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness,0));
- meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness,0));
- meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness + inner_height,0));
- meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness + inner_height,0));
- meshout.verts.push_back(IfcVector3(0,ishape->OverallDepth,0));
- meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->OverallDepth,0));
- meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0));
- meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0));
- meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness,0));
- meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness,0));
- meshout.verts.push_back(IfcVector3(ishape->OverallWidth,0,0));
-
- meshout.vertcnt.push_back(12);
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName());
- return;
- }
-
- IfcMatrix4 trafo;
- ConvertAxisPlacement(trafo, *def.Position);
- meshout.Transform(trafo);
+ }
+
+ meshout.vertcnt.push_back(segments);
+ }
+ else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
+ // construct simplified IBeam shape
+ const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2;
+ const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2;
+
+ meshout.verts.reserve(12);
+ meshout.verts.push_back(IfcVector3(0,0,0));
+ meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness,0));
+ meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness,0));
+ meshout.verts.push_back(IfcVector3(offset,ishape->FlangeThickness + inner_height,0));
+ meshout.verts.push_back(IfcVector3(0,ishape->FlangeThickness + inner_height,0));
+ meshout.verts.push_back(IfcVector3(0,ishape->OverallDepth,0));
+ meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->OverallDepth,0));
+ meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0));
+ meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0));
+ meshout.verts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness,0));
+ meshout.verts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness,0));
+ meshout.verts.push_back(IfcVector3(ishape->OverallWidth,0,0));
+
+ meshout.vertcnt.push_back(12);
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName());
+ return;
+ }
+
+ IfcMatrix4 trafo;
+ ConvertAxisPlacement(trafo, *def.Position);
+ meshout.Transform(trafo);
}
// ------------------------------------------------------------------------------------------------
-bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv)
+bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv)
{
- if(const IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<IfcArbitraryClosedProfileDef>()) {
- ProcessClosedProfile(*cprofile,meshout,conv);
- }
- else if(const IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<IfcArbitraryOpenProfileDef>()) {
- ProcessOpenProfile(*copen,meshout,conv);
- }
- else if(const IfcParameterizedProfileDef* const cparam = prof.ToPtr<IfcParameterizedProfileDef>()) {
- ProcessParametrizedProfile(*cparam,meshout,conv);
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName());
- return false;
- }
- meshout.RemoveAdjacentDuplicates();
- if (!meshout.vertcnt.size() || meshout.vertcnt.front() <= 1) {
- return false;
- }
- return true;
+ if(const IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<IfcArbitraryClosedProfileDef>()) {
+ ProcessClosedProfile(*cprofile,meshout,conv);
+ }
+ else if(const IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<IfcArbitraryOpenProfileDef>()) {
+ ProcessOpenProfile(*copen,meshout,conv);
+ }
+ else if(const IfcParameterizedProfileDef* const cparam = prof.ToPtr<IfcParameterizedProfileDef>()) {
+ ProcessParametrizedProfile(*cparam,meshout,conv);
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName());
+ return false;
+ }
+ meshout.RemoveAdjacentDuplicates();
+ if (!meshout.vertcnt.size() || meshout.vertcnt.front() <= 1) {
+ return false;
+ }
+ return true;
}
} // ! IFC
diff --git a/src/3rdparty/assimp/code/IFCReaderGen.h b/src/3rdparty/assimp/code/IFCReaderGen.h
index d7f831087..85c62faac 100644
--- a/src/3rdparty/assimp/code/IFCReaderGen.h
+++ b/src/3rdparty/assimp/code/IFCReaderGen.h
@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,1340 +47,1371 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace IFC {
- using namespace STEP;
- using namespace STEP::EXPRESS;
-
-
- struct NotImplemented : public ObjectHelper<NotImplemented,0> {
-
- };
-
+ using namespace STEP;
+ using namespace STEP::EXPRESS;
- // ******************************************************************************
- // IFC Custom data types
- // ******************************************************************************
+ struct NotImplemented : public ObjectHelper<NotImplemented,0> {
- // C++ wrapper type for IfcStairTypeEnum
- typedef ENUMERATION IfcStairTypeEnum;
- // C++ wrapper type for IfcSpaceTypeEnum
- typedef ENUMERATION IfcSpaceTypeEnum;
- // C++ wrapper type for IfcWallTypeEnum
- typedef ENUMERATION IfcWallTypeEnum;
- // C++ wrapper type for IfcMonthInYearNumber
- typedef INTEGER IfcMonthInYearNumber;
- // C++ wrapper type for IfcHeatFluxDensityMeasure
- typedef REAL IfcHeatFluxDensityMeasure;
- // C++ wrapper type for IfcKinematicViscosityMeasure
- typedef REAL IfcKinematicViscosityMeasure;
- // C++ wrapper type for IfcSequenceEnum
- typedef ENUMERATION IfcSequenceEnum;
- // C++ wrapper type for IfcAirToAirHeatRecoveryTypeEnum
- typedef ENUMERATION IfcAirToAirHeatRecoveryTypeEnum;
- // C++ wrapper type for IfcActorSelect
- typedef SELECT IfcActorSelect;
- // C++ wrapper type for IfcTransformerTypeEnum
- typedef ENUMERATION IfcTransformerTypeEnum;
- // C++ wrapper type for IfcUnitaryEquipmentTypeEnum
- typedef ENUMERATION IfcUnitaryEquipmentTypeEnum;
- // C++ wrapper type for IfcElectricFlowStorageDeviceTypeEnum
- typedef ENUMERATION IfcElectricFlowStorageDeviceTypeEnum;
- // C++ wrapper type for IfcEnergySequenceEnum
- typedef ENUMERATION IfcEnergySequenceEnum;
- // C++ wrapper type for IfcWorkControlTypeEnum
- typedef ENUMERATION IfcWorkControlTypeEnum;
+ };
+
+
+ // ******************************************************************************
+ // IFC Custom data types
+ // ******************************************************************************
+
+
+ // C++ wrapper type for IfcAbsorbedDoseMeasure
+ typedef REAL IfcAbsorbedDoseMeasure;
+ // C++ wrapper type for IfcAccelerationMeasure
+ typedef REAL IfcAccelerationMeasure;
+ // C++ wrapper type for IfcAmountOfSubstanceMeasure
+ typedef REAL IfcAmountOfSubstanceMeasure;
+ // C++ wrapper type for IfcAngularVelocityMeasure
+ typedef REAL IfcAngularVelocityMeasure;
+ // C++ wrapper type for IfcAreaMeasure
+ typedef REAL IfcAreaMeasure;
+ // C++ wrapper type for IfcBoolean
+ typedef BOOLEAN IfcBoolean;
+ // C++ wrapper type for IfcBoxAlignment
+ typedef STRING IfcBoxAlignment;
+ // C++ wrapper type for IfcCompoundPlaneAngleMeasure
+ typedef ListOf< INTEGER, 3, 3 > IfcCompoundPlaneAngleMeasure;
+ // C++ wrapper type for IfcContextDependentMeasure
+ typedef REAL IfcContextDependentMeasure;
+ // C++ wrapper type for IfcCountMeasure
+ typedef NUMBER IfcCountMeasure;
// C++ wrapper type for IfcCurvatureMeasure
typedef REAL IfcCurvatureMeasure;
- // C++ wrapper type for IfcParameterValue
- typedef REAL IfcParameterValue;
- // C++ wrapper type for IfcAppliedValueSelect
- typedef SELECT IfcAppliedValueSelect;
- // C++ wrapper type for IfcWarpingConstantMeasure
- typedef REAL IfcWarpingConstantMeasure;
- // C++ wrapper type for IfcArithmeticOperatorEnum
- typedef ENUMERATION IfcArithmeticOperatorEnum;
- // C++ wrapper type for IfcLinearForceMeasure
- typedef REAL IfcLinearForceMeasure;
- // C++ wrapper type for IfcWindowPanelPositionEnum
- typedef ENUMERATION IfcWindowPanelPositionEnum;
- // C++ wrapper type for IfcFlowMeterTypeEnum
- typedef ENUMERATION IfcFlowMeterTypeEnum;
- // C++ wrapper type for IfcRampFlightTypeEnum
- typedef ENUMERATION IfcRampFlightTypeEnum;
- // C++ wrapper type for IfcSpecularHighlightSelect
- typedef SELECT IfcSpecularHighlightSelect;
- // C++ wrapper type for IfcActionTypeEnum
- typedef ENUMERATION IfcActionTypeEnum;
- // C++ wrapper type for IfcGeometricProjectionEnum
- typedef ENUMERATION IfcGeometricProjectionEnum;
- // C++ wrapper type for IfcTimeSeriesDataTypeEnum
- typedef ENUMERATION IfcTimeSeriesDataTypeEnum;
- // C++ wrapper type for IfcMagneticFluxMeasure
- typedef REAL IfcMagneticFluxMeasure;
- // C++ wrapper type for IfcObjectTypeEnum
- typedef ENUMERATION IfcObjectTypeEnum;
- // C++ wrapper type for IfcDataOriginEnum
- typedef ENUMERATION IfcDataOriginEnum;
- // C++ wrapper type for IfcMassDensityMeasure
- typedef REAL IfcMassDensityMeasure;
- // C++ wrapper type for IfcLightFixtureTypeEnum
- typedef ENUMERATION IfcLightFixtureTypeEnum;
- // C++ wrapper type for IfcServiceLifeTypeEnum
- typedef ENUMERATION IfcServiceLifeTypeEnum;
+ // C++ wrapper type for IfcDayInMonthNumber
+ typedef INTEGER IfcDayInMonthNumber;
+ // C++ wrapper type for IfcDaylightSavingHour
+ typedef INTEGER IfcDaylightSavingHour;
+ // C++ wrapper type for IfcDescriptiveMeasure
+ typedef STRING IfcDescriptiveMeasure;
+ // C++ wrapper type for IfcDimensionCount
+ typedef INTEGER IfcDimensionCount;
+ // C++ wrapper type for IfcDoseEquivalentMeasure
+ typedef REAL IfcDoseEquivalentMeasure;
+ // C++ wrapper type for IfcDynamicViscosityMeasure
+ typedef REAL IfcDynamicViscosityMeasure;
+ // C++ wrapper type for IfcElectricCapacitanceMeasure
+ typedef REAL IfcElectricCapacitanceMeasure;
+ // C++ wrapper type for IfcElectricChargeMeasure
+ typedef REAL IfcElectricChargeMeasure;
+ // C++ wrapper type for IfcElectricConductanceMeasure
+ typedef REAL IfcElectricConductanceMeasure;
+ // C++ wrapper type for IfcElectricCurrentMeasure
+ typedef REAL IfcElectricCurrentMeasure;
+ // C++ wrapper type for IfcElectricResistanceMeasure
+ typedef REAL IfcElectricResistanceMeasure;
// C++ wrapper type for IfcElectricVoltageMeasure
typedef REAL IfcElectricVoltageMeasure;
+ // C++ wrapper type for IfcEnergyMeasure
+ typedef REAL IfcEnergyMeasure;
+ // C++ wrapper type for IfcFontStyle
+ typedef STRING IfcFontStyle;
+ // C++ wrapper type for IfcFontVariant
+ typedef STRING IfcFontVariant;
+ // C++ wrapper type for IfcFontWeight
+ typedef STRING IfcFontWeight;
+ // C++ wrapper type for IfcForceMeasure
+ typedef REAL IfcForceMeasure;
+ // C++ wrapper type for IfcFrequencyMeasure
+ typedef REAL IfcFrequencyMeasure;
+ // C++ wrapper type for IfcGloballyUniqueId
+ typedef STRING IfcGloballyUniqueId;
+ // C++ wrapper type for IfcHeatFluxDensityMeasure
+ typedef REAL IfcHeatFluxDensityMeasure;
// C++ wrapper type for IfcHeatingValueMeasure
typedef REAL IfcHeatingValueMeasure;
- // C++ wrapper type for IfcPresentableText
- typedef STRING IfcPresentableText;
- // C++ wrapper type for IfcAheadOrBehind
- typedef ENUMERATION IfcAheadOrBehind;
- // C++ wrapper type for IfcSimpleValue
- typedef SELECT IfcSimpleValue;
- // C++ wrapper type for IfcSensorTypeEnum
- typedef ENUMERATION IfcSensorTypeEnum;
- // C++ wrapper type for IfcDerivedUnitEnum
- typedef ENUMERATION IfcDerivedUnitEnum;
- // C++ wrapper type for IfcSizeSelect
- typedef SELECT IfcSizeSelect;
- // C++ wrapper type for IfcTransportElementTypeEnum
- typedef ENUMERATION IfcTransportElementTypeEnum;
- // C++ wrapper type for IfcInventoryTypeEnum
- typedef ENUMERATION IfcInventoryTypeEnum;
- // C++ wrapper type for IfcTextDecoration
- typedef STRING IfcTextDecoration;
- // C++ wrapper type for IfcDirectionSenseEnum
- typedef ENUMERATION IfcDirectionSenseEnum;
- // C++ wrapper type for IfcDuctFittingTypeEnum
- typedef ENUMERATION IfcDuctFittingTypeEnum;
- // C++ wrapper type for IfcDocumentStatusEnum
- typedef ENUMERATION IfcDocumentStatusEnum;
- // C++ wrapper type for IfcSlabTypeEnum
- typedef ENUMERATION IfcSlabTypeEnum;
- // C++ wrapper type for IfcDoorStyleConstructionEnum
- typedef ENUMERATION IfcDoorStyleConstructionEnum;
- // C++ wrapper type for IfcVolumeMeasure
- typedef REAL IfcVolumeMeasure;
+ // C++ wrapper type for IfcHourInDay
+ typedef INTEGER IfcHourInDay;
+ // C++ wrapper type for IfcIdentifier
+ typedef STRING IfcIdentifier;
+ // C++ wrapper type for IfcIlluminanceMeasure
+ typedef REAL IfcIlluminanceMeasure;
// C++ wrapper type for IfcInductanceMeasure
typedef REAL IfcInductanceMeasure;
- // C++ wrapper type for IfcCurtainWallTypeEnum
- typedef ENUMERATION IfcCurtainWallTypeEnum;
- // C++ wrapper type for IfcSIUnitName
- typedef ENUMERATION IfcSIUnitName;
- // C++ wrapper type for IfcSpecularExponent
- typedef REAL IfcSpecularExponent;
- // C++ wrapper type for IfcSoundPressureMeasure
- typedef REAL IfcSoundPressureMeasure;
- // C++ wrapper type for IfcAnalysisTheoryTypeEnum
- typedef ENUMERATION IfcAnalysisTheoryTypeEnum;
- // C++ wrapper type for IfcGasTerminalTypeEnum
- typedef ENUMERATION IfcGasTerminalTypeEnum;
- // C++ wrapper type for IfcYearNumber
- typedef INTEGER IfcYearNumber;
- // C++ wrapper type for IfcModulusOfElasticityMeasure
- typedef REAL IfcModulusOfElasticityMeasure;
- // C++ wrapper type for IfcChangeActionEnum
- typedef ENUMERATION IfcChangeActionEnum;
- // C++ wrapper type for IfcDamperTypeEnum
- typedef ENUMERATION IfcDamperTypeEnum;
- // C++ wrapper type for IfcEvaporatorTypeEnum
- typedef ENUMERATION IfcEvaporatorTypeEnum;
+ // C++ wrapper type for IfcInteger
+ typedef INTEGER IfcInteger;
+ // C++ wrapper type for IfcIntegerCountRateMeasure
+ typedef INTEGER IfcIntegerCountRateMeasure;
// C++ wrapper type for IfcIonConcentrationMeasure
typedef REAL IfcIonConcentrationMeasure;
- // C++ wrapper type for IfcDuctSegmentTypeEnum
- typedef ENUMERATION IfcDuctSegmentTypeEnum;
- // C++ wrapper type for IfcProtectiveDeviceTypeEnum
- typedef ENUMERATION IfcProtectiveDeviceTypeEnum;
- // C++ wrapper type for IfcAbsorbedDoseMeasure
- typedef REAL IfcAbsorbedDoseMeasure;
+ // C++ wrapper type for IfcIsothermalMoistureCapacityMeasure
+ typedef REAL IfcIsothermalMoistureCapacityMeasure;
+ // C++ wrapper type for IfcKinematicViscosityMeasure
+ typedef REAL IfcKinematicViscosityMeasure;
+ // C++ wrapper type for IfcLabel
+ typedef STRING IfcLabel;
+ // C++ wrapper type for IfcLengthMeasure
+ typedef REAL IfcLengthMeasure;
+ // C++ wrapper type for IfcLinearForceMeasure
+ typedef REAL IfcLinearForceMeasure;
+ // C++ wrapper type for IfcLinearMomentMeasure
+ typedef REAL IfcLinearMomentMeasure;
+ // C++ wrapper type for IfcLinearStiffnessMeasure
+ typedef REAL IfcLinearStiffnessMeasure;
+ // C++ wrapper type for IfcLinearVelocityMeasure
+ typedef REAL IfcLinearVelocityMeasure;
+ // C++ wrapper type for IfcLogical
+ typedef LOGICAL IfcLogical;
+ // C++ wrapper type for IfcLuminousFluxMeasure
+ typedef REAL IfcLuminousFluxMeasure;
+ // C++ wrapper type for IfcLuminousIntensityDistributionMeasure
+ typedef REAL IfcLuminousIntensityDistributionMeasure;
+ // C++ wrapper type for IfcLuminousIntensityMeasure
+ typedef REAL IfcLuminousIntensityMeasure;
+ // C++ wrapper type for IfcMagneticFluxDensityMeasure
+ typedef REAL IfcMagneticFluxDensityMeasure;
+ // C++ wrapper type for IfcMagneticFluxMeasure
+ typedef REAL IfcMagneticFluxMeasure;
+ // C++ wrapper type for IfcMassDensityMeasure
+ typedef REAL IfcMassDensityMeasure;
+ // C++ wrapper type for IfcMassFlowRateMeasure
+ typedef REAL IfcMassFlowRateMeasure;
+ // C++ wrapper type for IfcMassMeasure
+ typedef REAL IfcMassMeasure;
// C++ wrapper type for IfcMassPerLengthMeasure
typedef REAL IfcMassPerLengthMeasure;
- // C++ wrapper type for IfcTextFontName
- typedef STRING IfcTextFontName;
- // C++ wrapper type for IfcOrientationSelect
- typedef SELECT IfcOrientationSelect;
- // C++ wrapper type for IfcIlluminanceMeasure
- typedef REAL IfcIlluminanceMeasure;
- // C++ wrapper type for IfcFireSuppressionTerminalTypeEnum
- typedef ENUMERATION IfcFireSuppressionTerminalTypeEnum;
- // C++ wrapper type for IfcFontStyle
- typedef STRING IfcFontStyle;
- // C++ wrapper type for IfcMomentOfInertiaMeasure
- typedef REAL IfcMomentOfInertiaMeasure;
- // C++ wrapper type for IfcModulusOfSubgradeReactionMeasure
- typedef REAL IfcModulusOfSubgradeReactionMeasure;
- // C++ wrapper type for IfcHumidifierTypeEnum
- typedef ENUMERATION IfcHumidifierTypeEnum;
- // C++ wrapper type for IfcPresentationStyleSelect
- typedef SELECT IfcPresentationStyleSelect;
- // C++ wrapper type for IfcThermalTransmittanceMeasure
- typedef REAL IfcThermalTransmittanceMeasure;
- // C++ wrapper type for IfcRibPlateDirectionEnum
- typedef ENUMERATION IfcRibPlateDirectionEnum;
- // C++ wrapper type for IfcClassificationNotationSelect
- typedef SELECT IfcClassificationNotationSelect;
// C++ wrapper type for IfcMinuteInHour
typedef INTEGER IfcMinuteInHour;
- // C++ wrapper type for IfcInternalOrExternalEnum
- typedef ENUMERATION IfcInternalOrExternalEnum;
- // C++ wrapper type for IfcRotationalFrequencyMeasure
- typedef REAL IfcRotationalFrequencyMeasure;
- // C++ wrapper type for IfcSanitaryTerminalTypeEnum
- typedef ENUMERATION IfcSanitaryTerminalTypeEnum;
- // C++ wrapper type for IfcSymbolStyleSelect
- typedef SELECT IfcSymbolStyleSelect;
- // C++ wrapper type for IfcElementCompositionEnum
- typedef ENUMERATION IfcElementCompositionEnum;
- // C++ wrapper type for IfcTextPath
- typedef ENUMERATION IfcTextPath;
- // C++ wrapper type for IfcPowerMeasure
- typedef REAL IfcPowerMeasure;
- // C++ wrapper type for IfcSurfaceStyleElementSelect
- typedef SELECT IfcSurfaceStyleElementSelect;
- // C++ wrapper type for IfcResourceConsumptionEnum
- typedef ENUMERATION IfcResourceConsumptionEnum;
- // C++ wrapper type for IfcElectricCapacitanceMeasure
- typedef REAL IfcElectricCapacitanceMeasure;
- // C++ wrapper type for IfcLayerSetDirectionEnum
- typedef ENUMERATION IfcLayerSetDirectionEnum;
- // C++ wrapper type for IfcRailingTypeEnum
- typedef ENUMERATION IfcRailingTypeEnum;
- // C++ wrapper type for IfcObjectiveEnum
- typedef ENUMERATION IfcObjectiveEnum;
- // C++ wrapper type for IfcDocumentSelect
- typedef SELECT IfcDocumentSelect;
+ // C++ wrapper type for IfcModulusOfElasticityMeasure
+ typedef REAL IfcModulusOfElasticityMeasure;
// C++ wrapper type for IfcModulusOfLinearSubgradeReactionMeasure
typedef REAL IfcModulusOfLinearSubgradeReactionMeasure;
- // C++ wrapper type for IfcThermalAdmittanceMeasure
- typedef REAL IfcThermalAdmittanceMeasure;
- // C++ wrapper type for IfcTransitionCode
- typedef ENUMERATION IfcTransitionCode;
- // C++ wrapper type for IfcConnectionTypeEnum
- typedef ENUMERATION IfcConnectionTypeEnum;
+ // C++ wrapper type for IfcModulusOfRotationalSubgradeReactionMeasure
+ typedef REAL IfcModulusOfRotationalSubgradeReactionMeasure;
+ // C++ wrapper type for IfcModulusOfSubgradeReactionMeasure
+ typedef REAL IfcModulusOfSubgradeReactionMeasure;
+ // C++ wrapper type for IfcMoistureDiffusivityMeasure
+ typedef REAL IfcMoistureDiffusivityMeasure;
+ // C++ wrapper type for IfcMolecularWeightMeasure
+ typedef REAL IfcMolecularWeightMeasure;
+ // C++ wrapper type for IfcMomentOfInertiaMeasure
+ typedef REAL IfcMomentOfInertiaMeasure;
// C++ wrapper type for IfcMonetaryMeasure
typedef REAL IfcMonetaryMeasure;
- // C++ wrapper type for IfcStackTerminalTypeEnum
- typedef ENUMERATION IfcStackTerminalTypeEnum;
- // C++ wrapper type for IfcColour
- typedef SELECT IfcColour;
- // C++ wrapper type for IfcText
- typedef STRING IfcText;
- // C++ wrapper type for IfcContextDependentMeasure
- typedef REAL IfcContextDependentMeasure;
- // C++ wrapper type for IfcThermalConductivityMeasure
- typedef REAL IfcThermalConductivityMeasure;
- // C++ wrapper type for IfcProjectedOrTrueLengthEnum
- typedef ENUMERATION IfcProjectedOrTrueLengthEnum;
+ // C++ wrapper type for IfcMonthInYearNumber
+ typedef INTEGER IfcMonthInYearNumber;
+ // C++ wrapper type for IfcNormalisedRatioMeasure
+ typedef REAL IfcNormalisedRatioMeasure;
+ // C++ wrapper type for IfcNumericMeasure
+ typedef NUMBER IfcNumericMeasure;
+ // C++ wrapper type for IfcPHMeasure
+ typedef REAL IfcPHMeasure;
+ // C++ wrapper type for IfcParameterValue
+ typedef REAL IfcParameterValue;
+ // C++ wrapper type for IfcPlanarForceMeasure
+ typedef REAL IfcPlanarForceMeasure;
+ // C++ wrapper type for IfcPlaneAngleMeasure
+ typedef REAL IfcPlaneAngleMeasure;
+ // C++ wrapper type for IfcPositiveLengthMeasure
+ typedef REAL IfcPositiveLengthMeasure;
+ // C++ wrapper type for IfcPositivePlaneAngleMeasure
+ typedef REAL IfcPositivePlaneAngleMeasure;
+ // C++ wrapper type for IfcPositiveRatioMeasure
+ typedef REAL IfcPositiveRatioMeasure;
+ // C++ wrapper type for IfcPowerMeasure
+ typedef REAL IfcPowerMeasure;
+ // C++ wrapper type for IfcPresentableText
+ typedef STRING IfcPresentableText;
// C++ wrapper type for IfcPressureMeasure
typedef REAL IfcPressureMeasure;
- // C++ wrapper type for IfcMoistureDiffusivityMeasure
- typedef REAL IfcMoistureDiffusivityMeasure;
- // C++ wrapper type for IfcBooleanOperator
- typedef ENUMERATION IfcBooleanOperator;
- // C++ wrapper type for IfcPropertySourceEnum
- typedef ENUMERATION IfcPropertySourceEnum;
- // C++ wrapper type for IfcTimeStamp
- typedef INTEGER IfcTimeStamp;
- // C++ wrapper type for IfcMaterialSelect
- typedef SELECT IfcMaterialSelect;
- // C++ wrapper type for IfcGloballyUniqueId
- typedef STRING IfcGloballyUniqueId;
- // C++ wrapper type for IfcReflectanceMethodEnum
- typedef ENUMERATION IfcReflectanceMethodEnum;
- // C++ wrapper type for IfcVaporPermeabilityMeasure
- typedef REAL IfcVaporPermeabilityMeasure;
- // C++ wrapper type for IfcTimeSeriesScheduleTypeEnum
- typedef ENUMERATION IfcTimeSeriesScheduleTypeEnum;
- // C++ wrapper type for IfcLinearMomentMeasure
- typedef REAL IfcLinearMomentMeasure;
- // C++ wrapper type for IfcGeometricSetSelect
- typedef SELECT IfcGeometricSetSelect;
+ // C++ wrapper type for IfcRadioActivityMeasure
+ typedef REAL IfcRadioActivityMeasure;
+ // C++ wrapper type for IfcRatioMeasure
+ typedef REAL IfcRatioMeasure;
+ // C++ wrapper type for IfcReal
+ typedef REAL IfcReal;
+ // C++ wrapper type for IfcRotationalFrequencyMeasure
+ typedef REAL IfcRotationalFrequencyMeasure;
+ // C++ wrapper type for IfcRotationalMassMeasure
+ typedef REAL IfcRotationalMassMeasure;
+ // C++ wrapper type for IfcRotationalStiffnessMeasure
+ typedef REAL IfcRotationalStiffnessMeasure;
+ // C++ wrapper type for IfcSecondInMinute
+ typedef REAL IfcSecondInMinute;
// C++ wrapper type for IfcSectionModulusMeasure
typedef REAL IfcSectionModulusMeasure;
- // C++ wrapper type for IfcBSplineCurveForm
- typedef ENUMERATION IfcBSplineCurveForm;
- // C++ wrapper type for IfcDimensionExtentUsage
- typedef ENUMERATION IfcDimensionExtentUsage;
+ // C++ wrapper type for IfcSectionalAreaIntegralMeasure
+ typedef REAL IfcSectionalAreaIntegralMeasure;
+ // C++ wrapper type for IfcShearModulusMeasure
+ typedef REAL IfcShearModulusMeasure;
+ // C++ wrapper type for IfcSolidAngleMeasure
+ typedef REAL IfcSolidAngleMeasure;
+ // C++ wrapper type for IfcSoundPowerMeasure
+ typedef REAL IfcSoundPowerMeasure;
+ // C++ wrapper type for IfcSoundPressureMeasure
+ typedef REAL IfcSoundPressureMeasure;
+ // C++ wrapper type for IfcSpecificHeatCapacityMeasure
+ typedef REAL IfcSpecificHeatCapacityMeasure;
+ // C++ wrapper type for IfcSpecularExponent
+ typedef REAL IfcSpecularExponent;
+ // C++ wrapper type for IfcSpecularRoughness
+ typedef REAL IfcSpecularRoughness;
+ // C++ wrapper type for IfcTemperatureGradientMeasure
+ typedef REAL IfcTemperatureGradientMeasure;
+ // C++ wrapper type for IfcText
+ typedef STRING IfcText;
+ // C++ wrapper type for IfcTextAlignment
+ typedef STRING IfcTextAlignment;
+ // C++ wrapper type for IfcTextDecoration
+ typedef STRING IfcTextDecoration;
+ // C++ wrapper type for IfcTextFontName
+ typedef STRING IfcTextFontName;
+ // C++ wrapper type for IfcTextTransformation
+ typedef STRING IfcTextTransformation;
+ // C++ wrapper type for IfcThermalAdmittanceMeasure
+ typedef REAL IfcThermalAdmittanceMeasure;
+ // C++ wrapper type for IfcThermalConductivityMeasure
+ typedef REAL IfcThermalConductivityMeasure;
// C++ wrapper type for IfcThermalExpansionCoefficientMeasure
typedef REAL IfcThermalExpansionCoefficientMeasure;
- // C++ wrapper type for IfcHourInDay
- typedef INTEGER IfcHourInDay;
- // C++ wrapper type for IfcLinearVelocityMeasure
- typedef REAL IfcLinearVelocityMeasure;
+ // C++ wrapper type for IfcThermalResistanceMeasure
+ typedef REAL IfcThermalResistanceMeasure;
+ // C++ wrapper type for IfcThermalTransmittanceMeasure
+ typedef REAL IfcThermalTransmittanceMeasure;
+ // C++ wrapper type for IfcThermodynamicTemperatureMeasure
+ typedef REAL IfcThermodynamicTemperatureMeasure;
+ // C++ wrapper type for IfcTimeMeasure
+ typedef REAL IfcTimeMeasure;
+ // C++ wrapper type for IfcTimeStamp
+ typedef INTEGER IfcTimeStamp;
// C++ wrapper type for IfcTorqueMeasure
typedef REAL IfcTorqueMeasure;
- // C++ wrapper type for IfcTemperatureGradientMeasure
- typedef REAL IfcTemperatureGradientMeasure;
- // C++ wrapper type for IfcFillStyleSelect
- typedef SELECT IfcFillStyleSelect;
- // C++ wrapper type for IfcElectricChargeMeasure
- typedef REAL IfcElectricChargeMeasure;
- // C++ wrapper type for IfcHeatExchangerTypeEnum
- typedef ENUMERATION IfcHeatExchangerTypeEnum;
- // C++ wrapper type for IfcElectricCurrentEnum
- typedef ENUMERATION IfcElectricCurrentEnum;
- // C++ wrapper type for IfcDaylightSavingHour
- typedef INTEGER IfcDaylightSavingHour;
- // C++ wrapper type for IfcShell
- typedef SELECT IfcShell;
- // C++ wrapper type for IfcDoseEquivalentMeasure
- typedef REAL IfcDoseEquivalentMeasure;
- // C++ wrapper type for IfcProjectOrderTypeEnum
- typedef ENUMERATION IfcProjectOrderTypeEnum;
- // C++ wrapper type for IfcDerivedMeasureValue
- typedef SELECT IfcDerivedMeasureValue;
- // C++ wrapper type for IfcLightDistributionCurveEnum
- typedef ENUMERATION IfcLightDistributionCurveEnum;
+ // C++ wrapper type for IfcVaporPermeabilityMeasure
+ typedef REAL IfcVaporPermeabilityMeasure;
+ // C++ wrapper type for IfcVolumeMeasure
+ typedef REAL IfcVolumeMeasure;
+ // C++ wrapper type for IfcVolumetricFlowRateMeasure
+ typedef REAL IfcVolumetricFlowRateMeasure;
+ // C++ wrapper type for IfcWarpingConstantMeasure
+ typedef REAL IfcWarpingConstantMeasure;
// C++ wrapper type for IfcWarpingMomentMeasure
typedef REAL IfcWarpingMomentMeasure;
- // C++ wrapper type for IfcMemberTypeEnum
- typedef ENUMERATION IfcMemberTypeEnum;
- // C++ wrapper type for IfcSoundPowerMeasure
- typedef REAL IfcSoundPowerMeasure;
- // C++ wrapper type for IfcTextAlignment
- typedef STRING IfcTextAlignment;
- // C++ wrapper type for IfcCurveOrEdgeCurve
- typedef SELECT IfcCurveOrEdgeCurve;
- // C++ wrapper type for IfcMassFlowRateMeasure
- typedef REAL IfcMassFlowRateMeasure;
- // C++ wrapper type for IfcIsothermalMoistureCapacityMeasure
- typedef REAL IfcIsothermalMoistureCapacityMeasure;
- // C++ wrapper type for IfcCsgSelect
- typedef SELECT IfcCsgSelect;
- // C++ wrapper type for IfcCoolingTowerTypeEnum
- typedef ENUMERATION IfcCoolingTowerTypeEnum;
- // C++ wrapper type for IfcMassMeasure
- typedef REAL IfcMassMeasure;
- // C++ wrapper type for IfcPileConstructionEnum
- typedef ENUMERATION IfcPileConstructionEnum;
- // C++ wrapper type for IfcDoorStyleOperationEnum
- typedef ENUMERATION IfcDoorStyleOperationEnum;
- // C++ wrapper type for IfcFlowDirectionEnum
- typedef ENUMERATION IfcFlowDirectionEnum;
- // C++ wrapper type for IfcThermalLoadSourceEnum
- typedef ENUMERATION IfcThermalLoadSourceEnum;
- // C++ wrapper type for IfcLengthMeasure
- typedef REAL IfcLengthMeasure;
- // C++ wrapper type for IfcConstraintEnum
- typedef ENUMERATION IfcConstraintEnum;
- // C++ wrapper type for IfcAxis2Placement
- typedef SELECT IfcAxis2Placement;
- // C++ wrapper type for IfcLoadGroupTypeEnum
- typedef ENUMERATION IfcLoadGroupTypeEnum;
- // C++ wrapper type for IfcValue
- typedef SELECT IfcValue;
- // C++ wrapper type for IfcReinforcingBarSurfaceEnum
- typedef ENUMERATION IfcReinforcingBarSurfaceEnum;
- // C++ wrapper type for IfcProjectOrderRecordTypeEnum
- typedef ENUMERATION IfcProjectOrderRecordTypeEnum;
- // C++ wrapper type for IfcDateTimeSelect
- typedef SELECT IfcDateTimeSelect;
- // C++ wrapper type for IfcStructuralSurfaceTypeEnum
- typedef ENUMERATION IfcStructuralSurfaceTypeEnum;
- // C++ wrapper type for IfcPermeableCoveringOperationEnum
- typedef ENUMERATION IfcPermeableCoveringOperationEnum;
- // C++ wrapper type for IfcFontWeight
- typedef STRING IfcFontWeight;
- // C++ wrapper type for IfcPHMeasure
- typedef REAL IfcPHMeasure;
- // C++ wrapper type for IfcDescriptiveMeasure
- typedef STRING IfcDescriptiveMeasure;
- // C++ wrapper type for IfcCurveStyleFontSelect
- typedef SELECT IfcCurveStyleFontSelect;
- // C++ wrapper type for IfcUnit
- typedef SELECT IfcUnit;
- // C++ wrapper type for IfcHatchLineDistanceSelect
- typedef SELECT IfcHatchLineDistanceSelect;
- // C++ wrapper type for IfcTextStyleSelect
- typedef SELECT IfcTextStyleSelect;
- // C++ wrapper type for IfcMetricValueSelect
- typedef SELECT IfcMetricValueSelect;
- // C++ wrapper type for IfcVectorOrDirection
- typedef SELECT IfcVectorOrDirection;
- // C++ wrapper type for IfcAssemblyPlaceEnum
- typedef ENUMERATION IfcAssemblyPlaceEnum;
+ // C++ wrapper type for IfcYearNumber
+ typedef INTEGER IfcYearNumber;
+ // C++ wrapper type for IfcActionSourceTypeEnum
+ typedef ENUMERATION IfcActionSourceTypeEnum;
+ // C++ wrapper type for IfcActionTypeEnum
+ typedef ENUMERATION IfcActionTypeEnum;
+ // C++ wrapper type for IfcActuatorTypeEnum
+ typedef ENUMERATION IfcActuatorTypeEnum;
+ // C++ wrapper type for IfcAddressTypeEnum
+ typedef ENUMERATION IfcAddressTypeEnum;
+ // C++ wrapper type for IfcAheadOrBehind
+ typedef ENUMERATION IfcAheadOrBehind;
+ // C++ wrapper type for IfcAirTerminalBoxTypeEnum
+ typedef ENUMERATION IfcAirTerminalBoxTypeEnum;
// C++ wrapper type for IfcAirTerminalTypeEnum
typedef ENUMERATION IfcAirTerminalTypeEnum;
- // C++ wrapper type for IfcCoveringTypeEnum
- typedef ENUMERATION IfcCoveringTypeEnum;
- // C++ wrapper type for IfcPlanarForceMeasure
- typedef REAL IfcPlanarForceMeasure;
- // C++ wrapper type for IfcValveTypeEnum
- typedef ENUMERATION IfcValveTypeEnum;
+ // C++ wrapper type for IfcAirToAirHeatRecoveryTypeEnum
+ typedef ENUMERATION IfcAirToAirHeatRecoveryTypeEnum;
// C++ wrapper type for IfcAlarmTypeEnum
typedef ENUMERATION IfcAlarmTypeEnum;
- // C++ wrapper type for IfcDynamicViscosityMeasure
- typedef REAL IfcDynamicViscosityMeasure;
- // C++ wrapper type for IfcCurrencyEnum
- typedef ENUMERATION IfcCurrencyEnum;
- // C++ wrapper type for IfcModulusOfRotationalSubgradeReactionMeasure
- typedef REAL IfcModulusOfRotationalSubgradeReactionMeasure;
+ // C++ wrapper type for IfcAnalysisModelTypeEnum
+ typedef ENUMERATION IfcAnalysisModelTypeEnum;
+ // C++ wrapper type for IfcAnalysisTheoryTypeEnum
+ typedef ENUMERATION IfcAnalysisTheoryTypeEnum;
+ // C++ wrapper type for IfcArithmeticOperatorEnum
+ typedef ENUMERATION IfcArithmeticOperatorEnum;
+ // C++ wrapper type for IfcAssemblyPlaceEnum
+ typedef ENUMERATION IfcAssemblyPlaceEnum;
+ // C++ wrapper type for IfcBSplineCurveForm
+ typedef ENUMERATION IfcBSplineCurveForm;
+ // C++ wrapper type for IfcBeamTypeEnum
+ typedef ENUMERATION IfcBeamTypeEnum;
+ // C++ wrapper type for IfcBenchmarkEnum
+ typedef ENUMERATION IfcBenchmarkEnum;
+ // C++ wrapper type for IfcBoilerTypeEnum
+ typedef ENUMERATION IfcBoilerTypeEnum;
+ // C++ wrapper type for IfcBooleanOperator
+ typedef ENUMERATION IfcBooleanOperator;
+ // C++ wrapper type for IfcBuildingElementProxyTypeEnum
+ typedef ENUMERATION IfcBuildingElementProxyTypeEnum;
// C++ wrapper type for IfcCableCarrierFittingTypeEnum
typedef ENUMERATION IfcCableCarrierFittingTypeEnum;
- // C++ wrapper type for IfcBoolean
- typedef BOOLEAN IfcBoolean;
- // C++ wrapper type for IfcActionSourceTypeEnum
- typedef ENUMERATION IfcActionSourceTypeEnum;
- // C++ wrapper type for IfcStructuralActivityAssignmentSelect
- typedef SELECT IfcStructuralActivityAssignmentSelect;
+ // C++ wrapper type for IfcCableCarrierSegmentTypeEnum
+ typedef ENUMERATION IfcCableCarrierSegmentTypeEnum;
+ // C++ wrapper type for IfcCableSegmentTypeEnum
+ typedef ENUMERATION IfcCableSegmentTypeEnum;
+ // C++ wrapper type for IfcChangeActionEnum
+ typedef ENUMERATION IfcChangeActionEnum;
+ // C++ wrapper type for IfcChillerTypeEnum
+ typedef ENUMERATION IfcChillerTypeEnum;
+ // C++ wrapper type for IfcCoilTypeEnum
+ typedef ENUMERATION IfcCoilTypeEnum;
+ // C++ wrapper type for IfcColumnTypeEnum
+ typedef ENUMERATION IfcColumnTypeEnum;
+ // C++ wrapper type for IfcCompressorTypeEnum
+ typedef ENUMERATION IfcCompressorTypeEnum;
+ // C++ wrapper type for IfcCondenserTypeEnum
+ typedef ENUMERATION IfcCondenserTypeEnum;
+ // C++ wrapper type for IfcConnectionTypeEnum
+ typedef ENUMERATION IfcConnectionTypeEnum;
+ // C++ wrapper type for IfcConstraintEnum
+ typedef ENUMERATION IfcConstraintEnum;
+ // C++ wrapper type for IfcControllerTypeEnum
+ typedef ENUMERATION IfcControllerTypeEnum;
+ // C++ wrapper type for IfcCooledBeamTypeEnum
+ typedef ENUMERATION IfcCooledBeamTypeEnum;
+ // C++ wrapper type for IfcCoolingTowerTypeEnum
+ typedef ENUMERATION IfcCoolingTowerTypeEnum;
+ // C++ wrapper type for IfcCostScheduleTypeEnum
+ typedef ENUMERATION IfcCostScheduleTypeEnum;
+ // C++ wrapper type for IfcCoveringTypeEnum
+ typedef ENUMERATION IfcCoveringTypeEnum;
+ // C++ wrapper type for IfcCurrencyEnum
+ typedef ENUMERATION IfcCurrencyEnum;
+ // C++ wrapper type for IfcCurtainWallTypeEnum
+ typedef ENUMERATION IfcCurtainWallTypeEnum;
+ // C++ wrapper type for IfcDamperTypeEnum
+ typedef ENUMERATION IfcDamperTypeEnum;
+ // C++ wrapper type for IfcDataOriginEnum
+ typedef ENUMERATION IfcDataOriginEnum;
+ // C++ wrapper type for IfcDerivedUnitEnum
+ typedef ENUMERATION IfcDerivedUnitEnum;
+ // C++ wrapper type for IfcDimensionExtentUsage
+ typedef ENUMERATION IfcDimensionExtentUsage;
+ // C++ wrapper type for IfcDirectionSenseEnum
+ typedef ENUMERATION IfcDirectionSenseEnum;
// C++ wrapper type for IfcDistributionChamberElementTypeEnum
typedef ENUMERATION IfcDistributionChamberElementTypeEnum;
- // C++ wrapper type for IfcEvaporativeCoolerTypeEnum
- typedef ENUMERATION IfcEvaporativeCoolerTypeEnum;
- // C++ wrapper type for IfcMagneticFluxDensityMeasure
- typedef REAL IfcMagneticFluxDensityMeasure;
- // C++ wrapper type for IfcLightDistributionDataSourceSelect
- typedef SELECT IfcLightDistributionDataSourceSelect;
- // C++ wrapper type for IfcTubeBundleTypeEnum
- typedef ENUMERATION IfcTubeBundleTypeEnum;
- // C++ wrapper type for IfcAccelerationMeasure
- typedef REAL IfcAccelerationMeasure;
- // C++ wrapper type for IfcBoilerTypeEnum
- typedef ENUMERATION IfcBoilerTypeEnum;
- // C++ wrapper type for IfcRampTypeEnum
- typedef ENUMERATION IfcRampTypeEnum;
- // C++ wrapper type for IfcLuminousIntensityDistributionMeasure
- typedef REAL IfcLuminousIntensityDistributionMeasure;
- // C++ wrapper type for IfcTrimmingPreference
- typedef ENUMERATION IfcTrimmingPreference;
- // C++ wrapper type for IfcSpecificHeatCapacityMeasure
- typedef REAL IfcSpecificHeatCapacityMeasure;
- // C++ wrapper type for IfcAmountOfSubstanceMeasure
- typedef REAL IfcAmountOfSubstanceMeasure;
- // C++ wrapper type for IfcRoleEnum
- typedef ENUMERATION IfcRoleEnum;
// C++ wrapper type for IfcDocumentConfidentialityEnum
typedef ENUMERATION IfcDocumentConfidentialityEnum;
- // C++ wrapper type for IfcFrequencyMeasure
- typedef REAL IfcFrequencyMeasure;
- // C++ wrapper type for IfcSectionTypeEnum
- typedef ENUMERATION IfcSectionTypeEnum;
- // C++ wrapper type for IfcElementAssemblyTypeEnum
- typedef ENUMERATION IfcElementAssemblyTypeEnum;
- // C++ wrapper type for IfcFootingTypeEnum
- typedef ENUMERATION IfcFootingTypeEnum;
- // C++ wrapper type for IfcLayeredItem
- typedef SELECT IfcLayeredItem;
- // C++ wrapper type for IfcCableSegmentTypeEnum
- typedef ENUMERATION IfcCableSegmentTypeEnum;
- // C++ wrapper type for IfcDefinedSymbolSelect
- typedef SELECT IfcDefinedSymbolSelect;
- // C++ wrapper type for IfcBuildingElementProxyTypeEnum
- typedef ENUMERATION IfcBuildingElementProxyTypeEnum;
+ // C++ wrapper type for IfcDocumentStatusEnum
+ typedef ENUMERATION IfcDocumentStatusEnum;
+ // C++ wrapper type for IfcDoorPanelOperationEnum
+ typedef ENUMERATION IfcDoorPanelOperationEnum;
+ // C++ wrapper type for IfcDoorPanelPositionEnum
+ typedef ENUMERATION IfcDoorPanelPositionEnum;
+ // C++ wrapper type for IfcDoorStyleConstructionEnum
+ typedef ENUMERATION IfcDoorStyleConstructionEnum;
+ // C++ wrapper type for IfcDoorStyleOperationEnum
+ typedef ENUMERATION IfcDoorStyleOperationEnum;
+ // C++ wrapper type for IfcDuctFittingTypeEnum
+ typedef ENUMERATION IfcDuctFittingTypeEnum;
+ // C++ wrapper type for IfcDuctSegmentTypeEnum
+ typedef ENUMERATION IfcDuctSegmentTypeEnum;
+ // C++ wrapper type for IfcDuctSilencerTypeEnum
+ typedef ENUMERATION IfcDuctSilencerTypeEnum;
+ // C++ wrapper type for IfcElectricApplianceTypeEnum
+ typedef ENUMERATION IfcElectricApplianceTypeEnum;
+ // C++ wrapper type for IfcElectricCurrentEnum
+ typedef ENUMERATION IfcElectricCurrentEnum;
+ // C++ wrapper type for IfcElectricDistributionPointFunctionEnum
+ typedef ENUMERATION IfcElectricDistributionPointFunctionEnum;
+ // C++ wrapper type for IfcElectricFlowStorageDeviceTypeEnum
+ typedef ENUMERATION IfcElectricFlowStorageDeviceTypeEnum;
// C++ wrapper type for IfcElectricGeneratorTypeEnum
typedef ENUMERATION IfcElectricGeneratorTypeEnum;
- // C++ wrapper type for IfcRotationalStiffnessMeasure
- typedef REAL IfcRotationalStiffnessMeasure;
- // C++ wrapper type for IfcSpaceHeaterTypeEnum
- typedef ENUMERATION IfcSpaceHeaterTypeEnum;
- // C++ wrapper type for IfcAreaMeasure
- typedef REAL IfcAreaMeasure;
- // C++ wrapper type for IfcLabel
- typedef STRING IfcLabel;
- // C++ wrapper type for IfcCostScheduleTypeEnum
- typedef ENUMERATION IfcCostScheduleTypeEnum;
- // C++ wrapper type for IfcSwitchingDeviceTypeEnum
- typedef ENUMERATION IfcSwitchingDeviceTypeEnum;
+ // C++ wrapper type for IfcElectricHeaterTypeEnum
+ typedef ENUMERATION IfcElectricHeaterTypeEnum;
+ // C++ wrapper type for IfcElectricMotorTypeEnum
+ typedef ENUMERATION IfcElectricMotorTypeEnum;
// C++ wrapper type for IfcElectricTimeControlTypeEnum
typedef ENUMERATION IfcElectricTimeControlTypeEnum;
+ // C++ wrapper type for IfcElementAssemblyTypeEnum
+ typedef ENUMERATION IfcElementAssemblyTypeEnum;
+ // C++ wrapper type for IfcElementCompositionEnum
+ typedef ENUMERATION IfcElementCompositionEnum;
+ // C++ wrapper type for IfcEnergySequenceEnum
+ typedef ENUMERATION IfcEnergySequenceEnum;
+ // C++ wrapper type for IfcEnvironmentalImpactCategoryEnum
+ typedef ENUMERATION IfcEnvironmentalImpactCategoryEnum;
+ // C++ wrapper type for IfcEvaporativeCoolerTypeEnum
+ typedef ENUMERATION IfcEvaporativeCoolerTypeEnum;
+ // C++ wrapper type for IfcEvaporatorTypeEnum
+ typedef ENUMERATION IfcEvaporatorTypeEnum;
+ // C++ wrapper type for IfcFanTypeEnum
+ typedef ENUMERATION IfcFanTypeEnum;
// C++ wrapper type for IfcFilterTypeEnum
typedef ENUMERATION IfcFilterTypeEnum;
- // C++ wrapper type for IfcPositiveLengthMeasure
- typedef REAL IfcPositiveLengthMeasure;
- // C++ wrapper type for IfcNullStyle
- typedef ENUMERATION IfcNullStyle;
- // C++ wrapper type for IfcConditionCriterionSelect
- typedef SELECT IfcConditionCriterionSelect;
- // C++ wrapper type for IfcShearModulusMeasure
- typedef REAL IfcShearModulusMeasure;
- // C++ wrapper type for IfcNormalisedRatioMeasure
- typedef REAL IfcNormalisedRatioMeasure;
- // C++ wrapper type for IfcDoorPanelOperationEnum
- typedef ENUMERATION IfcDoorPanelOperationEnum;
- // C++ wrapper type for IfcPointOrVertexPoint
- typedef SELECT IfcPointOrVertexPoint;
- // C++ wrapper type for IfcRoofTypeEnum
- typedef ENUMERATION IfcRoofTypeEnum;
- // C++ wrapper type for IfcCountMeasure
- typedef NUMBER IfcCountMeasure;
- // C++ wrapper type for IfcElectricConductanceMeasure
- typedef REAL IfcElectricConductanceMeasure;
- // C++ wrapper type for IfcProcedureTypeEnum
- typedef ENUMERATION IfcProcedureTypeEnum;
+ // C++ wrapper type for IfcFireSuppressionTerminalTypeEnum
+ typedef ENUMERATION IfcFireSuppressionTerminalTypeEnum;
+ // C++ wrapper type for IfcFlowDirectionEnum
+ typedef ENUMERATION IfcFlowDirectionEnum;
// C++ wrapper type for IfcFlowInstrumentTypeEnum
typedef ENUMERATION IfcFlowInstrumentTypeEnum;
- // C++ wrapper type for IfcElectricMotorTypeEnum
- typedef ENUMERATION IfcElectricMotorTypeEnum;
- // C++ wrapper type for IfcSurfaceSide
- typedef ENUMERATION IfcSurfaceSide;
- // C++ wrapper type for IfcStructuralCurveTypeEnum
- typedef ENUMERATION IfcStructuralCurveTypeEnum;
- // C++ wrapper type for IfcCondenserTypeEnum
- typedef ENUMERATION IfcCondenserTypeEnum;
- // C++ wrapper type for IfcLinearStiffnessMeasure
- typedef REAL IfcLinearStiffnessMeasure;
- // C++ wrapper type for IfcUnitEnum
- typedef ENUMERATION IfcUnitEnum;
+ // C++ wrapper type for IfcFlowMeterTypeEnum
+ typedef ENUMERATION IfcFlowMeterTypeEnum;
+ // C++ wrapper type for IfcFootingTypeEnum
+ typedef ENUMERATION IfcFootingTypeEnum;
+ // C++ wrapper type for IfcGasTerminalTypeEnum
+ typedef ENUMERATION IfcGasTerminalTypeEnum;
+ // C++ wrapper type for IfcGeometricProjectionEnum
+ typedef ENUMERATION IfcGeometricProjectionEnum;
+ // C++ wrapper type for IfcGlobalOrLocalEnum
+ typedef ENUMERATION IfcGlobalOrLocalEnum;
+ // C++ wrapper type for IfcHeatExchangerTypeEnum
+ typedef ENUMERATION IfcHeatExchangerTypeEnum;
+ // C++ wrapper type for IfcHumidifierTypeEnum
+ typedef ENUMERATION IfcHumidifierTypeEnum;
+ // C++ wrapper type for IfcInternalOrExternalEnum
+ typedef ENUMERATION IfcInternalOrExternalEnum;
+ // C++ wrapper type for IfcInventoryTypeEnum
+ typedef ENUMERATION IfcInventoryTypeEnum;
+ // C++ wrapper type for IfcJunctionBoxTypeEnum
+ typedef ENUMERATION IfcJunctionBoxTypeEnum;
+ // C++ wrapper type for IfcLampTypeEnum
+ typedef ENUMERATION IfcLampTypeEnum;
+ // C++ wrapper type for IfcLayerSetDirectionEnum
+ typedef ENUMERATION IfcLayerSetDirectionEnum;
+ // C++ wrapper type for IfcLightDistributionCurveEnum
+ typedef ENUMERATION IfcLightDistributionCurveEnum;
+ // C++ wrapper type for IfcLightEmissionSourceEnum
+ typedef ENUMERATION IfcLightEmissionSourceEnum;
+ // C++ wrapper type for IfcLightFixtureTypeEnum
+ typedef ENUMERATION IfcLightFixtureTypeEnum;
+ // C++ wrapper type for IfcLoadGroupTypeEnum
+ typedef ENUMERATION IfcLoadGroupTypeEnum;
+ // C++ wrapper type for IfcLogicalOperatorEnum
+ typedef ENUMERATION IfcLogicalOperatorEnum;
+ // C++ wrapper type for IfcMemberTypeEnum
+ typedef ENUMERATION IfcMemberTypeEnum;
+ // C++ wrapper type for IfcMotorConnectionTypeEnum
+ typedef ENUMERATION IfcMotorConnectionTypeEnum;
+ // C++ wrapper type for IfcNullStyle
+ typedef ENUMERATION IfcNullStyle;
+ // C++ wrapper type for IfcObjectTypeEnum
+ typedef ENUMERATION IfcObjectTypeEnum;
+ // C++ wrapper type for IfcObjectiveEnum
+ typedef ENUMERATION IfcObjectiveEnum;
// C++ wrapper type for IfcOccupantTypeEnum
typedef ENUMERATION IfcOccupantTypeEnum;
- // C++ wrapper type for IfcThermalLoadTypeEnum
- typedef ENUMERATION IfcThermalLoadTypeEnum;
- // C++ wrapper type for IfcReinforcingBarRoleEnum
- typedef ENUMERATION IfcReinforcingBarRoleEnum;
- // C++ wrapper type for IfcBenchmarkEnum
- typedef ENUMERATION IfcBenchmarkEnum;
- // C++ wrapper type for IfcPositivePlaneAngleMeasure
- typedef REAL IfcPositivePlaneAngleMeasure;
- // C++ wrapper type for IfcTextTransformation
- typedef STRING IfcTextTransformation;
- // C++ wrapper type for IfcDraughtingCalloutElement
- typedef SELECT IfcDraughtingCalloutElement;
- // C++ wrapper type for IfcRatioMeasure
- typedef REAL IfcRatioMeasure;
- // C++ wrapper type for IfcSolidAngleMeasure
- typedef REAL IfcSolidAngleMeasure;
+ // C++ wrapper type for IfcOutletTypeEnum
+ typedef ENUMERATION IfcOutletTypeEnum;
+ // C++ wrapper type for IfcPermeableCoveringOperationEnum
+ typedef ENUMERATION IfcPermeableCoveringOperationEnum;
+ // C++ wrapper type for IfcPhysicalOrVirtualEnum
+ typedef ENUMERATION IfcPhysicalOrVirtualEnum;
+ // C++ wrapper type for IfcPileConstructionEnum
+ typedef ENUMERATION IfcPileConstructionEnum;
+ // C++ wrapper type for IfcPileTypeEnum
+ typedef ENUMERATION IfcPileTypeEnum;
+ // C++ wrapper type for IfcPipeFittingTypeEnum
+ typedef ENUMERATION IfcPipeFittingTypeEnum;
// C++ wrapper type for IfcPipeSegmentTypeEnum
typedef ENUMERATION IfcPipeSegmentTypeEnum;
- // C++ wrapper type for IfcCableCarrierSegmentTypeEnum
- typedef ENUMERATION IfcCableCarrierSegmentTypeEnum;
- // C++ wrapper type for IfcColourOrFactor
- typedef SELECT IfcColourOrFactor;
- // C++ wrapper type for IfcIdentifier
- typedef STRING IfcIdentifier;
- // C++ wrapper type for IfcTendonTypeEnum
- typedef ENUMERATION IfcTendonTypeEnum;
- // C++ wrapper type for IfcControllerTypeEnum
- typedef ENUMERATION IfcControllerTypeEnum;
- // C++ wrapper type for IfcRadioActivityMeasure
- typedef REAL IfcRadioActivityMeasure;
- // C++ wrapper type for IfcTimeMeasure
- typedef REAL IfcTimeMeasure;
+ // C++ wrapper type for IfcPlateTypeEnum
+ typedef ENUMERATION IfcPlateTypeEnum;
+ // C++ wrapper type for IfcProcedureTypeEnum
+ typedef ENUMERATION IfcProcedureTypeEnum;
+ // C++ wrapper type for IfcProfileTypeEnum
+ typedef ENUMERATION IfcProfileTypeEnum;
+ // C++ wrapper type for IfcProjectOrderRecordTypeEnum
+ typedef ENUMERATION IfcProjectOrderRecordTypeEnum;
+ // C++ wrapper type for IfcProjectOrderTypeEnum
+ typedef ENUMERATION IfcProjectOrderTypeEnum;
+ // C++ wrapper type for IfcProjectedOrTrueLengthEnum
+ typedef ENUMERATION IfcProjectedOrTrueLengthEnum;
+ // C++ wrapper type for IfcPropertySourceEnum
+ typedef ENUMERATION IfcPropertySourceEnum;
+ // C++ wrapper type for IfcProtectiveDeviceTypeEnum
+ typedef ENUMERATION IfcProtectiveDeviceTypeEnum;
// C++ wrapper type for IfcPumpTypeEnum
typedef ENUMERATION IfcPumpTypeEnum;
- // C++ wrapper type for IfcElectricHeaterTypeEnum
- typedef ENUMERATION IfcElectricHeaterTypeEnum;
- // C++ wrapper type for IfcBeamTypeEnum
- typedef ENUMERATION IfcBeamTypeEnum;
- // C++ wrapper type for IfcStateEnum
- typedef ENUMERATION IfcStateEnum;
+ // C++ wrapper type for IfcRailingTypeEnum
+ typedef ENUMERATION IfcRailingTypeEnum;
+ // C++ wrapper type for IfcRampFlightTypeEnum
+ typedef ENUMERATION IfcRampFlightTypeEnum;
+ // C++ wrapper type for IfcRampTypeEnum
+ typedef ENUMERATION IfcRampTypeEnum;
+ // C++ wrapper type for IfcReflectanceMethodEnum
+ typedef ENUMERATION IfcReflectanceMethodEnum;
+ // C++ wrapper type for IfcReinforcingBarRoleEnum
+ typedef ENUMERATION IfcReinforcingBarRoleEnum;
+ // C++ wrapper type for IfcReinforcingBarSurfaceEnum
+ typedef ENUMERATION IfcReinforcingBarSurfaceEnum;
+ // C++ wrapper type for IfcResourceConsumptionEnum
+ typedef ENUMERATION IfcResourceConsumptionEnum;
+ // C++ wrapper type for IfcRibPlateDirectionEnum
+ typedef ENUMERATION IfcRibPlateDirectionEnum;
+ // C++ wrapper type for IfcRoleEnum
+ typedef ENUMERATION IfcRoleEnum;
+ // C++ wrapper type for IfcRoofTypeEnum
+ typedef ENUMERATION IfcRoofTypeEnum;
// C++ wrapper type for IfcSIPrefix
typedef ENUMERATION IfcSIPrefix;
- // C++ wrapper type for IfcNumericMeasure
- typedef NUMBER IfcNumericMeasure;
- // C++ wrapper type for IfcOutletTypeEnum
- typedef ENUMERATION IfcOutletTypeEnum;
- // C++ wrapper type for IfcCompoundPlaneAngleMeasure
- typedef ListOf< INTEGER, 3, 3 > IfcCompoundPlaneAngleMeasure;
+ // C++ wrapper type for IfcSIUnitName
+ typedef ENUMERATION IfcSIUnitName;
+ // C++ wrapper type for IfcSanitaryTerminalTypeEnum
+ typedef ENUMERATION IfcSanitaryTerminalTypeEnum;
+ // C++ wrapper type for IfcSectionTypeEnum
+ typedef ENUMERATION IfcSectionTypeEnum;
+ // C++ wrapper type for IfcSensorTypeEnum
+ typedef ENUMERATION IfcSensorTypeEnum;
+ // C++ wrapper type for IfcSequenceEnum
+ typedef ENUMERATION IfcSequenceEnum;
// C++ wrapper type for IfcServiceLifeFactorTypeEnum
typedef ENUMERATION IfcServiceLifeFactorTypeEnum;
- // C++ wrapper type for IfcLogicalOperatorEnum
- typedef ENUMERATION IfcLogicalOperatorEnum;
- // C++ wrapper type for IfcBooleanOperand
- typedef SELECT IfcBooleanOperand;
- // C++ wrapper type for IfcObjectReferenceSelect
- typedef SELECT IfcObjectReferenceSelect;
- // C++ wrapper type for IfcCooledBeamTypeEnum
- typedef ENUMERATION IfcCooledBeamTypeEnum;
- // C++ wrapper type for IfcDuctSilencerTypeEnum
- typedef ENUMERATION IfcDuctSilencerTypeEnum;
- // C++ wrapper type for IfcSectionalAreaIntegralMeasure
- typedef REAL IfcSectionalAreaIntegralMeasure;
- // C++ wrapper type for IfcFontVariant
- typedef STRING IfcFontVariant;
- // C++ wrapper type for IfcVolumetricFlowRateMeasure
- typedef REAL IfcVolumetricFlowRateMeasure;
- // C++ wrapper type for IfcPlateTypeEnum
- typedef ENUMERATION IfcPlateTypeEnum;
- // C++ wrapper type for IfcEnvironmentalImpactCategoryEnum
- typedef ENUMERATION IfcEnvironmentalImpactCategoryEnum;
+ // C++ wrapper type for IfcServiceLifeTypeEnum
+ typedef ENUMERATION IfcServiceLifeTypeEnum;
+ // C++ wrapper type for IfcSlabTypeEnum
+ typedef ENUMERATION IfcSlabTypeEnum;
+ // C++ wrapper type for IfcSoundScaleEnum
+ typedef ENUMERATION IfcSoundScaleEnum;
+ // C++ wrapper type for IfcSpaceHeaterTypeEnum
+ typedef ENUMERATION IfcSpaceHeaterTypeEnum;
+ // C++ wrapper type for IfcSpaceTypeEnum
+ typedef ENUMERATION IfcSpaceTypeEnum;
+ // C++ wrapper type for IfcStackTerminalTypeEnum
+ typedef ENUMERATION IfcStackTerminalTypeEnum;
+ // C++ wrapper type for IfcStairFlightTypeEnum
+ typedef ENUMERATION IfcStairFlightTypeEnum;
+ // C++ wrapper type for IfcStairTypeEnum
+ typedef ENUMERATION IfcStairTypeEnum;
+ // C++ wrapper type for IfcStateEnum
+ typedef ENUMERATION IfcStateEnum;
+ // C++ wrapper type for IfcStructuralCurveTypeEnum
+ typedef ENUMERATION IfcStructuralCurveTypeEnum;
+ // C++ wrapper type for IfcStructuralSurfaceTypeEnum
+ typedef ENUMERATION IfcStructuralSurfaceTypeEnum;
+ // C++ wrapper type for IfcSurfaceSide
+ typedef ENUMERATION IfcSurfaceSide;
+ // C++ wrapper type for IfcSurfaceTextureEnum
+ typedef ENUMERATION IfcSurfaceTextureEnum;
+ // C++ wrapper type for IfcSwitchingDeviceTypeEnum
+ typedef ENUMERATION IfcSwitchingDeviceTypeEnum;
+ // C++ wrapper type for IfcTankTypeEnum
+ typedef ENUMERATION IfcTankTypeEnum;
+ // C++ wrapper type for IfcTendonTypeEnum
+ typedef ENUMERATION IfcTendonTypeEnum;
+ // C++ wrapper type for IfcTextPath
+ typedef ENUMERATION IfcTextPath;
+ // C++ wrapper type for IfcThermalLoadSourceEnum
+ typedef ENUMERATION IfcThermalLoadSourceEnum;
+ // C++ wrapper type for IfcThermalLoadTypeEnum
+ typedef ENUMERATION IfcThermalLoadTypeEnum;
+ // C++ wrapper type for IfcTimeSeriesDataTypeEnum
+ typedef ENUMERATION IfcTimeSeriesDataTypeEnum;
+ // C++ wrapper type for IfcTimeSeriesScheduleTypeEnum
+ typedef ENUMERATION IfcTimeSeriesScheduleTypeEnum;
+ // C++ wrapper type for IfcTransformerTypeEnum
+ typedef ENUMERATION IfcTransformerTypeEnum;
+ // C++ wrapper type for IfcTransitionCode
+ typedef ENUMERATION IfcTransitionCode;
+ // C++ wrapper type for IfcTransportElementTypeEnum
+ typedef ENUMERATION IfcTransportElementTypeEnum;
+ // C++ wrapper type for IfcTrimmingPreference
+ typedef ENUMERATION IfcTrimmingPreference;
+ // C++ wrapper type for IfcTubeBundleTypeEnum
+ typedef ENUMERATION IfcTubeBundleTypeEnum;
+ // C++ wrapper type for IfcUnitEnum
+ typedef ENUMERATION IfcUnitEnum;
+ // C++ wrapper type for IfcUnitaryEquipmentTypeEnum
+ typedef ENUMERATION IfcUnitaryEquipmentTypeEnum;
+ // C++ wrapper type for IfcValveTypeEnum
+ typedef ENUMERATION IfcValveTypeEnum;
// C++ wrapper type for IfcVibrationIsolatorTypeEnum
typedef ENUMERATION IfcVibrationIsolatorTypeEnum;
- // C++ wrapper type for IfcThermodynamicTemperatureMeasure
- typedef REAL IfcThermodynamicTemperatureMeasure;
- // C++ wrapper type for IfcRotationalMassMeasure
- typedef REAL IfcRotationalMassMeasure;
- // C++ wrapper type for IfcSecondInMinute
- typedef REAL IfcSecondInMinute;
- // C++ wrapper type for IfcDayInMonthNumber
- typedef INTEGER IfcDayInMonthNumber;
- // C++ wrapper type for IfcDimensionCount
- typedef INTEGER IfcDimensionCount;
+ // C++ wrapper type for IfcWallTypeEnum
+ typedef ENUMERATION IfcWallTypeEnum;
+ // C++ wrapper type for IfcWasteTerminalTypeEnum
+ typedef ENUMERATION IfcWasteTerminalTypeEnum;
+ // C++ wrapper type for IfcWindowPanelOperationEnum
+ typedef ENUMERATION IfcWindowPanelOperationEnum;
+ // C++ wrapper type for IfcWindowPanelPositionEnum
+ typedef ENUMERATION IfcWindowPanelPositionEnum;
+ // C++ wrapper type for IfcWindowStyleConstructionEnum
+ typedef ENUMERATION IfcWindowStyleConstructionEnum;
// C++ wrapper type for IfcWindowStyleOperationEnum
typedef ENUMERATION IfcWindowStyleOperationEnum;
- // C++ wrapper type for IfcThermalResistanceMeasure
- typedef REAL IfcThermalResistanceMeasure;
+ // C++ wrapper type for IfcWorkControlTypeEnum
+ typedef ENUMERATION IfcWorkControlTypeEnum;
+ // C++ wrapper type for IfcActorSelect
+ typedef SELECT IfcActorSelect;
+ // C++ wrapper type for IfcAppliedValueSelect
+ typedef SELECT IfcAppliedValueSelect;
+ // C++ wrapper type for IfcAxis2Placement
+ typedef SELECT IfcAxis2Placement;
+ // C++ wrapper type for IfcBooleanOperand
+ typedef SELECT IfcBooleanOperand;
+ // C++ wrapper type for IfcCharacterStyleSelect
+ typedef SELECT IfcCharacterStyleSelect;
+ // C++ wrapper type for IfcClassificationNotationSelect
+ typedef SELECT IfcClassificationNotationSelect;
+ // C++ wrapper type for IfcColour
+ typedef SELECT IfcColour;
+ // C++ wrapper type for IfcColourOrFactor
+ typedef SELECT IfcColourOrFactor;
+ // C++ wrapper type for IfcConditionCriterionSelect
+ typedef SELECT IfcConditionCriterionSelect;
+ // C++ wrapper type for IfcCsgSelect
+ typedef SELECT IfcCsgSelect;
+ // C++ wrapper type for IfcCurveFontOrScaledCurveFontSelect
+ typedef SELECT IfcCurveFontOrScaledCurveFontSelect;
+ // C++ wrapper type for IfcCurveOrEdgeCurve
+ typedef SELECT IfcCurveOrEdgeCurve;
+ // C++ wrapper type for IfcCurveStyleFontSelect
+ typedef SELECT IfcCurveStyleFontSelect;
+ // C++ wrapper type for IfcDateTimeSelect
+ typedef SELECT IfcDateTimeSelect;
+ // C++ wrapper type for IfcDefinedSymbolSelect
+ typedef SELECT IfcDefinedSymbolSelect;
+ // C++ wrapper type for IfcDerivedMeasureValue
+ typedef SELECT IfcDerivedMeasureValue;
+ // C++ wrapper type for IfcDocumentSelect
+ typedef SELECT IfcDocumentSelect;
+ // C++ wrapper type for IfcDraughtingCalloutElement
+ typedef SELECT IfcDraughtingCalloutElement;
+ // C++ wrapper type for IfcFillAreaStyleTileShapeSelect
+ typedef SELECT IfcFillAreaStyleTileShapeSelect;
+ // C++ wrapper type for IfcFillStyleSelect
+ typedef SELECT IfcFillStyleSelect;
+ // C++ wrapper type for IfcGeometricSetSelect
+ typedef SELECT IfcGeometricSetSelect;
+ // C++ wrapper type for IfcHatchLineDistanceSelect
+ typedef SELECT IfcHatchLineDistanceSelect;
+ // C++ wrapper type for IfcLayeredItem
+ typedef SELECT IfcLayeredItem;
+ // C++ wrapper type for IfcLibrarySelect
+ typedef SELECT IfcLibrarySelect;
+ // C++ wrapper type for IfcLightDistributionDataSourceSelect
+ typedef SELECT IfcLightDistributionDataSourceSelect;
+ // C++ wrapper type for IfcMaterialSelect
+ typedef SELECT IfcMaterialSelect;
// C++ wrapper type for IfcMeasureValue
typedef SELECT IfcMeasureValue;
- // C++ wrapper type for IfcWindowPanelOperationEnum
- typedef ENUMERATION IfcWindowPanelOperationEnum;
- // C++ wrapper type for IfcChillerTypeEnum
- typedef ENUMERATION IfcChillerTypeEnum;
- // C++ wrapper type for IfcPositiveRatioMeasure
- typedef REAL IfcPositiveRatioMeasure;
- // C++ wrapper type for IfcInteger
- typedef INTEGER IfcInteger;
- // C++ wrapper type for IfcLogical
- typedef LOGICAL IfcLogical;
- // C++ wrapper type for IfcJunctionBoxTypeEnum
- typedef ENUMERATION IfcJunctionBoxTypeEnum;
- // C++ wrapper type for IfcAddressTypeEnum
- typedef ENUMERATION IfcAddressTypeEnum;
- // C++ wrapper type for IfcWasteTerminalTypeEnum
- typedef ENUMERATION IfcWasteTerminalTypeEnum;
- // C++ wrapper type for IfcTrimmingSelect
- typedef SELECT IfcTrimmingSelect;
- // C++ wrapper type for IfcLightEmissionSourceEnum
- typedef ENUMERATION IfcLightEmissionSourceEnum;
- // C++ wrapper type for IfcSoundScaleEnum
- typedef ENUMERATION IfcSoundScaleEnum;
- // C++ wrapper type for IfcLuminousFluxMeasure
- typedef REAL IfcLuminousFluxMeasure;
- // C++ wrapper type for IfcElectricResistanceMeasure
- typedef REAL IfcElectricResistanceMeasure;
- // C++ wrapper type for IfcIntegerCountRateMeasure
- typedef INTEGER IfcIntegerCountRateMeasure;
- // C++ wrapper type for IfcPhysicalOrVirtualEnum
- typedef ENUMERATION IfcPhysicalOrVirtualEnum;
- // C++ wrapper type for IfcMolecularWeightMeasure
- typedef REAL IfcMolecularWeightMeasure;
- // C++ wrapper type for IfcProfileTypeEnum
- typedef ENUMERATION IfcProfileTypeEnum;
- // C++ wrapper type for IfcBoxAlignment
- typedef STRING IfcBoxAlignment;
- // C++ wrapper type for IfcGlobalOrLocalEnum
- typedef ENUMERATION IfcGlobalOrLocalEnum;
- // C++ wrapper type for IfcSpecularRoughness
- typedef REAL IfcSpecularRoughness;
- // C++ wrapper type for IfcLampTypeEnum
- typedef ENUMERATION IfcLampTypeEnum;
- // C++ wrapper type for IfcPileTypeEnum
- typedef ENUMERATION IfcPileTypeEnum;
- // C++ wrapper type for IfcElectricCurrentMeasure
- typedef REAL IfcElectricCurrentMeasure;
- // C++ wrapper type for IfcFanTypeEnum
- typedef ENUMERATION IfcFanTypeEnum;
+ // C++ wrapper type for IfcMetricValueSelect
+ typedef SELECT IfcMetricValueSelect;
+ // C++ wrapper type for IfcObjectReferenceSelect
+ typedef SELECT IfcObjectReferenceSelect;
+ // C++ wrapper type for IfcOrientationSelect
+ typedef SELECT IfcOrientationSelect;
+ // C++ wrapper type for IfcPointOrVertexPoint
+ typedef SELECT IfcPointOrVertexPoint;
+ // C++ wrapper type for IfcPresentationStyleSelect
+ typedef SELECT IfcPresentationStyleSelect;
+ // C++ wrapper type for IfcShell
+ typedef SELECT IfcShell;
+ // C++ wrapper type for IfcSimpleValue
+ typedef SELECT IfcSimpleValue;
+ // C++ wrapper type for IfcSizeSelect
+ typedef SELECT IfcSizeSelect;
+ // C++ wrapper type for IfcSpecularHighlightSelect
+ typedef SELECT IfcSpecularHighlightSelect;
+ // C++ wrapper type for IfcStructuralActivityAssignmentSelect
+ typedef SELECT IfcStructuralActivityAssignmentSelect;
// C++ wrapper type for IfcSurfaceOrFaceSurface
typedef SELECT IfcSurfaceOrFaceSurface;
- // C++ wrapper type for IfcPipeFittingTypeEnum
- typedef ENUMERATION IfcPipeFittingTypeEnum;
- // C++ wrapper type for IfcTankTypeEnum
- typedef ENUMERATION IfcTankTypeEnum;
- // C++ wrapper type for IfcCurveFontOrScaledCurveFontSelect
- typedef SELECT IfcCurveFontOrScaledCurveFontSelect;
- // C++ wrapper type for IfcWindowStyleConstructionEnum
- typedef ENUMERATION IfcWindowStyleConstructionEnum;
- // C++ wrapper type for IfcAirTerminalBoxTypeEnum
- typedef ENUMERATION IfcAirTerminalBoxTypeEnum;
- // C++ wrapper type for IfcStairFlightTypeEnum
- typedef ENUMERATION IfcStairFlightTypeEnum;
- // C++ wrapper type for IfcLuminousIntensityMeasure
- typedef REAL IfcLuminousIntensityMeasure;
- // C++ wrapper type for IfcMotorConnectionTypeEnum
- typedef ENUMERATION IfcMotorConnectionTypeEnum;
- // C++ wrapper type for IfcPlaneAngleMeasure
- typedef REAL IfcPlaneAngleMeasure;
- // C++ wrapper type for IfcActuatorTypeEnum
- typedef ENUMERATION IfcActuatorTypeEnum;
- // C++ wrapper type for IfcColumnTypeEnum
- typedef ENUMERATION IfcColumnTypeEnum;
+ // C++ wrapper type for IfcSurfaceStyleElementSelect
+ typedef SELECT IfcSurfaceStyleElementSelect;
+ // C++ wrapper type for IfcSymbolStyleSelect
+ typedef SELECT IfcSymbolStyleSelect;
// C++ wrapper type for IfcTextFontSelect
typedef SELECT IfcTextFontSelect;
- // C++ wrapper type for IfcDoorPanelPositionEnum
- typedef ENUMERATION IfcDoorPanelPositionEnum;
- // C++ wrapper type for IfcCoilTypeEnum
- typedef ENUMERATION IfcCoilTypeEnum;
- // C++ wrapper type for IfcAngularVelocityMeasure
- typedef REAL IfcAngularVelocityMeasure;
- // C++ wrapper type for IfcAnalysisModelTypeEnum
- typedef ENUMERATION IfcAnalysisModelTypeEnum;
- // C++ wrapper type for IfcLibrarySelect
- typedef SELECT IfcLibrarySelect;
- // C++ wrapper type for IfcForceMeasure
- typedef REAL IfcForceMeasure;
- // C++ wrapper type for IfcFillAreaStyleTileShapeSelect
- typedef SELECT IfcFillAreaStyleTileShapeSelect;
- // C++ wrapper type for IfcElectricApplianceTypeEnum
- typedef ENUMERATION IfcElectricApplianceTypeEnum;
- // C++ wrapper type for IfcSurfaceTextureEnum
- typedef ENUMERATION IfcSurfaceTextureEnum;
- // C++ wrapper type for IfcCharacterStyleSelect
- typedef SELECT IfcCharacterStyleSelect;
- // C++ wrapper type for IfcEnergyMeasure
- typedef REAL IfcEnergyMeasure;
- // C++ wrapper type for IfcReal
- typedef REAL IfcReal;
- // C++ wrapper type for IfcCompressorTypeEnum
- typedef ENUMERATION IfcCompressorTypeEnum;
- // C++ wrapper type for IfcElectricDistributionPointFunctionEnum
- typedef ENUMERATION IfcElectricDistributionPointFunctionEnum;
+ // C++ wrapper type for IfcTextStyleSelect
+ typedef SELECT IfcTextStyleSelect;
+ // C++ wrapper type for IfcTrimmingSelect
+ typedef SELECT IfcTrimmingSelect;
+ // C++ wrapper type for IfcUnit
+ typedef SELECT IfcUnit;
+ // C++ wrapper type for IfcValue
+ typedef SELECT IfcValue;
+ // C++ wrapper type for IfcVectorOrDirection
+ typedef SELECT IfcVectorOrDirection;
- // ******************************************************************************
- // IFC Entities
- // ******************************************************************************
-
- struct IfcRoot;
- struct IfcObjectDefinition;
- struct IfcTypeObject;
- struct IfcTypeProduct;
- struct IfcElementType;
- struct IfcDistributionElementType;
- struct IfcDistributionFlowElementType;
- struct IfcFlowControllerType;
- struct IfcElectricTimeControlType;
- struct IfcRepresentation;
- struct IfcShapeModel;
- struct IfcTopologyRepresentation;
- struct IfcRelationship;
- struct IfcRelConnects;
- typedef NotImplemented IfcRelCoversSpaces; // (not currently used by Assimp)
- struct IfcFlowFittingType;
- struct IfcCableCarrierFittingType;
- typedef NotImplemented IfcStructuralConnectionCondition; // (not currently used by Assimp)
- typedef NotImplemented IfcSlippageConnectionCondition; // (not currently used by Assimp)
- struct IfcEnergyConversionDeviceType;
- struct IfcCoilType;
- struct IfcObject;
- struct IfcControl;
- struct IfcPerformanceHistory;
- struct IfcRepresentationItem;
- struct IfcGeometricRepresentationItem;
- struct IfcTextLiteral;
- struct IfcTextLiteralWithExtent;
- struct IfcProductRepresentation;
- struct IfcProduct;
- struct IfcElement;
- struct IfcDistributionElement;
- struct IfcDistributionFlowElement;
- struct IfcCurve;
- struct IfcBoundedCurve;
- struct IfcCompositeCurve;
- struct Ifc2DCompositeCurve;
- typedef NotImplemented IfcBoundaryCondition; // (not currently used by Assimp)
- typedef NotImplemented IfcBoundaryFaceCondition; // (not currently used by Assimp)
- struct IfcCartesianTransformationOperator;
- struct IfcCartesianTransformationOperator3D;
- struct IfcProperty;
- struct IfcSimpleProperty;
- struct IfcPropertyEnumeratedValue;
- typedef NotImplemented IfcPresentationLayerAssignment; // (not currently used by Assimp)
- typedef NotImplemented IfcPresentationLayerWithStyle; // (not currently used by Assimp)
- struct IfcBuildingElementType;
- struct IfcStairFlightType;
- struct IfcSurface;
- struct IfcElementarySurface;
- struct IfcPlane;
- struct IfcBooleanResult;
- struct IfcBooleanClippingResult;
- struct IfcSolidModel;
- struct IfcManifoldSolidBrep;
- typedef NotImplemented IfcProfileProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcGeneralProfileProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralProfileProperties; // (not currently used by Assimp)
- struct IfcFlowTerminalType;
- struct IfcStackTerminalType;
- struct IfcStructuralItem;
- struct IfcStructuralConnection;
- struct IfcStructuralCurveConnection;
- struct IfcJunctionBoxType;
- typedef NotImplemented IfcRelAssociates; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesConstraint; // (not currently used by Assimp)
- struct IfcPropertyDefinition;
- struct IfcPropertySetDefinition;
- typedef NotImplemented IfcDoorPanelProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcConstraintRelationship; // (not currently used by Assimp)
- typedef NotImplemented IfcSpaceThermalLoadProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcLibraryInformation; // (not currently used by Assimp)
- struct IfcProcess;
- struct IfcTask;
- typedef NotImplemented IfcAppliedValue; // (not currently used by Assimp)
- typedef NotImplemented IfcEnvironmentalImpactValue; // (not currently used by Assimp)
- struct IfcRelFillsElement;
- struct IfcProcedure;
- typedef NotImplemented IfcStructuralLoad; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralLoadStatic; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralLoadSingleDisplacement; // (not currently used by Assimp)
- struct IfcProxy;
- typedef NotImplemented IfcCurveStyleFont; // (not currently used by Assimp)
- struct IfcResource;
- struct IfcConstructionResource;
- struct IfcSubContractResource;
- typedef NotImplemented IfcCalendarDate; // (not currently used by Assimp)
- typedef NotImplemented IfcDocumentElectronicFormat; // (not currently used by Assimp)
- struct IfcRelContainedInSpatialStructure;
- typedef NotImplemented IfcMaterialProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcProductsOfCombustionProperties; // (not currently used by Assimp)
- struct IfcTopologicalRepresentationItem;
- struct IfcEdge;
- struct IfcEdgeCurve;
- struct IfcPlateType;
- struct IfcObjectPlacement;
- struct IfcGridPlacement;
- struct IfcFireSuppressionTerminalType;
- typedef NotImplemented IfcMechanicalMaterialProperties; // (not currently used by Assimp)
- struct IfcFlowStorageDevice;
- typedef NotImplemented IfcPerson; // (not currently used by Assimp)
- struct IfcSweptSurface;
- struct IfcSurfaceOfRevolution;
- struct IfcOrientedEdge;
- typedef NotImplemented IfcOwnerHistory; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssigns; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssignsToActor; // (not currently used by Assimp)
- struct IfcDirection;
- typedef NotImplemented IfcReinforcementBarProperties; // (not currently used by Assimp)
- struct IfcProfileDef;
- struct IfcParameterizedProfileDef;
- struct IfcCShapeProfileDef;
- struct IfcFeatureElement;
- struct IfcFeatureElementSubtraction;
- struct IfcEdgeFeature;
- struct IfcChamferEdgeFeature;
- struct IfcBuildingElement;
- struct IfcColumn;
- struct IfcPropertyReferenceValue;
- typedef NotImplemented IfcMaterialClassificationRelationship; // (not currently used by Assimp)
- struct IfcElectricMotorType;
- struct IfcSpatialStructureElementType;
- struct IfcSpaceType;
- typedef NotImplemented IfcExternalReference; // (not currently used by Assimp)
- typedef NotImplemented IfcExternallyDefinedHatchStyle; // (not currently used by Assimp)
- struct IfcColumnType;
- struct IfcCraneRailAShapeProfileDef;
- struct IfcCondenserType;
- typedef NotImplemented IfcRelConnectsElements; // (not currently used by Assimp)
- typedef NotImplemented IfcRelConnectsWithRealizingElements; // (not currently used by Assimp)
- struct IfcCircleProfileDef;
- struct IfcCircleHollowProfileDef;
- typedef NotImplemented IfcOrganizationRelationship; // (not currently used by Assimp)
- struct IfcPlacement;
- struct IfcAxis2Placement3D;
- struct IfcPresentationStyle;
- typedef NotImplemented IfcCurveStyle; // (not currently used by Assimp)
- struct IfcEquipmentElement;
- struct IfcCompositeCurveSegment;
- struct IfcRectangleProfileDef;
- typedef NotImplemented IfcPhysicalQuantity; // (not currently used by Assimp)
- typedef NotImplemented IfcPhysicalComplexQuantity; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesLibrary; // (not currently used by Assimp)
- typedef NotImplemented IfcRelSequence; // (not currently used by Assimp)
- struct IfcBuildingElementProxy;
- struct IfcDistributionControlElementType;
- struct IfcFlowInstrumentType;
- struct IfcDraughtingCallout;
- struct IfcDimensionCurveDirectedCallout;
- struct IfcLinearDimension;
- struct IfcElementAssembly;
- typedef NotImplemented IfcDraughtingCalloutRelationship; // (not currently used by Assimp)
- struct IfcCsgPrimitive3D;
- struct IfcRightCircularCone;
- typedef NotImplemented IfcExternallyDefinedSurfaceStyle; // (not currently used by Assimp)
- struct IfcProjectOrder;
- typedef NotImplemented IfcPropertyConstraintRelationship; // (not currently used by Assimp)
- struct IfcLShapeProfileDef;
- struct IfcAngularDimension;
- typedef NotImplemented IfcTextStyleForDefinedFont; // (not currently used by Assimp)
- struct IfcLocalPlacement;
- struct IfcSweptAreaSolid;
- struct IfcRevolvedAreaSolid;
- struct IfcStructuralSurfaceConnection;
- struct IfcRadiusDimension;
- struct IfcSweptDiskSolid;
- struct IfcHalfSpaceSolid;
- struct IfcPolygonalBoundedHalfSpace;
- struct IfcTimeSeriesSchedule;
- typedef NotImplemented IfcDimensionCalloutRelationship; // (not currently used by Assimp)
- struct IfcCooledBeamType;
- struct IfcProject;
- typedef NotImplemented IfcApprovalRelationship; // (not currently used by Assimp)
- struct IfcEvaporatorType;
- struct IfcLaborResource;
- typedef NotImplemented IfcStructuralLoadSingleDisplacementDistortion; // (not currently used by Assimp)
- struct IfcPropertyBoundedValue;
- struct IfcRampFlightType;
- struct IfcMember;
- typedef NotImplemented IfcStructuralLoadPlanarForce; // (not currently used by Assimp)
- struct IfcTubeBundleType;
- struct IfcValveType;
- typedef NotImplemented IfcExternallyDefinedTextFont; // (not currently used by Assimp)
- struct IfcTrimmedCurve;
- struct IfcRelDefines;
- struct IfcRelDefinesByProperties;
- typedef NotImplemented IfcRelAssignsToControl; // (not currently used by Assimp)
- struct IfcActor;
- struct IfcOccupant;
- struct IfcHumidifierType;
- struct IfcArbitraryOpenProfileDef;
- typedef NotImplemented IfcRelAssignsToProjectOrder; // (not currently used by Assimp)
- struct IfcPermit;
- struct IfcOffsetCurve3D;
- struct IfcLightSource;
- struct IfcLightSourcePositional;
- typedef NotImplemented IfcSurfaceTexture; // (not currently used by Assimp)
- typedef NotImplemented IfcBlobTexture; // (not currently used by Assimp)
- struct IfcCompositeProfileDef;
- typedef NotImplemented IfcDocumentInformation; // (not currently used by Assimp)
- typedef NotImplemented IfcSurfaceStyleLighting; // (not currently used by Assimp)
- typedef NotImplemented IfcPhysicalSimpleQuantity; // (not currently used by Assimp)
- typedef NotImplemented IfcQuantityArea; // (not currently used by Assimp)
- typedef NotImplemented IfcTimeSeries; // (not currently used by Assimp)
- typedef NotImplemented IfcClassificationNotation; // (not currently used by Assimp)
- struct IfcRamp;
- typedef NotImplemented IfcPreDefinedItem; // (not currently used by Assimp)
- typedef NotImplemented IfcPreDefinedCurveFont; // (not currently used by Assimp)
- typedef NotImplemented IfcPreDefinedColour; // (not currently used by Assimp)
- typedef NotImplemented IfcCurrencyRelationship; // (not currently used by Assimp)
- struct IfcFlowMovingDevice;
- struct IfcSpaceHeaterType;
- struct IfcLampType;
- struct IfcBuildingElementComponent;
- struct IfcReinforcingElement;
- struct IfcReinforcingBar;
- struct IfcElectricHeaterType;
- struct IfcTShapeProfileDef;
- typedef NotImplemented IfcConstraint; // (not currently used by Assimp)
- typedef NotImplemented IfcObjective; // (not currently used by Assimp)
- struct IfcStructuralActivity;
- struct IfcStructuralAction;
- typedef NotImplemented IfcTextureCoordinate; // (not currently used by Assimp)
- typedef NotImplemented IfcTextureMap; // (not currently used by Assimp)
- typedef NotImplemented IfcMonetaryUnit; // (not currently used by Assimp)
- typedef NotImplemented IfcQuantityTime; // (not currently used by Assimp)
- typedef NotImplemented IfcTableRow; // (not currently used by Assimp)
- typedef NotImplemented IfcLightDistributionData; // (not currently used by Assimp)
- struct IfcDuctFittingType;
- struct IfcCartesianTransformationOperator2D;
- struct IfcCartesianTransformationOperator2DnonUniform;
- typedef NotImplemented IfcClassificationNotationFacet; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesApproval; // (not currently used by Assimp)
- typedef NotImplemented IfcDraughtingPreDefinedCurveFont; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralLoadSingleForce; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralLoadSingleForceWarping; // (not currently used by Assimp)
- typedef NotImplemented IfcCurveStyleFontAndScaling; // (not currently used by Assimp)
- struct IfcVirtualElement;
- struct IfcRightCircularCylinder;
- struct IfcOutletType;
- struct IfcRelDecomposes;
- typedef NotImplemented IfcRelNests; // (not currently used by Assimp)
- struct IfcCovering;
- typedef NotImplemented IfcExternallyDefinedSymbol; // (not currently used by Assimp)
- typedef NotImplemented IfcIrregularTimeSeries; // (not currently used by Assimp)
- struct IfcPolyline;
- struct IfcPath;
- struct IfcElementComponent;
- struct IfcFastener;
- struct IfcMappedItem;
- typedef NotImplemented IfcMetric; // (not currently used by Assimp)
- typedef NotImplemented IfcDocumentReference; // (not currently used by Assimp)
- typedef NotImplemented IfcSectionProperties; // (not currently used by Assimp)
- struct IfcRectangularPyramid;
- typedef NotImplemented IfcRelReferencedInSpatialStructure; // (not currently used by Assimp)
- struct IfcCrewResource;
- struct IfcNamedUnit;
- struct IfcContextDependentUnit;
- struct IfcUnitaryEquipmentType;
- struct IfcRoof;
- typedef NotImplemented IfcRelAssignsTasks; // (not currently used by Assimp)
- struct IfcStructuralMember;
- typedef NotImplemented IfcRelConnectsPorts; // (not currently used by Assimp)
- struct IfcStyleModel;
- struct IfcStyledRepresentation;
- struct IfcSpatialStructureElement;
- struct IfcBuilding;
- struct IfcConnectedFaceSet;
- struct IfcOpenShell;
- struct IfcFacetedBrep;
- typedef NotImplemented IfcLocalTime; // (not currently used by Assimp)
- typedef NotImplemented IfcMechanicalConcreteMaterialProperties; // (not currently used by Assimp)
- struct IfcConic;
- struct IfcCoveringType;
- struct IfcRoundedRectangleProfileDef;
- struct IfcAirTerminalType;
- struct IfcFlowMovingDeviceType;
- struct IfcCompressorType;
- typedef NotImplemented IfcWindowPanelProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcPreDefinedSymbol; // (not currently used by Assimp)
- typedef NotImplemented IfcPreDefinedTerminatorSymbol; // (not currently used by Assimp)
- struct IfcIShapeProfileDef;
- struct IfcAsymmetricIShapeProfileDef;
- struct IfcControllerType;
- struct IfcRailing;
- struct IfcGroup;
- struct IfcAsset;
- struct IfcMaterialDefinitionRepresentation;
- typedef NotImplemented IfcCurveStyleFontPattern; // (not currently used by Assimp)
- typedef NotImplemented IfcApprovalPropertyRelationship; // (not currently used by Assimp)
- struct IfcRailingType;
- struct IfcWall;
- typedef NotImplemented IfcClassificationItem; // (not currently used by Assimp)
- struct IfcStructuralPointConnection;
- typedef NotImplemented IfcConnectionGeometry; // (not currently used by Assimp)
- typedef NotImplemented IfcConnectionPointGeometry; // (not currently used by Assimp)
- typedef NotImplemented IfcTimeSeriesValue; // (not currently used by Assimp)
- struct IfcPropertyListValue;
- struct IfcFurnitureStandard;
- typedef NotImplemented IfcRelSchedulesCostItems; // (not currently used by Assimp)
- struct IfcElectricGeneratorType;
- struct IfcDoor;
- struct IfcStyledItem;
- struct IfcAnnotationOccurrence;
- struct IfcAnnotationSymbolOccurrence;
- struct IfcArbitraryClosedProfileDef;
- struct IfcArbitraryProfileDefWithVoids;
- struct IfcLine;
- typedef NotImplemented IfcMaterialLayerSet; // (not currently used by Assimp)
- struct IfcFlowSegmentType;
- struct IfcAirTerminalBoxType;
- typedef NotImplemented IfcRelConnectsStructuralMember; // (not currently used by Assimp)
- struct IfcPropertySingleValue;
- struct IfcAlarmType;
- struct IfcEllipseProfileDef;
- struct IfcStair;
- typedef NotImplemented IfcPreDefinedTextFont; // (not currently used by Assimp)
- typedef NotImplemented IfcTextStyleFontModel; // (not currently used by Assimp)
- struct IfcSurfaceStyleShading;
- struct IfcPumpType;
- struct IfcDefinedSymbol;
- typedef NotImplemented IfcClassificationItemRelationship; // (not currently used by Assimp)
- typedef NotImplemented IfcGeneralMaterialProperties; // (not currently used by Assimp)
- struct IfcElementComponentType;
- struct IfcFastenerType;
- struct IfcMechanicalFastenerType;
- typedef NotImplemented IfcPermeableCoveringProperties; // (not currently used by Assimp)
- struct IfcFlowFitting;
- typedef NotImplemented IfcApproval; // (not currently used by Assimp)
- typedef NotImplemented IfcShapeAspect; // (not currently used by Assimp)
- typedef NotImplemented IfcConstraintClassificationRelationship; // (not currently used by Assimp)
- struct IfcLightSourceDirectional;
- struct IfcSurfaceStyle;
- typedef NotImplemented IfcRelConnectsStructuralActivity; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesProfileProperties; // (not currently used by Assimp)
- struct IfcAnnotationSurface;
- typedef NotImplemented IfcFuelProperties; // (not currently used by Assimp)
- struct IfcFlowController;
- typedef NotImplemented IfcFailureConnectionCondition; // (not currently used by Assimp)
- struct IfcBuildingStorey;
- struct IfcWorkControl;
- struct IfcWorkSchedule;
- typedef NotImplemented IfcTable; // (not currently used by Assimp)
- struct IfcDuctSegmentType;
- typedef NotImplemented IfcStructuralSteelProfileProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcDraughtingPreDefinedTextFont; // (not currently used by Assimp)
- struct IfcFace;
- struct IfcStructuralSurfaceMember;
- struct IfcStructuralSurfaceMemberVarying;
- struct IfcFaceSurface;
- typedef NotImplemented IfcClassification; // (not currently used by Assimp)
- typedef NotImplemented IfcMaterialList; // (not currently used by Assimp)
- struct IfcCostSchedule;
- typedef NotImplemented IfcCoordinatedUniversalTimeOffset; // (not currently used by Assimp)
- struct IfcPlanarExtent;
- struct IfcPlanarBox;
- typedef NotImplemented IfcFillAreaStyle; // (not currently used by Assimp)
- typedef NotImplemented IfcSectionReinforcementProperties; // (not currently used by Assimp)
- struct IfcColourSpecification;
- struct IfcVector;
- struct IfcBeam;
- struct IfcColourRgb;
- struct IfcStructuralPlanarAction;
- struct IfcStructuralPlanarActionVarying;
- struct IfcSite;
- struct IfcDiscreteAccessoryType;
- struct IfcVibrationIsolatorType;
- struct IfcEvaporativeCoolerType;
- struct IfcDistributionChamberElementType;
- struct IfcFeatureElementAddition;
- typedef NotImplemented IfcRelAssignsToResource; // (not currently used by Assimp)
- struct IfcStructuredDimensionCallout;
- struct IfcCoolingTowerType;
- struct IfcCenterLineProfileDef;
- typedef NotImplemented IfcTextureVertex; // (not currently used by Assimp)
- typedef NotImplemented IfcOrganization; // (not currently used by Assimp)
- struct IfcWindowStyle;
- struct IfcLightSourceGoniometric;
- typedef NotImplemented IfcRibPlateProfileProperties; // (not currently used by Assimp)
- struct IfcTransformerType;
- struct IfcMemberType;
- struct IfcSurfaceOfLinearExtrusion;
- struct IfcMotorConnectionType;
- struct IfcFlowTreatmentDeviceType;
- struct IfcDuctSilencerType;
- typedef NotImplemented IfcWindowLiningProperties; // (not currently used by Assimp)
- struct IfcFurnishingElementType;
- struct IfcSystemFurnitureElementType;
- typedef NotImplemented IfcConnectionPointEccentricity; // (not currently used by Assimp)
- struct IfcWasteTerminalType;
- struct IfcBSplineCurve;
- struct IfcBezierCurve;
- typedef NotImplemented IfcDocumentInformationRelationship; // (not currently used by Assimp)
- struct IfcActuatorType;
- struct IfcDistributionControlElement;
- struct IfcAnnotation;
- typedef NotImplemented IfcRelAssociatesDocument; // (not currently used by Assimp)
- typedef NotImplemented IfcDoorLiningProperties; // (not currently used by Assimp)
- struct IfcShellBasedSurfaceModel;
- struct IfcActionRequest;
- struct IfcExtrudedAreaSolid;
- struct IfcSystem;
- struct IfcFillAreaStyleHatching;
- struct IfcRelVoidsElement;
- typedef NotImplemented IfcRelConnectsPathElements; // (not currently used by Assimp)
- typedef NotImplemented IfcRelSpaceBoundary; // (not currently used by Assimp)
- struct IfcSurfaceCurveSweptAreaSolid;
- struct IfcCartesianTransformationOperator3DnonUniform;
- typedef NotImplemented IfcRelInteractionRequirements; // (not currently used by Assimp)
- struct IfcCurtainWallType;
- typedef NotImplemented IfcQuantityLength; // (not currently used by Assimp)
- struct IfcEquipmentStandard;
- struct IfcFlowStorageDeviceType;
- typedef NotImplemented IfcVirtualGridIntersection; // (not currently used by Assimp)
- struct IfcDiameterDimension;
- struct IfcSwitchingDeviceType;
- typedef NotImplemented IfcAddress; // (not currently used by Assimp)
- typedef NotImplemented IfcTelecomAddress; // (not currently used by Assimp)
- struct IfcWindow;
- typedef NotImplemented IfcMechanicalSteelMaterialProperties; // (not currently used by Assimp)
- struct IfcFlowTreatmentDevice;
- typedef NotImplemented IfcRelServicesBuildings; // (not currently used by Assimp)
- struct IfcChillerType;
- typedef NotImplemented IfcRelAssignsToProduct; // (not currently used by Assimp)
- struct IfcRectangleHollowProfileDef;
- typedef NotImplemented IfcEnergyProperties; // (not currently used by Assimp)
- struct IfcBoxedHalfSpace;
- struct IfcAxis2Placement2D;
- struct IfcSpaceProgram;
- struct IfcPoint;
- struct IfcCartesianPoint;
- struct IfcBoundedSurface;
- struct IfcLoop;
- struct IfcPolyLoop;
- typedef NotImplemented IfcPreDefinedPointMarkerSymbol; // (not currently used by Assimp)
- struct IfcTerminatorSymbol;
- struct IfcDimensionCurveTerminator;
- typedef NotImplemented IfcRelProjectsElement; // (not currently used by Assimp)
- struct IfcTrapeziumProfileDef;
- struct IfcRepresentationContext;
- struct IfcGeometricRepresentationContext;
- typedef NotImplemented IfcTextStyleWithBoxCharacteristics; // (not currently used by Assimp)
- struct IfcCurveBoundedPlane;
- typedef NotImplemented IfcQuantityCount; // (not currently used by Assimp)
- typedef NotImplemented IfcTimeSeriesReferenceRelationship; // (not currently used by Assimp)
- typedef NotImplemented IfcStructuralLoadTemperature; // (not currently used by Assimp)
- struct IfcSIUnit;
- struct IfcStructuralReaction;
- struct IfcStructuralPointReaction;
- struct IfcAxis1Placement;
- typedef NotImplemented IfcReinforcementDefinitionProperties; // (not currently used by Assimp)
- struct IfcElectricApplianceType;
- struct IfcSensorType;
- struct IfcFurnishingElement;
- struct IfcProtectiveDeviceType;
- struct IfcZShapeProfileDef;
- struct IfcScheduleTimeControl;
- struct IfcRepresentationMap;
- struct IfcClosedShell;
- struct IfcBuildingElementPart;
- typedef NotImplemented IfcDraughtingPreDefinedColour; // (not currently used by Assimp)
- typedef NotImplemented IfcPostalAddress; // (not currently used by Assimp)
- struct IfcBlock;
- struct IfcLightFixtureType;
- struct IfcOpeningElement;
- struct IfcLightSourceSpot;
- struct IfcTendonAnchor;
- typedef NotImplemented IfcSurfaceStyleRefraction; // (not currently used by Assimp)
- struct IfcElectricFlowStorageDeviceType;
- typedef NotImplemented IfcFluidFlowProperties; // (not currently used by Assimp)
- struct IfcSphere;
- typedef NotImplemented IfcRelAssociatesAppliedValue; // (not currently used by Assimp)
- struct IfcDamperType;
- struct IfcProjectOrderRecord;
- typedef NotImplemented IfcDimensionalExponents; // (not currently used by Assimp)
- typedef NotImplemented IfcRelDefinesByType; // (not currently used by Assimp)
- struct IfcDistributionChamberElement;
- struct IfcMechanicalFastener;
- typedef NotImplemented IfcQuantityVolume; // (not currently used by Assimp)
- struct IfcRectangularTrimmedSurface;
- typedef NotImplemented IfcDateAndTime; // (not currently used by Assimp)
- struct IfcZone;
- struct IfcFanType;
- struct IfcGeometricSet;
- struct IfcFillAreaStyleTiles;
- typedef NotImplemented IfcPixelTexture; // (not currently used by Assimp)
- struct IfcCableSegmentType;
- struct IfcRelOverridesProperties;
- struct IfcMeasureWithUnit;
- struct IfcSlabType;
- struct IfcServiceLife;
- struct IfcFurnitureType;
- struct IfcCostItem;
- struct IfcReinforcingMesh;
- typedef NotImplemented IfcExtendedMaterialProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcActorRole; // (not currently used by Assimp)
- struct IfcFacetedBrepWithVoids;
- typedef NotImplemented IfcConstraintAggregationRelationship; // (not currently used by Assimp)
- struct IfcGasTerminalType;
- typedef NotImplemented IfcRelConnectsWithEccentricity; // (not currently used by Assimp)
- struct IfcPile;
- struct IfcFillAreaStyleTileSymbolWithStyle;
- typedef NotImplemented IfcElectricalBaseProperties; // (not currently used by Assimp)
- struct IfcConstructionMaterialResource;
- struct IfcAnnotationCurveOccurrence;
- struct IfcDimensionCurve;
- struct IfcGeometricCurveSet;
- struct IfcRelAggregates;
- struct IfcFaceBasedSurfaceModel;
- struct IfcEnergyConversionDevice;
- struct IfcRampFlight;
- typedef NotImplemented IfcPropertyEnumeration; // (not currently used by Assimp)
- struct IfcVertexLoop;
- struct IfcPlate;
- struct IfcUShapeProfileDef;
- typedef NotImplemented IfcHygroscopicMaterialProperties; // (not currently used by Assimp)
- struct IfcFaceBound;
- struct IfcFaceOuterBound;
- struct IfcOneDirectionRepeatFactor;
- struct IfcBoilerType;
- struct IfcConstructionEquipmentResource;
- struct IfcComplexProperty;
- struct IfcFooting;
- typedef NotImplemented IfcOpticalMaterialProperties; // (not currently used by Assimp)
- struct IfcConstructionProductResource;
- typedef NotImplemented IfcBoundaryEdgeCondition; // (not currently used by Assimp)
- struct IfcDerivedProfileDef;
- struct IfcPropertyTableValue;
- typedef NotImplemented IfcRelAssignsToGroup; // (not currently used by Assimp)
- struct IfcFlowMeterType;
- struct IfcDoorStyle;
- typedef NotImplemented IfcRelConnectsPortToElement; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesClassification; // (not currently used by Assimp)
- struct IfcUnitAssignment;
- struct IfcFlowTerminal;
- struct IfcCraneRailFShapeProfileDef;
- struct IfcFlowSegment;
- struct IfcElementQuantity;
- typedef NotImplemented IfcBoundaryNodeCondition; // (not currently used by Assimp)
- typedef NotImplemented IfcBoundaryNodeConditionWarping; // (not currently used by Assimp)
- struct IfcCurtainWall;
- struct IfcDiscreteAccessory;
- struct IfcGrid;
- struct IfcSanitaryTerminalType;
- typedef NotImplemented IfcSoundProperties; // (not currently used by Assimp)
- struct IfcSubedge;
- typedef NotImplemented IfcTextStyleTextModel; // (not currently used by Assimp)
- struct IfcFilterType;
- typedef NotImplemented IfcSymbolStyle; // (not currently used by Assimp)
- struct IfcTendon;
- typedef NotImplemented IfcDimensionPair; // (not currently used by Assimp)
- struct IfcStructuralLoadGroup;
- struct IfcPresentationStyleAssignment;
- typedef NotImplemented IfcRegularTimeSeries; // (not currently used by Assimp)
- struct IfcStructuralCurveMember;
- struct IfcLightSourceAmbient;
- struct IfcCondition;
- struct IfcPort;
- struct IfcSpace;
- struct IfcHeatExchangerType;
- struct IfcTankType;
- struct IfcInventory;
- typedef NotImplemented IfcTextStyle; // (not currently used by Assimp)
- typedef NotImplemented IfcAppliedValueRelationship; // (not currently used by Assimp)
- typedef NotImplemented IfcSoundValue; // (not currently used by Assimp)
- struct IfcTransportElementType;
- struct IfcAirToAirHeatRecoveryType;
- struct IfcStairFlight;
- struct IfcElectricalElement;
- typedef NotImplemented IfcLightIntensityDistribution; // (not currently used by Assimp)
- typedef NotImplemented IfcClassificationReference; // (not currently used by Assimp)
- struct IfcSurfaceStyleWithTextures;
- struct IfcBoundingBox;
- typedef NotImplemented IfcApplication; // (not currently used by Assimp)
- struct IfcWallType;
- struct IfcMove;
- struct IfcCircle;
- struct IfcOffsetCurve2D;
- typedef NotImplemented IfcMaterialLayerSetUsage; // (not currently used by Assimp)
- struct IfcPointOnCurve;
- struct IfcStructuralResultGroup;
- struct IfcSectionedSpine;
- struct IfcSlab;
- typedef NotImplemented IfcConnectionPortGeometry; // (not currently used by Assimp)
- typedef NotImplemented IfcQuantityWeight; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssociatesMaterial; // (not currently used by Assimp)
- struct IfcVertex;
- struct IfcVertexPoint;
- typedef NotImplemented IfcReferencesValueDocument; // (not currently used by Assimp)
- typedef NotImplemented IfcPersonAndOrganization; // (not currently used by Assimp)
- typedef NotImplemented IfcRelFlowControlElements; // (not currently used by Assimp)
- typedef NotImplemented IfcRelAssignsToProcess; // (not currently used by Assimp)
- struct IfcStructuralLinearAction;
- struct IfcStructuralLinearActionVarying;
- struct IfcBuildingElementProxyType;
- struct IfcProjectionElement;
- typedef NotImplemented IfcDerivedUnit; // (not currently used by Assimp)
- typedef NotImplemented IfcApprovalActorRelationship; // (not currently used by Assimp)
- struct IfcConversionBasedUnit;
- typedef NotImplemented IfcMaterial; // (not currently used by Assimp)
- struct IfcGeometricRepresentationSubContext;
- struct IfcAnnotationSurfaceOccurrence;
- typedef NotImplemented IfcPreDefinedDimensionSymbol; // (not currently used by Assimp)
- struct IfcRoundedEdgeFeature;
- typedef NotImplemented IfcRelCoversBldgElements; // (not currently used by Assimp)
- struct IfcElectricDistributionPoint;
- struct IfcCableCarrierSegmentType;
- typedef NotImplemented IfcStructuralLoadLinearForce; // (not currently used by Assimp)
- typedef NotImplemented IfcGridAxis; // (not currently used by Assimp)
- typedef NotImplemented IfcIrregularTimeSeriesValue; // (not currently used by Assimp)
- struct IfcWallStandardCase;
- typedef NotImplemented IfcRelOccupiesSpaces; // (not currently used by Assimp)
- typedef NotImplemented IfcDerivedUnitElement; // (not currently used by Assimp)
- struct IfcCsgSolid;
- struct IfcBeamType;
- struct IfcAnnotationFillArea;
- typedef NotImplemented IfcRelaxation; // (not currently used by Assimp)
- struct IfcStructuralCurveMemberVarying;
- struct IfcPointOnSurface;
- typedef NotImplemented IfcPropertyDependencyRelationship; // (not currently used by Assimp)
- typedef NotImplemented IfcVertexBasedTextureMap; // (not currently used by Assimp)
- struct IfcOrderAction;
- typedef NotImplemented IfcLibraryReference; // (not currently used by Assimp)
- struct IfcEdgeLoop;
- struct IfcAnnotationFillAreaOccurrence;
- typedef NotImplemented IfcRelConnectsStructuralElement; // (not currently used by Assimp)
- struct IfcWorkPlan;
- struct IfcEllipse;
- struct IfcProductDefinitionShape;
- struct IfcProjectionCurve;
- struct IfcElectricalCircuit;
- struct IfcRationalBezierCurve;
- struct IfcStructuralPointAction;
- typedef NotImplemented IfcServiceLifeFactor; // (not currently used by Assimp)
- typedef NotImplemented IfcThermalMaterialProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcTextureCoordinateGenerator; // (not currently used by Assimp)
- struct IfcPipeSegmentType;
- struct IfcTwoDirectionRepeatFactor;
- struct IfcShapeRepresentation;
- struct IfcPropertySet;
- struct IfcSurfaceStyleRendering;
- struct IfcDistributionPort;
- typedef NotImplemented IfcImageTexture; // (not currently used by Assimp)
- struct IfcPipeFittingType;
- struct IfcTransportElement;
- struct IfcAnnotationTextOccurrence;
- typedef NotImplemented IfcConnectionSurfaceGeometry; // (not currently used by Assimp)
- struct IfcStructuralAnalysisModel;
- typedef NotImplemented IfcConnectionCurveGeometry; // (not currently used by Assimp)
- struct IfcConditionCriterion;
- typedef NotImplemented IfcWaterProperties; // (not currently used by Assimp)
- typedef NotImplemented IfcMaterialLayer; // (not currently used by Assimp)
- typedef NotImplemented IfcCostValue; // (not currently used by Assimp)
+ // ******************************************************************************
+ // IFC Entities
+ // ******************************************************************************
+
+ struct IfcRepresentationItem;
+ struct IfcGeometricRepresentationItem;
+ struct IfcCurve;
+ struct IfcBoundedCurve;
+ struct IfcCompositeCurve;
+ struct Ifc2DCompositeCurve;
+ struct IfcRoot;
+ struct IfcObjectDefinition;
+ struct IfcObject;
+ struct IfcControl;
+ struct IfcActionRequest;
+ struct IfcActor;
+ typedef NotImplemented IfcActorRole; // (not currently used by Assimp)
+ struct IfcTypeObject;
+ struct IfcTypeProduct;
+ struct IfcElementType;
+ struct IfcDistributionElementType;
+ struct IfcDistributionControlElementType;
+ struct IfcActuatorType;
+ typedef NotImplemented IfcAddress; // (not currently used by Assimp)
+ struct IfcDistributionFlowElementType;
+ struct IfcFlowControllerType;
+ struct IfcAirTerminalBoxType;
+ struct IfcFlowTerminalType;
+ struct IfcAirTerminalType;
+ struct IfcEnergyConversionDeviceType;
+ struct IfcAirToAirHeatRecoveryType;
+ struct IfcAlarmType;
+ struct IfcDraughtingCallout;
+ struct IfcDimensionCurveDirectedCallout;
+ struct IfcAngularDimension;
+ struct IfcProduct;
+ struct IfcAnnotation;
+ struct IfcStyledItem;
+ struct IfcAnnotationOccurrence;
+ struct IfcAnnotationCurveOccurrence;
+ struct IfcAnnotationFillArea;
+ struct IfcAnnotationFillAreaOccurrence;
+ struct IfcAnnotationSurface;
+ struct IfcAnnotationSurfaceOccurrence;
+ struct IfcAnnotationSymbolOccurrence;
+ struct IfcAnnotationTextOccurrence;
+ typedef NotImplemented IfcApplication; // (not currently used by Assimp)
+ typedef NotImplemented IfcAppliedValue; // (not currently used by Assimp)
+ typedef NotImplemented IfcAppliedValueRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcApproval; // (not currently used by Assimp)
+ typedef NotImplemented IfcApprovalActorRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcApprovalPropertyRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcApprovalRelationship; // (not currently used by Assimp)
+ struct IfcProfileDef;
+ struct IfcArbitraryClosedProfileDef;
+ struct IfcArbitraryOpenProfileDef;
+ struct IfcArbitraryProfileDefWithVoids;
+ struct IfcGroup;
+ struct IfcAsset;
+ struct IfcParameterizedProfileDef;
+ struct IfcIShapeProfileDef;
+ struct IfcAsymmetricIShapeProfileDef;
+ struct IfcPlacement;
+ struct IfcAxis1Placement;
+ struct IfcAxis2Placement2D;
+ struct IfcAxis2Placement3D;
+ struct IfcBSplineCurve;
+ struct IfcElement;
+ struct IfcBuildingElement;
+ struct IfcBeam;
+ struct IfcBuildingElementType;
+ struct IfcBeamType;
+ struct IfcBezierCurve;
+ typedef NotImplemented IfcSurfaceTexture; // (not currently used by Assimp)
+ typedef NotImplemented IfcBlobTexture; // (not currently used by Assimp)
+ struct IfcCsgPrimitive3D;
+ struct IfcBlock;
+ struct IfcBoilerType;
+ struct IfcBooleanResult;
+ struct IfcBooleanClippingResult;
+ typedef NotImplemented IfcBoundaryCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcBoundaryEdgeCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcBoundaryFaceCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcBoundaryNodeCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcBoundaryNodeConditionWarping; // (not currently used by Assimp)
+ struct IfcSurface;
+ struct IfcBoundedSurface;
+ struct IfcBoundingBox;
+ struct IfcHalfSpaceSolid;
+ struct IfcBoxedHalfSpace;
+ struct IfcSpatialStructureElement;
+ struct IfcBuilding;
+ struct IfcBuildingElementComponent;
+ struct IfcBuildingElementPart;
+ struct IfcBuildingElementProxy;
+ struct IfcBuildingElementProxyType;
+ struct IfcBuildingStorey;
+ struct IfcCShapeProfileDef;
+ struct IfcFlowFittingType;
+ struct IfcCableCarrierFittingType;
+ struct IfcFlowSegmentType;
+ struct IfcCableCarrierSegmentType;
+ struct IfcCableSegmentType;
+ typedef NotImplemented IfcCalendarDate; // (not currently used by Assimp)
+ struct IfcPoint;
+ struct IfcCartesianPoint;
+ struct IfcCartesianTransformationOperator;
+ struct IfcCartesianTransformationOperator2D;
+ struct IfcCartesianTransformationOperator2DnonUniform;
+ struct IfcCartesianTransformationOperator3D;
+ struct IfcCartesianTransformationOperator3DnonUniform;
+ struct IfcCenterLineProfileDef;
+ struct IfcFeatureElement;
+ struct IfcFeatureElementSubtraction;
+ struct IfcEdgeFeature;
+ struct IfcChamferEdgeFeature;
+ struct IfcChillerType;
+ struct IfcConic;
+ struct IfcCircle;
+ struct IfcCircleProfileDef;
+ struct IfcCircleHollowProfileDef;
+ typedef NotImplemented IfcClassification; // (not currently used by Assimp)
+ typedef NotImplemented IfcClassificationItem; // (not currently used by Assimp)
+ typedef NotImplemented IfcClassificationItemRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcClassificationNotation; // (not currently used by Assimp)
+ typedef NotImplemented IfcClassificationNotationFacet; // (not currently used by Assimp)
+ typedef NotImplemented IfcExternalReference; // (not currently used by Assimp)
+ typedef NotImplemented IfcClassificationReference; // (not currently used by Assimp)
+ struct IfcTopologicalRepresentationItem;
+ struct IfcConnectedFaceSet;
+ struct IfcClosedShell;
+ struct IfcCoilType;
+ struct IfcColourSpecification;
+ struct IfcColourRgb;
+ struct IfcColumn;
+ struct IfcColumnType;
+ struct IfcProperty;
+ struct IfcComplexProperty;
+ struct IfcCompositeCurveSegment;
+ struct IfcCompositeProfileDef;
+ struct IfcFlowMovingDeviceType;
+ struct IfcCompressorType;
+ struct IfcCondenserType;
+ struct IfcCondition;
+ struct IfcConditionCriterion;
+ typedef NotImplemented IfcConnectionGeometry; // (not currently used by Assimp)
+ typedef NotImplemented IfcConnectionCurveGeometry; // (not currently used by Assimp)
+ typedef NotImplemented IfcConnectionPointGeometry; // (not currently used by Assimp)
+ typedef NotImplemented IfcConnectionPointEccentricity; // (not currently used by Assimp)
+ typedef NotImplemented IfcConnectionPortGeometry; // (not currently used by Assimp)
+ typedef NotImplemented IfcConnectionSurfaceGeometry; // (not currently used by Assimp)
+ typedef NotImplemented IfcConstraint; // (not currently used by Assimp)
+ typedef NotImplemented IfcConstraintAggregationRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcConstraintClassificationRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcConstraintRelationship; // (not currently used by Assimp)
+ struct IfcResource;
+ struct IfcConstructionResource;
+ struct IfcConstructionEquipmentResource;
+ struct IfcConstructionMaterialResource;
+ struct IfcConstructionProductResource;
+ struct IfcNamedUnit;
+ struct IfcContextDependentUnit;
+ struct IfcControllerType;
+ struct IfcConversionBasedUnit;
+ struct IfcCooledBeamType;
+ struct IfcCoolingTowerType;
+ typedef NotImplemented IfcCoordinatedUniversalTimeOffset; // (not currently used by Assimp)
+ struct IfcCostItem;
+ struct IfcCostSchedule;
+ typedef NotImplemented IfcCostValue; // (not currently used by Assimp)
+ struct IfcCovering;
+ struct IfcCoveringType;
+ struct IfcCraneRailAShapeProfileDef;
+ struct IfcCraneRailFShapeProfileDef;
+ struct IfcCrewResource;
+ struct IfcSolidModel;
+ struct IfcCsgSolid;
+ typedef NotImplemented IfcCurrencyRelationship; // (not currently used by Assimp)
+ struct IfcCurtainWall;
+ struct IfcCurtainWallType;
+ struct IfcCurveBoundedPlane;
+ struct IfcPresentationStyle;
+ typedef NotImplemented IfcCurveStyle; // (not currently used by Assimp)
+ typedef NotImplemented IfcCurveStyleFont; // (not currently used by Assimp)
+ typedef NotImplemented IfcCurveStyleFontAndScaling; // (not currently used by Assimp)
+ typedef NotImplemented IfcCurveStyleFontPattern; // (not currently used by Assimp)
+ struct IfcDamperType;
+ typedef NotImplemented IfcDateAndTime; // (not currently used by Assimp)
+ struct IfcDefinedSymbol;
+ struct IfcDerivedProfileDef;
+ typedef NotImplemented IfcDerivedUnit; // (not currently used by Assimp)
+ typedef NotImplemented IfcDerivedUnitElement; // (not currently used by Assimp)
+ struct IfcDiameterDimension;
+ typedef NotImplemented IfcDraughtingCalloutRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcDimensionCalloutRelationship; // (not currently used by Assimp)
+ struct IfcDimensionCurve;
+ struct IfcTerminatorSymbol;
+ struct IfcDimensionCurveTerminator;
+ typedef NotImplemented IfcDimensionPair; // (not currently used by Assimp)
+ typedef NotImplemented IfcDimensionalExponents; // (not currently used by Assimp)
+ struct IfcDirection;
+ struct IfcElementComponent;
+ struct IfcDiscreteAccessory;
+ struct IfcElementComponentType;
+ struct IfcDiscreteAccessoryType;
+ struct IfcDistributionElement;
+ struct IfcDistributionFlowElement;
+ struct IfcDistributionChamberElement;
+ struct IfcDistributionChamberElementType;
+ struct IfcDistributionControlElement;
+ struct IfcPort;
+ struct IfcDistributionPort;
+ typedef NotImplemented IfcDocumentElectronicFormat; // (not currently used by Assimp)
+ typedef NotImplemented IfcDocumentInformation; // (not currently used by Assimp)
+ typedef NotImplemented IfcDocumentInformationRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcDocumentReference; // (not currently used by Assimp)
+ struct IfcDoor;
+ struct IfcPropertyDefinition;
+ struct IfcPropertySetDefinition;
+ typedef NotImplemented IfcDoorLiningProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcDoorPanelProperties; // (not currently used by Assimp)
+ struct IfcDoorStyle;
+ typedef NotImplemented IfcPreDefinedItem; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedColour; // (not currently used by Assimp)
+ typedef NotImplemented IfcDraughtingPreDefinedColour; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedCurveFont; // (not currently used by Assimp)
+ typedef NotImplemented IfcDraughtingPreDefinedCurveFont; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedTextFont; // (not currently used by Assimp)
+ typedef NotImplemented IfcDraughtingPreDefinedTextFont; // (not currently used by Assimp)
+ struct IfcDuctFittingType;
+ struct IfcDuctSegmentType;
+ struct IfcFlowTreatmentDeviceType;
+ struct IfcDuctSilencerType;
+ struct IfcEdge;
+ struct IfcEdgeCurve;
+ struct IfcLoop;
+ struct IfcEdgeLoop;
+ struct IfcElectricApplianceType;
+ struct IfcFlowController;
+ struct IfcElectricDistributionPoint;
+ struct IfcFlowStorageDeviceType;
+ struct IfcElectricFlowStorageDeviceType;
+ struct IfcElectricGeneratorType;
+ struct IfcElectricHeaterType;
+ struct IfcElectricMotorType;
+ struct IfcElectricTimeControlType;
+ typedef NotImplemented IfcEnergyProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcElectricalBaseProperties; // (not currently used by Assimp)
+ struct IfcSystem;
+ struct IfcElectricalCircuit;
+ struct IfcElectricalElement;
+ struct IfcElementAssembly;
+ struct IfcElementQuantity;
+ struct IfcElementarySurface;
+ struct IfcEllipse;
+ struct IfcEllipseProfileDef;
+ struct IfcEnergyConversionDevice;
+ typedef NotImplemented IfcEnvironmentalImpactValue; // (not currently used by Assimp)
+ struct IfcEquipmentElement;
+ struct IfcEquipmentStandard;
+ struct IfcEvaporativeCoolerType;
+ struct IfcEvaporatorType;
+ typedef NotImplemented IfcMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcExtendedMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcExternallyDefinedHatchStyle; // (not currently used by Assimp)
+ typedef NotImplemented IfcExternallyDefinedSurfaceStyle; // (not currently used by Assimp)
+ typedef NotImplemented IfcExternallyDefinedSymbol; // (not currently used by Assimp)
+ typedef NotImplemented IfcExternallyDefinedTextFont; // (not currently used by Assimp)
+ struct IfcSweptAreaSolid;
+ struct IfcExtrudedAreaSolid;
+ struct IfcFace;
+ struct IfcFaceBasedSurfaceModel;
+ struct IfcFaceBound;
+ struct IfcFaceOuterBound;
+ struct IfcFaceSurface;
+ struct IfcManifoldSolidBrep;
+ struct IfcFacetedBrep;
+ struct IfcFacetedBrepWithVoids;
+ typedef NotImplemented IfcStructuralConnectionCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcFailureConnectionCondition; // (not currently used by Assimp)
+ struct IfcFanType;
+ struct IfcFastener;
+ struct IfcFastenerType;
+ struct IfcFeatureElementAddition;
+ typedef NotImplemented IfcFillAreaStyle; // (not currently used by Assimp)
+ struct IfcFillAreaStyleHatching;
+ struct IfcFillAreaStyleTileSymbolWithStyle;
+ struct IfcFillAreaStyleTiles;
+ struct IfcFilterType;
+ struct IfcFireSuppressionTerminalType;
+ struct IfcFlowFitting;
+ struct IfcFlowInstrumentType;
+ struct IfcFlowMeterType;
+ struct IfcFlowMovingDevice;
+ struct IfcFlowSegment;
+ struct IfcFlowStorageDevice;
+ struct IfcFlowTerminal;
+ struct IfcFlowTreatmentDevice;
+ typedef NotImplemented IfcFluidFlowProperties; // (not currently used by Assimp)
+ struct IfcFooting;
+ typedef NotImplemented IfcFuelProperties; // (not currently used by Assimp)
+ struct IfcFurnishingElement;
+ struct IfcFurnishingElementType;
+ struct IfcFurnitureStandard;
+ struct IfcFurnitureType;
+ struct IfcGasTerminalType;
+ typedef NotImplemented IfcGeneralMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcProfileProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcGeneralProfileProperties; // (not currently used by Assimp)
+ struct IfcGeometricSet;
+ struct IfcGeometricCurveSet;
+ struct IfcRepresentationContext;
+ struct IfcGeometricRepresentationContext;
+ struct IfcGeometricRepresentationSubContext;
+ struct IfcGrid;
+ typedef NotImplemented IfcGridAxis; // (not currently used by Assimp)
+ struct IfcObjectPlacement;
+ struct IfcGridPlacement;
+ struct IfcHeatExchangerType;
+ struct IfcHumidifierType;
+ typedef NotImplemented IfcHygroscopicMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcImageTexture; // (not currently used by Assimp)
+ struct IfcInventory;
+ typedef NotImplemented IfcTimeSeries; // (not currently used by Assimp)
+ typedef NotImplemented IfcIrregularTimeSeries; // (not currently used by Assimp)
+ typedef NotImplemented IfcIrregularTimeSeriesValue; // (not currently used by Assimp)
+ struct IfcJunctionBoxType;
+ struct IfcLShapeProfileDef;
+ struct IfcLaborResource;
+ struct IfcLampType;
+ typedef NotImplemented IfcLibraryInformation; // (not currently used by Assimp)
+ typedef NotImplemented IfcLibraryReference; // (not currently used by Assimp)
+ typedef NotImplemented IfcLightDistributionData; // (not currently used by Assimp)
+ struct IfcLightFixtureType;
+ typedef NotImplemented IfcLightIntensityDistribution; // (not currently used by Assimp)
+ struct IfcLightSource;
+ struct IfcLightSourceAmbient;
+ struct IfcLightSourceDirectional;
+ struct IfcLightSourceGoniometric;
+ struct IfcLightSourcePositional;
+ struct IfcLightSourceSpot;
+ struct IfcLine;
+ struct IfcLinearDimension;
+ struct IfcLocalPlacement;
+ typedef NotImplemented IfcLocalTime; // (not currently used by Assimp)
+ struct IfcMappedItem;
+ typedef NotImplemented IfcMaterial; // (not currently used by Assimp)
+ typedef NotImplemented IfcMaterialClassificationRelationship; // (not currently used by Assimp)
+ struct IfcProductRepresentation;
+ struct IfcMaterialDefinitionRepresentation;
+ typedef NotImplemented IfcMaterialLayer; // (not currently used by Assimp)
+ typedef NotImplemented IfcMaterialLayerSet; // (not currently used by Assimp)
+ typedef NotImplemented IfcMaterialLayerSetUsage; // (not currently used by Assimp)
+ typedef NotImplemented IfcMaterialList; // (not currently used by Assimp)
+ struct IfcMeasureWithUnit;
+ typedef NotImplemented IfcMechanicalMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcMechanicalConcreteMaterialProperties; // (not currently used by Assimp)
+ struct IfcMechanicalFastener;
+ struct IfcMechanicalFastenerType;
+ typedef NotImplemented IfcMechanicalSteelMaterialProperties; // (not currently used by Assimp)
+ struct IfcMember;
+ struct IfcMemberType;
+ typedef NotImplemented IfcMetric; // (not currently used by Assimp)
+ typedef NotImplemented IfcMonetaryUnit; // (not currently used by Assimp)
+ struct IfcMotorConnectionType;
+ struct IfcProcess;
+ struct IfcTask;
+ struct IfcMove;
+ typedef NotImplemented IfcObjective; // (not currently used by Assimp)
+ struct IfcOccupant;
+ struct IfcOffsetCurve2D;
+ struct IfcOffsetCurve3D;
+ struct IfcOneDirectionRepeatFactor;
+ struct IfcOpenShell;
+ struct IfcOpeningElement;
+ typedef NotImplemented IfcOpticalMaterialProperties; // (not currently used by Assimp)
+ struct IfcOrderAction;
+ typedef NotImplemented IfcOrganization; // (not currently used by Assimp)
+ typedef NotImplemented IfcOrganizationRelationship; // (not currently used by Assimp)
+ struct IfcOrientedEdge;
+ struct IfcOutletType;
+ typedef NotImplemented IfcOwnerHistory; // (not currently used by Assimp)
+ struct IfcPath;
+ struct IfcPerformanceHistory;
+ typedef NotImplemented IfcPermeableCoveringProperties; // (not currently used by Assimp)
+ struct IfcPermit;
+ typedef NotImplemented IfcPerson; // (not currently used by Assimp)
+ typedef NotImplemented IfcPersonAndOrganization; // (not currently used by Assimp)
+ typedef NotImplemented IfcPhysicalQuantity; // (not currently used by Assimp)
+ typedef NotImplemented IfcPhysicalComplexQuantity; // (not currently used by Assimp)
+ typedef NotImplemented IfcPhysicalSimpleQuantity; // (not currently used by Assimp)
+ struct IfcPile;
+ struct IfcPipeFittingType;
+ struct IfcPipeSegmentType;
+ typedef NotImplemented IfcPixelTexture; // (not currently used by Assimp)
+ struct IfcPlanarExtent;
+ struct IfcPlanarBox;
+ struct IfcPlane;
+ struct IfcPlate;
+ struct IfcPlateType;
+ struct IfcPointOnCurve;
+ struct IfcPointOnSurface;
+ struct IfcPolyLoop;
+ struct IfcPolygonalBoundedHalfSpace;
+ struct IfcPolyline;
+ typedef NotImplemented IfcPostalAddress; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedSymbol; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedDimensionSymbol; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedPointMarkerSymbol; // (not currently used by Assimp)
+ typedef NotImplemented IfcPreDefinedTerminatorSymbol; // (not currently used by Assimp)
+ typedef NotImplemented IfcPresentationLayerAssignment; // (not currently used by Assimp)
+ typedef NotImplemented IfcPresentationLayerWithStyle; // (not currently used by Assimp)
+ struct IfcPresentationStyleAssignment;
+ struct IfcProcedure;
+ struct IfcProductDefinitionShape;
+ typedef NotImplemented IfcProductsOfCombustionProperties; // (not currently used by Assimp)
+ struct IfcProject;
+ struct IfcProjectOrder;
+ struct IfcProjectOrderRecord;
+ struct IfcProjectionCurve;
+ struct IfcProjectionElement;
+ struct IfcSimpleProperty;
+ struct IfcPropertyBoundedValue;
+ typedef NotImplemented IfcPropertyConstraintRelationship; // (not currently used by Assimp)
+ typedef NotImplemented IfcPropertyDependencyRelationship; // (not currently used by Assimp)
+ struct IfcPropertyEnumeratedValue;
+ typedef NotImplemented IfcPropertyEnumeration; // (not currently used by Assimp)
+ struct IfcPropertyListValue;
+ struct IfcPropertyReferenceValue;
+ struct IfcPropertySet;
+ struct IfcPropertySingleValue;
+ struct IfcPropertyTableValue;
+ struct IfcProtectiveDeviceType;
+ struct IfcProxy;
+ struct IfcPumpType;
+ typedef NotImplemented IfcQuantityArea; // (not currently used by Assimp)
+ typedef NotImplemented IfcQuantityCount; // (not currently used by Assimp)
+ typedef NotImplemented IfcQuantityLength; // (not currently used by Assimp)
+ typedef NotImplemented IfcQuantityTime; // (not currently used by Assimp)
+ typedef NotImplemented IfcQuantityVolume; // (not currently used by Assimp)
+ typedef NotImplemented IfcQuantityWeight; // (not currently used by Assimp)
+ struct IfcRadiusDimension;
+ struct IfcRailing;
+ struct IfcRailingType;
+ struct IfcRamp;
+ struct IfcRampFlight;
+ struct IfcRampFlightType;
+ struct IfcRationalBezierCurve;
+ struct IfcRectangleProfileDef;
+ struct IfcRectangleHollowProfileDef;
+ struct IfcRectangularPyramid;
+ struct IfcRectangularTrimmedSurface;
+ typedef NotImplemented IfcReferencesValueDocument; // (not currently used by Assimp)
+ typedef NotImplemented IfcRegularTimeSeries; // (not currently used by Assimp)
+ typedef NotImplemented IfcReinforcementBarProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcReinforcementDefinitionProperties; // (not currently used by Assimp)
+ struct IfcReinforcingElement;
+ struct IfcReinforcingBar;
+ struct IfcReinforcingMesh;
+ struct IfcRelationship;
+ struct IfcRelDecomposes;
+ struct IfcRelAggregates;
+ typedef NotImplemented IfcRelAssigns; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToControl; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsTasks; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToActor; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToGroup; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToProcess; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToProduct; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToProjectOrder; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssignsToResource; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociates; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesAppliedValue; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesApproval; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesClassification; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesConstraint; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesDocument; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesLibrary; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesMaterial; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelAssociatesProfileProperties; // (not currently used by Assimp)
+ struct IfcRelConnects;
+ typedef NotImplemented IfcRelConnectsElements; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsPathElements; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsPortToElement; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsPorts; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsStructuralActivity; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsStructuralElement; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsStructuralMember; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsWithEccentricity; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelConnectsWithRealizingElements; // (not currently used by Assimp)
+ struct IfcRelContainedInSpatialStructure;
+ typedef NotImplemented IfcRelCoversBldgElements; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelCoversSpaces; // (not currently used by Assimp)
+ struct IfcRelDefines;
+ struct IfcRelDefinesByProperties;
+ typedef NotImplemented IfcRelDefinesByType; // (not currently used by Assimp)
+ struct IfcRelFillsElement;
+ typedef NotImplemented IfcRelFlowControlElements; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelInteractionRequirements; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelNests; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelOccupiesSpaces; // (not currently used by Assimp)
+ struct IfcRelOverridesProperties;
+ typedef NotImplemented IfcRelProjectsElement; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelReferencedInSpatialStructure; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelSchedulesCostItems; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelSequence; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelServicesBuildings; // (not currently used by Assimp)
+ typedef NotImplemented IfcRelSpaceBoundary; // (not currently used by Assimp)
+ struct IfcRelVoidsElement;
+ typedef NotImplemented IfcRelaxation; // (not currently used by Assimp)
+ struct IfcRepresentation;
+ struct IfcRepresentationMap;
+ struct IfcRevolvedAreaSolid;
+ typedef NotImplemented IfcRibPlateProfileProperties; // (not currently used by Assimp)
+ struct IfcRightCircularCone;
+ struct IfcRightCircularCylinder;
+ struct IfcRoof;
+ struct IfcRoundedEdgeFeature;
+ struct IfcRoundedRectangleProfileDef;
+ struct IfcSIUnit;
+ struct IfcSanitaryTerminalType;
+ struct IfcScheduleTimeControl;
+ typedef NotImplemented IfcSectionProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcSectionReinforcementProperties; // (not currently used by Assimp)
+ struct IfcSectionedSpine;
+ struct IfcSensorType;
+ struct IfcServiceLife;
+ typedef NotImplemented IfcServiceLifeFactor; // (not currently used by Assimp)
+ typedef NotImplemented IfcShapeAspect; // (not currently used by Assimp)
+ struct IfcShapeModel;
+ struct IfcShapeRepresentation;
+ struct IfcShellBasedSurfaceModel;
+ struct IfcSite;
+ struct IfcSlab;
+ struct IfcSlabType;
+ typedef NotImplemented IfcSlippageConnectionCondition; // (not currently used by Assimp)
+ typedef NotImplemented IfcSoundProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcSoundValue; // (not currently used by Assimp)
+ struct IfcSpace;
+ struct IfcSpaceHeaterType;
+ struct IfcSpaceProgram;
+ typedef NotImplemented IfcSpaceThermalLoadProperties; // (not currently used by Assimp)
+ struct IfcSpatialStructureElementType;
+ struct IfcSpaceType;
+ struct IfcSphere;
+ struct IfcStackTerminalType;
+ struct IfcStair;
+ struct IfcStairFlight;
+ struct IfcStairFlightType;
+ struct IfcStructuralActivity;
+ struct IfcStructuralAction;
+ struct IfcStructuralAnalysisModel;
+ struct IfcStructuralItem;
+ struct IfcStructuralConnection;
+ struct IfcStructuralCurveConnection;
+ struct IfcStructuralMember;
+ struct IfcStructuralCurveMember;
+ struct IfcStructuralCurveMemberVarying;
+ struct IfcStructuralLinearAction;
+ struct IfcStructuralLinearActionVarying;
+ typedef NotImplemented IfcStructuralLoad; // (not currently used by Assimp)
+ struct IfcStructuralLoadGroup;
+ typedef NotImplemented IfcStructuralLoadStatic; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadLinearForce; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadPlanarForce; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadSingleDisplacement; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadSingleDisplacementDistortion; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadSingleForce; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadSingleForceWarping; // (not currently used by Assimp)
+ typedef NotImplemented IfcStructuralLoadTemperature; // (not currently used by Assimp)
+ struct IfcStructuralPlanarAction;
+ struct IfcStructuralPlanarActionVarying;
+ struct IfcStructuralPointAction;
+ struct IfcStructuralPointConnection;
+ struct IfcStructuralReaction;
+ struct IfcStructuralPointReaction;
+ typedef NotImplemented IfcStructuralProfileProperties; // (not currently used by Assimp)
+ struct IfcStructuralResultGroup;
+ typedef NotImplemented IfcStructuralSteelProfileProperties; // (not currently used by Assimp)
+ struct IfcStructuralSurfaceConnection;
+ struct IfcStructuralSurfaceMember;
+ struct IfcStructuralSurfaceMemberVarying;
+ struct IfcStructuredDimensionCallout;
+ struct IfcStyleModel;
+ struct IfcStyledRepresentation;
+ struct IfcSubContractResource;
+ struct IfcSubedge;
+ struct IfcSurfaceCurveSweptAreaSolid;
+ struct IfcSweptSurface;
+ struct IfcSurfaceOfLinearExtrusion;
+ struct IfcSurfaceOfRevolution;
+ struct IfcSurfaceStyle;
+ typedef NotImplemented IfcSurfaceStyleLighting; // (not currently used by Assimp)
+ typedef NotImplemented IfcSurfaceStyleRefraction; // (not currently used by Assimp)
+ struct IfcSurfaceStyleShading;
+ struct IfcSurfaceStyleRendering;
+ struct IfcSurfaceStyleWithTextures;
+ struct IfcSweptDiskSolid;
+ struct IfcSwitchingDeviceType;
+ typedef NotImplemented IfcSymbolStyle; // (not currently used by Assimp)
+ struct IfcSystemFurnitureElementType;
+ struct IfcTShapeProfileDef;
+ typedef NotImplemented IfcTable; // (not currently used by Assimp)
+ typedef NotImplemented IfcTableRow; // (not currently used by Assimp)
+ struct IfcTankType;
+ typedef NotImplemented IfcTelecomAddress; // (not currently used by Assimp)
+ struct IfcTendon;
+ struct IfcTendonAnchor;
+ struct IfcTextLiteral;
+ struct IfcTextLiteralWithExtent;
+ typedef NotImplemented IfcTextStyle; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextStyleFontModel; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextStyleForDefinedFont; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextStyleTextModel; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextStyleWithBoxCharacteristics; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextureCoordinate; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextureCoordinateGenerator; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextureMap; // (not currently used by Assimp)
+ typedef NotImplemented IfcTextureVertex; // (not currently used by Assimp)
+ typedef NotImplemented IfcThermalMaterialProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcTimeSeriesReferenceRelationship; // (not currently used by Assimp)
+ struct IfcTimeSeriesSchedule;
+ typedef NotImplemented IfcTimeSeriesValue; // (not currently used by Assimp)
+ struct IfcTopologyRepresentation;
+ struct IfcTransformerType;
+ struct IfcTransportElement;
+ struct IfcTransportElementType;
+ struct IfcTrapeziumProfileDef;
+ struct IfcTrimmedCurve;
+ struct IfcTubeBundleType;
+ struct IfcTwoDirectionRepeatFactor;
+ struct IfcUShapeProfileDef;
+ struct IfcUnitAssignment;
+ struct IfcUnitaryEquipmentType;
+ struct IfcValveType;
+ struct IfcVector;
+ struct IfcVertex;
+ typedef NotImplemented IfcVertexBasedTextureMap; // (not currently used by Assimp)
+ struct IfcVertexLoop;
+ struct IfcVertexPoint;
+ struct IfcVibrationIsolatorType;
+ struct IfcVirtualElement;
+ typedef NotImplemented IfcVirtualGridIntersection; // (not currently used by Assimp)
+ struct IfcWall;
+ struct IfcWallStandardCase;
+ struct IfcWallType;
+ struct IfcWasteTerminalType;
+ typedef NotImplemented IfcWaterProperties; // (not currently used by Assimp)
+ struct IfcWindow;
+ typedef NotImplemented IfcWindowLiningProperties; // (not currently used by Assimp)
+ typedef NotImplemented IfcWindowPanelProperties; // (not currently used by Assimp)
+ struct IfcWindowStyle;
+ struct IfcWorkControl;
+ struct IfcWorkPlan;
+ struct IfcWorkSchedule;
+ struct IfcZShapeProfileDef;
+ struct IfcZone;
+ // C++ wrapper for IfcRepresentationItem
+ struct IfcRepresentationItem : ObjectHelper<IfcRepresentationItem,0> { IfcRepresentationItem() : Object("IfcRepresentationItem") {}
+
+ };
+
+ // C++ wrapper for IfcGeometricRepresentationItem
+ struct IfcGeometricRepresentationItem : IfcRepresentationItem, ObjectHelper<IfcGeometricRepresentationItem,0> { IfcGeometricRepresentationItem() : Object("IfcGeometricRepresentationItem") {}
+
+ };
+
+ // C++ wrapper for IfcCurve
+ struct IfcCurve : IfcGeometricRepresentationItem, ObjectHelper<IfcCurve,0> { IfcCurve() : Object("IfcCurve") {}
+
+ };
+
+ // C++ wrapper for IfcBoundedCurve
+ struct IfcBoundedCurve : IfcCurve, ObjectHelper<IfcBoundedCurve,0> { IfcBoundedCurve() : Object("IfcBoundedCurve") {}
+
+ };
+
+ // C++ wrapper for IfcCompositeCurve
+ struct IfcCompositeCurve : IfcBoundedCurve, ObjectHelper<IfcCompositeCurve,2> { IfcCompositeCurve() : Object("IfcCompositeCurve") {}
+ ListOf< Lazy< IfcCompositeCurveSegment >, 1, 0 > Segments;
+ LOGICAL::Out SelfIntersect;
+ };
+
+ // C++ wrapper for Ifc2DCompositeCurve
+ struct Ifc2DCompositeCurve : IfcCompositeCurve, ObjectHelper<Ifc2DCompositeCurve,0> { Ifc2DCompositeCurve() : Object("Ifc2DCompositeCurve") {}
+
+ };
+
// C++ wrapper for IfcRoot
struct IfcRoot : ObjectHelper<IfcRoot,4> { IfcRoot() : Object("IfcRoot") {}
- IfcGloballyUniqueId::Out GlobalId;
- Lazy< NotImplemented > OwnerHistory;
- Maybe< IfcLabel::Out > Name;
- Maybe< IfcText::Out > Description;
+ IfcGloballyUniqueId::Out GlobalId;
+ Lazy< NotImplemented > OwnerHistory;
+ Maybe< IfcLabel::Out > Name;
+ Maybe< IfcText::Out > Description;
};
// C++ wrapper for IfcObjectDefinition
@@ -1388,21 +1419,41 @@ namespace IFC {
};
+ // C++ wrapper for IfcObject
+ struct IfcObject : IfcObjectDefinition, ObjectHelper<IfcObject,1> { IfcObject() : Object("IfcObject") {}
+ Maybe< IfcLabel::Out > ObjectType;
+ };
+
+ // C++ wrapper for IfcControl
+ struct IfcControl : IfcObject, ObjectHelper<IfcControl,0> { IfcControl() : Object("IfcControl") {}
+
+ };
+
+ // C++ wrapper for IfcActionRequest
+ struct IfcActionRequest : IfcControl, ObjectHelper<IfcActionRequest,1> { IfcActionRequest() : Object("IfcActionRequest") {}
+ IfcIdentifier::Out RequestID;
+ };
+
+ // C++ wrapper for IfcActor
+ struct IfcActor : IfcObject, ObjectHelper<IfcActor,1> { IfcActor() : Object("IfcActor") {}
+ IfcActorSelect::Out TheActor;
+ };
+
// C++ wrapper for IfcTypeObject
struct IfcTypeObject : IfcObjectDefinition, ObjectHelper<IfcTypeObject,2> { IfcTypeObject() : Object("IfcTypeObject") {}
- Maybe< IfcLabel::Out > ApplicableOccurrence;
- Maybe< ListOf< Lazy< IfcPropertySetDefinition >, 1, 0 > > HasPropertySets;
+ Maybe< IfcLabel::Out > ApplicableOccurrence;
+ Maybe< ListOf< Lazy< IfcPropertySetDefinition >, 1, 0 > > HasPropertySets;
};
// C++ wrapper for IfcTypeProduct
struct IfcTypeProduct : IfcTypeObject, ObjectHelper<IfcTypeProduct,2> { IfcTypeProduct() : Object("IfcTypeProduct") {}
- Maybe< ListOf< Lazy< IfcRepresentationMap >, 1, 0 > > RepresentationMaps;
- Maybe< IfcLabel::Out > Tag;
+ Maybe< ListOf< Lazy< IfcRepresentationMap >, 1, 0 > > RepresentationMaps;
+ Maybe< IfcLabel::Out > Tag;
};
// C++ wrapper for IfcElementType
struct IfcElementType : IfcTypeProduct, ObjectHelper<IfcElementType,1> { IfcElementType() : Object("IfcElementType") {}
- Maybe< IfcLabel::Out > ElementType;
+ Maybe< IfcLabel::Out > ElementType;
};
// C++ wrapper for IfcDistributionElementType
@@ -1410,6 +1461,16 @@ namespace IFC {
};
+ // C++ wrapper for IfcDistributionControlElementType
+ struct IfcDistributionControlElementType : IfcDistributionElementType, ObjectHelper<IfcDistributionControlElementType,0> { IfcDistributionControlElementType() : Object("IfcDistributionControlElementType") {}
+
+ };
+
+ // C++ wrapper for IfcActuatorType
+ struct IfcActuatorType : IfcDistributionControlElementType, ObjectHelper<IfcActuatorType,1> { IfcActuatorType() : Object("IfcActuatorType") {}
+ IfcActuatorTypeEnum::Out PredefinedType;
+ };
+
// C++ wrapper for IfcDistributionFlowElementType
struct IfcDistributionFlowElementType : IfcDistributionElementType, ObjectHelper<IfcDistributionFlowElementType,0> { IfcDistributionFlowElementType() : Object("IfcDistributionFlowElementType") {}
@@ -1420,405 +1481,406 @@ namespace IFC {
};
- // C++ wrapper for IfcElectricTimeControlType
- struct IfcElectricTimeControlType : IfcFlowControllerType, ObjectHelper<IfcElectricTimeControlType,1> { IfcElectricTimeControlType() : Object("IfcElectricTimeControlType") {}
- IfcElectricTimeControlTypeEnum::Out PredefinedType;
- };
-
- // C++ wrapper for IfcRepresentation
- struct IfcRepresentation : ObjectHelper<IfcRepresentation,4> { IfcRepresentation() : Object("IfcRepresentation") {}
- Lazy< IfcRepresentationContext > ContextOfItems;
- Maybe< IfcLabel::Out > RepresentationIdentifier;
- Maybe< IfcLabel::Out > RepresentationType;
- ListOf< Lazy< IfcRepresentationItem >, 1, 0 > Items;
+ // C++ wrapper for IfcAirTerminalBoxType
+ struct IfcAirTerminalBoxType : IfcFlowControllerType, ObjectHelper<IfcAirTerminalBoxType,1> { IfcAirTerminalBoxType() : Object("IfcAirTerminalBoxType") {}
+ IfcAirTerminalBoxTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcShapeModel
- struct IfcShapeModel : IfcRepresentation, ObjectHelper<IfcShapeModel,0> { IfcShapeModel() : Object("IfcShapeModel") {}
+ // C++ wrapper for IfcFlowTerminalType
+ struct IfcFlowTerminalType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowTerminalType,0> { IfcFlowTerminalType() : Object("IfcFlowTerminalType") {}
};
- // C++ wrapper for IfcTopologyRepresentation
- struct IfcTopologyRepresentation : IfcShapeModel, ObjectHelper<IfcTopologyRepresentation,0> { IfcTopologyRepresentation() : Object("IfcTopologyRepresentation") {}
-
+ // C++ wrapper for IfcAirTerminalType
+ struct IfcAirTerminalType : IfcFlowTerminalType, ObjectHelper<IfcAirTerminalType,1> { IfcAirTerminalType() : Object("IfcAirTerminalType") {}
+ IfcAirTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcRelationship
- struct IfcRelationship : IfcRoot, ObjectHelper<IfcRelationship,0> { IfcRelationship() : Object("IfcRelationship") {}
+ // C++ wrapper for IfcEnergyConversionDeviceType
+ struct IfcEnergyConversionDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcEnergyConversionDeviceType,0> { IfcEnergyConversionDeviceType() : Object("IfcEnergyConversionDeviceType") {}
};
- // C++ wrapper for IfcRelConnects
- struct IfcRelConnects : IfcRelationship, ObjectHelper<IfcRelConnects,0> { IfcRelConnects() : Object("IfcRelConnects") {}
-
+ // C++ wrapper for IfcAirToAirHeatRecoveryType
+ struct IfcAirToAirHeatRecoveryType : IfcEnergyConversionDeviceType, ObjectHelper<IfcAirToAirHeatRecoveryType,1> { IfcAirToAirHeatRecoveryType() : Object("IfcAirToAirHeatRecoveryType") {}
+ IfcAirToAirHeatRecoveryTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowFittingType
- struct IfcFlowFittingType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowFittingType,0> { IfcFlowFittingType() : Object("IfcFlowFittingType") {}
-
+ // C++ wrapper for IfcAlarmType
+ struct IfcAlarmType : IfcDistributionControlElementType, ObjectHelper<IfcAlarmType,1> { IfcAlarmType() : Object("IfcAlarmType") {}
+ IfcAlarmTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCableCarrierFittingType
- struct IfcCableCarrierFittingType : IfcFlowFittingType, ObjectHelper<IfcCableCarrierFittingType,1> { IfcCableCarrierFittingType() : Object("IfcCableCarrierFittingType") {}
- IfcCableCarrierFittingTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDraughtingCallout
+ struct IfcDraughtingCallout : IfcGeometricRepresentationItem, ObjectHelper<IfcDraughtingCallout,1> { IfcDraughtingCallout() : Object("IfcDraughtingCallout") {}
+ ListOf< IfcDraughtingCalloutElement, 1, 0 >::Out Contents;
};
- // C++ wrapper for IfcEnergyConversionDeviceType
- struct IfcEnergyConversionDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcEnergyConversionDeviceType,0> { IfcEnergyConversionDeviceType() : Object("IfcEnergyConversionDeviceType") {}
+ // C++ wrapper for IfcDimensionCurveDirectedCallout
+ struct IfcDimensionCurveDirectedCallout : IfcDraughtingCallout, ObjectHelper<IfcDimensionCurveDirectedCallout,0> { IfcDimensionCurveDirectedCallout() : Object("IfcDimensionCurveDirectedCallout") {}
};
- // C++ wrapper for IfcCoilType
- struct IfcCoilType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCoilType,1> { IfcCoilType() : Object("IfcCoilType") {}
- IfcCoilTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcAngularDimension
+ struct IfcAngularDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcAngularDimension,0> { IfcAngularDimension() : Object("IfcAngularDimension") {}
+
};
- // C++ wrapper for IfcObject
- struct IfcObject : IfcObjectDefinition, ObjectHelper<IfcObject,1> { IfcObject() : Object("IfcObject") {}
- Maybe< IfcLabel::Out > ObjectType;
+ // C++ wrapper for IfcProduct
+ struct IfcProduct : IfcObject, ObjectHelper<IfcProduct,2> { IfcProduct() : Object("IfcProduct") {}
+ Maybe< Lazy< IfcObjectPlacement > > ObjectPlacement;
+ Maybe< Lazy< IfcProductRepresentation > > Representation;
};
- // C++ wrapper for IfcControl
- struct IfcControl : IfcObject, ObjectHelper<IfcControl,0> { IfcControl() : Object("IfcControl") {}
+ // C++ wrapper for IfcAnnotation
+ struct IfcAnnotation : IfcProduct, ObjectHelper<IfcAnnotation,0> { IfcAnnotation() : Object("IfcAnnotation") {}
};
- // C++ wrapper for IfcPerformanceHistory
- struct IfcPerformanceHistory : IfcControl, ObjectHelper<IfcPerformanceHistory,1> { IfcPerformanceHistory() : Object("IfcPerformanceHistory") {}
- IfcLabel::Out LifeCyclePhase;
+ // C++ wrapper for IfcStyledItem
+ struct IfcStyledItem : IfcRepresentationItem, ObjectHelper<IfcStyledItem,3> { IfcStyledItem() : Object("IfcStyledItem") {}
+ Maybe< Lazy< IfcRepresentationItem > > Item;
+ ListOf< Lazy< IfcPresentationStyleAssignment >, 1, 0 > Styles;
+ Maybe< IfcLabel::Out > Name;
};
- // C++ wrapper for IfcRepresentationItem
- struct IfcRepresentationItem : ObjectHelper<IfcRepresentationItem,0> { IfcRepresentationItem() : Object("IfcRepresentationItem") {}
+ // C++ wrapper for IfcAnnotationOccurrence
+ struct IfcAnnotationOccurrence : IfcStyledItem, ObjectHelper<IfcAnnotationOccurrence,0> { IfcAnnotationOccurrence() : Object("IfcAnnotationOccurrence") {}
};
- // C++ wrapper for IfcGeometricRepresentationItem
- struct IfcGeometricRepresentationItem : IfcRepresentationItem, ObjectHelper<IfcGeometricRepresentationItem,0> { IfcGeometricRepresentationItem() : Object("IfcGeometricRepresentationItem") {}
+ // C++ wrapper for IfcAnnotationCurveOccurrence
+ struct IfcAnnotationCurveOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationCurveOccurrence,0> { IfcAnnotationCurveOccurrence() : Object("IfcAnnotationCurveOccurrence") {}
};
- // C++ wrapper for IfcTextLiteral
- struct IfcTextLiteral : IfcGeometricRepresentationItem, ObjectHelper<IfcTextLiteral,3> { IfcTextLiteral() : Object("IfcTextLiteral") {}
- IfcPresentableText::Out Literal;
- IfcAxis2Placement::Out Placement;
- IfcTextPath::Out Path;
+ // C++ wrapper for IfcAnnotationFillArea
+ struct IfcAnnotationFillArea : IfcGeometricRepresentationItem, ObjectHelper<IfcAnnotationFillArea,2> { IfcAnnotationFillArea() : Object("IfcAnnotationFillArea") {}
+ Lazy< IfcCurve > OuterBoundary;
+ Maybe< ListOf< Lazy< IfcCurve >, 1, 0 > > InnerBoundaries;
};
- // C++ wrapper for IfcTextLiteralWithExtent
- struct IfcTextLiteralWithExtent : IfcTextLiteral, ObjectHelper<IfcTextLiteralWithExtent,2> { IfcTextLiteralWithExtent() : Object("IfcTextLiteralWithExtent") {}
- Lazy< IfcPlanarExtent > Extent;
- IfcBoxAlignment::Out BoxAlignment;
+ // C++ wrapper for IfcAnnotationFillAreaOccurrence
+ struct IfcAnnotationFillAreaOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationFillAreaOccurrence,2> { IfcAnnotationFillAreaOccurrence() : Object("IfcAnnotationFillAreaOccurrence") {}
+ Maybe< Lazy< IfcPoint > > FillStyleTarget;
+ Maybe< IfcGlobalOrLocalEnum::Out > GlobalOrLocal;
};
- // C++ wrapper for IfcProductRepresentation
- struct IfcProductRepresentation : ObjectHelper<IfcProductRepresentation,3> { IfcProductRepresentation() : Object("IfcProductRepresentation") {}
- Maybe< IfcLabel::Out > Name;
- Maybe< IfcText::Out > Description;
- ListOf< Lazy< IfcRepresentation >, 1, 0 > Representations;
+ // C++ wrapper for IfcAnnotationSurface
+ struct IfcAnnotationSurface : IfcGeometricRepresentationItem, ObjectHelper<IfcAnnotationSurface,2> { IfcAnnotationSurface() : Object("IfcAnnotationSurface") {}
+ Lazy< IfcGeometricRepresentationItem > Item;
+ Maybe< Lazy< NotImplemented > > TextureCoordinates;
};
- // C++ wrapper for IfcProduct
- struct IfcProduct : IfcObject, ObjectHelper<IfcProduct,2> { IfcProduct() : Object("IfcProduct") {}
- Maybe< Lazy< IfcObjectPlacement > > ObjectPlacement;
- Maybe< Lazy< IfcProductRepresentation > > Representation;
- };
+ // C++ wrapper for IfcAnnotationSurfaceOccurrence
+ struct IfcAnnotationSurfaceOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationSurfaceOccurrence,0> { IfcAnnotationSurfaceOccurrence() : Object("IfcAnnotationSurfaceOccurrence") {}
- // C++ wrapper for IfcElement
- struct IfcElement : IfcProduct, ObjectHelper<IfcElement,1> { IfcElement() : Object("IfcElement") {}
- Maybe< IfcIdentifier::Out > Tag;
};
- // C++ wrapper for IfcDistributionElement
- struct IfcDistributionElement : IfcElement, ObjectHelper<IfcDistributionElement,0> { IfcDistributionElement() : Object("IfcDistributionElement") {}
+ // C++ wrapper for IfcAnnotationSymbolOccurrence
+ struct IfcAnnotationSymbolOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationSymbolOccurrence,0> { IfcAnnotationSymbolOccurrence() : Object("IfcAnnotationSymbolOccurrence") {}
};
- // C++ wrapper for IfcDistributionFlowElement
- struct IfcDistributionFlowElement : IfcDistributionElement, ObjectHelper<IfcDistributionFlowElement,0> { IfcDistributionFlowElement() : Object("IfcDistributionFlowElement") {}
+ // C++ wrapper for IfcAnnotationTextOccurrence
+ struct IfcAnnotationTextOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationTextOccurrence,0> { IfcAnnotationTextOccurrence() : Object("IfcAnnotationTextOccurrence") {}
};
- // C++ wrapper for IfcCurve
- struct IfcCurve : IfcGeometricRepresentationItem, ObjectHelper<IfcCurve,0> { IfcCurve() : Object("IfcCurve") {}
-
+ // C++ wrapper for IfcProfileDef
+ struct IfcProfileDef : ObjectHelper<IfcProfileDef,2> { IfcProfileDef() : Object("IfcProfileDef") {}
+ IfcProfileTypeEnum::Out ProfileType;
+ Maybe< IfcLabel::Out > ProfileName;
};
- // C++ wrapper for IfcBoundedCurve
- struct IfcBoundedCurve : IfcCurve, ObjectHelper<IfcBoundedCurve,0> { IfcBoundedCurve() : Object("IfcBoundedCurve") {}
+ // C++ wrapper for IfcArbitraryClosedProfileDef
+ struct IfcArbitraryClosedProfileDef : IfcProfileDef, ObjectHelper<IfcArbitraryClosedProfileDef,1> { IfcArbitraryClosedProfileDef() : Object("IfcArbitraryClosedProfileDef") {}
+ Lazy< IfcCurve > OuterCurve;
+ };
+ // C++ wrapper for IfcArbitraryOpenProfileDef
+ struct IfcArbitraryOpenProfileDef : IfcProfileDef, ObjectHelper<IfcArbitraryOpenProfileDef,1> { IfcArbitraryOpenProfileDef() : Object("IfcArbitraryOpenProfileDef") {}
+ Lazy< IfcBoundedCurve > Curve;
};
- // C++ wrapper for IfcCompositeCurve
- struct IfcCompositeCurve : IfcBoundedCurve, ObjectHelper<IfcCompositeCurve,2> { IfcCompositeCurve() : Object("IfcCompositeCurve") {}
- ListOf< Lazy< IfcCompositeCurveSegment >, 1, 0 > Segments;
- LOGICAL::Out SelfIntersect;
+ // C++ wrapper for IfcArbitraryProfileDefWithVoids
+ struct IfcArbitraryProfileDefWithVoids : IfcArbitraryClosedProfileDef, ObjectHelper<IfcArbitraryProfileDefWithVoids,1> { IfcArbitraryProfileDefWithVoids() : Object("IfcArbitraryProfileDefWithVoids") {}
+ ListOf< Lazy< IfcCurve >, 1, 0 > InnerCurves;
};
- // C++ wrapper for Ifc2DCompositeCurve
- struct Ifc2DCompositeCurve : IfcCompositeCurve, ObjectHelper<Ifc2DCompositeCurve,0> { Ifc2DCompositeCurve() : Object("Ifc2DCompositeCurve") {}
+ // C++ wrapper for IfcGroup
+ struct IfcGroup : IfcObject, ObjectHelper<IfcGroup,0> { IfcGroup() : Object("IfcGroup") {}
};
- // C++ wrapper for IfcCartesianTransformationOperator
- struct IfcCartesianTransformationOperator : IfcGeometricRepresentationItem, ObjectHelper<IfcCartesianTransformationOperator,4> { IfcCartesianTransformationOperator() : Object("IfcCartesianTransformationOperator") {}
- Maybe< Lazy< IfcDirection > > Axis1;
- Maybe< Lazy< IfcDirection > > Axis2;
- Lazy< IfcCartesianPoint > LocalOrigin;
- Maybe< REAL::Out > Scale;
+ // C++ wrapper for IfcAsset
+ struct IfcAsset : IfcGroup, ObjectHelper<IfcAsset,9> { IfcAsset() : Object("IfcAsset") {}
+ IfcIdentifier::Out AssetID;
+ Lazy< NotImplemented > OriginalValue;
+ Lazy< NotImplemented > CurrentValue;
+ Lazy< NotImplemented > TotalReplacementCost;
+ IfcActorSelect::Out Owner;
+ IfcActorSelect::Out User;
+ Lazy< NotImplemented > ResponsiblePerson;
+ Lazy< NotImplemented > IncorporationDate;
+ Lazy< NotImplemented > DepreciatedValue;
};
- // C++ wrapper for IfcCartesianTransformationOperator3D
- struct IfcCartesianTransformationOperator3D : IfcCartesianTransformationOperator, ObjectHelper<IfcCartesianTransformationOperator3D,1> { IfcCartesianTransformationOperator3D() : Object("IfcCartesianTransformationOperator3D") {}
- Maybe< Lazy< IfcDirection > > Axis3;
+ // C++ wrapper for IfcParameterizedProfileDef
+ struct IfcParameterizedProfileDef : IfcProfileDef, ObjectHelper<IfcParameterizedProfileDef,1> { IfcParameterizedProfileDef() : Object("IfcParameterizedProfileDef") {}
+ Lazy< IfcAxis2Placement2D > Position;
};
- // C++ wrapper for IfcProperty
- struct IfcProperty : ObjectHelper<IfcProperty,2> { IfcProperty() : Object("IfcProperty") {}
- IfcIdentifier::Out Name;
- Maybe< IfcText::Out > Description;
+ // C++ wrapper for IfcIShapeProfileDef
+ struct IfcIShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcIShapeProfileDef,5> { IfcIShapeProfileDef() : Object("IfcIShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out OverallWidth;
+ IfcPositiveLengthMeasure::Out OverallDepth;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out FlangeThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
};
- // C++ wrapper for IfcSimpleProperty
- struct IfcSimpleProperty : IfcProperty, ObjectHelper<IfcSimpleProperty,0> { IfcSimpleProperty() : Object("IfcSimpleProperty") {}
-
+ // C++ wrapper for IfcAsymmetricIShapeProfileDef
+ struct IfcAsymmetricIShapeProfileDef : IfcIShapeProfileDef, ObjectHelper<IfcAsymmetricIShapeProfileDef,4> { IfcAsymmetricIShapeProfileDef() : Object("IfcAsymmetricIShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out TopFlangeWidth;
+ Maybe< IfcPositiveLengthMeasure::Out > TopFlangeThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > TopFlangeFilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcPropertyEnumeratedValue
- struct IfcPropertyEnumeratedValue : IfcSimpleProperty, ObjectHelper<IfcPropertyEnumeratedValue,2> { IfcPropertyEnumeratedValue() : Object("IfcPropertyEnumeratedValue") {}
- ListOf< IfcValue, 1, 0 >::Out EnumerationValues;
- Maybe< Lazy< NotImplemented > > EnumerationReference;
+ // C++ wrapper for IfcPlacement
+ struct IfcPlacement : IfcGeometricRepresentationItem, ObjectHelper<IfcPlacement,1> { IfcPlacement() : Object("IfcPlacement") {}
+ Lazy< IfcCartesianPoint > Location;
};
- // C++ wrapper for IfcBuildingElementType
- struct IfcBuildingElementType : IfcElementType, ObjectHelper<IfcBuildingElementType,0> { IfcBuildingElementType() : Object("IfcBuildingElementType") {}
-
+ // C++ wrapper for IfcAxis1Placement
+ struct IfcAxis1Placement : IfcPlacement, ObjectHelper<IfcAxis1Placement,1> { IfcAxis1Placement() : Object("IfcAxis1Placement") {}
+ Maybe< Lazy< IfcDirection > > Axis;
};
- // C++ wrapper for IfcStairFlightType
- struct IfcStairFlightType : IfcBuildingElementType, ObjectHelper<IfcStairFlightType,1> { IfcStairFlightType() : Object("IfcStairFlightType") {}
- IfcStairFlightTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcAxis2Placement2D
+ struct IfcAxis2Placement2D : IfcPlacement, ObjectHelper<IfcAxis2Placement2D,1> { IfcAxis2Placement2D() : Object("IfcAxis2Placement2D") {}
+ Maybe< Lazy< IfcDirection > > RefDirection;
};
- // C++ wrapper for IfcSurface
- struct IfcSurface : IfcGeometricRepresentationItem, ObjectHelper<IfcSurface,0> { IfcSurface() : Object("IfcSurface") {}
-
+ // C++ wrapper for IfcAxis2Placement3D
+ struct IfcAxis2Placement3D : IfcPlacement, ObjectHelper<IfcAxis2Placement3D,2> { IfcAxis2Placement3D() : Object("IfcAxis2Placement3D") {}
+ Maybe< Lazy< IfcDirection > > Axis;
+ Maybe< Lazy< IfcDirection > > RefDirection;
};
- // C++ wrapper for IfcElementarySurface
- struct IfcElementarySurface : IfcSurface, ObjectHelper<IfcElementarySurface,1> { IfcElementarySurface() : Object("IfcElementarySurface") {}
- Lazy< IfcAxis2Placement3D > Position;
+ // C++ wrapper for IfcBSplineCurve
+ struct IfcBSplineCurve : IfcBoundedCurve, ObjectHelper<IfcBSplineCurve,5> { IfcBSplineCurve() : Object("IfcBSplineCurve") {}
+ INTEGER::Out Degree;
+ ListOf< Lazy< IfcCartesianPoint >, 2, 0 > ControlPointsList;
+ IfcBSplineCurveForm::Out CurveForm;
+ LOGICAL::Out ClosedCurve;
+ LOGICAL::Out SelfIntersect;
};
- // C++ wrapper for IfcPlane
- struct IfcPlane : IfcElementarySurface, ObjectHelper<IfcPlane,0> { IfcPlane() : Object("IfcPlane") {}
-
+ // C++ wrapper for IfcElement
+ struct IfcElement : IfcProduct, ObjectHelper<IfcElement,1> { IfcElement() : Object("IfcElement") {}
+ Maybe< IfcIdentifier::Out > Tag;
};
- // C++ wrapper for IfcBooleanResult
- struct IfcBooleanResult : IfcGeometricRepresentationItem, ObjectHelper<IfcBooleanResult,3> { IfcBooleanResult() : Object("IfcBooleanResult") {}
- IfcBooleanOperator::Out Operator;
- IfcBooleanOperand::Out FirstOperand;
- IfcBooleanOperand::Out SecondOperand;
+ // C++ wrapper for IfcBuildingElement
+ struct IfcBuildingElement : IfcElement, ObjectHelper<IfcBuildingElement,0> { IfcBuildingElement() : Object("IfcBuildingElement") {}
+
};
- // C++ wrapper for IfcBooleanClippingResult
- struct IfcBooleanClippingResult : IfcBooleanResult, ObjectHelper<IfcBooleanClippingResult,0> { IfcBooleanClippingResult() : Object("IfcBooleanClippingResult") {}
+ // C++ wrapper for IfcBeam
+ struct IfcBeam : IfcBuildingElement, ObjectHelper<IfcBeam,0> { IfcBeam() : Object("IfcBeam") {}
};
- // C++ wrapper for IfcSolidModel
- struct IfcSolidModel : IfcGeometricRepresentationItem, ObjectHelper<IfcSolidModel,0> { IfcSolidModel() : Object("IfcSolidModel") {}
+ // C++ wrapper for IfcBuildingElementType
+ struct IfcBuildingElementType : IfcElementType, ObjectHelper<IfcBuildingElementType,0> { IfcBuildingElementType() : Object("IfcBuildingElementType") {}
};
- // C++ wrapper for IfcManifoldSolidBrep
- struct IfcManifoldSolidBrep : IfcSolidModel, ObjectHelper<IfcManifoldSolidBrep,1> { IfcManifoldSolidBrep() : Object("IfcManifoldSolidBrep") {}
- Lazy< IfcClosedShell > Outer;
+ // C++ wrapper for IfcBeamType
+ struct IfcBeamType : IfcBuildingElementType, ObjectHelper<IfcBeamType,1> { IfcBeamType() : Object("IfcBeamType") {}
+ IfcBeamTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowTerminalType
- struct IfcFlowTerminalType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowTerminalType,0> { IfcFlowTerminalType() : Object("IfcFlowTerminalType") {}
+ // C++ wrapper for IfcBezierCurve
+ struct IfcBezierCurve : IfcBSplineCurve, ObjectHelper<IfcBezierCurve,0> { IfcBezierCurve() : Object("IfcBezierCurve") {}
};
- // C++ wrapper for IfcStackTerminalType
- struct IfcStackTerminalType : IfcFlowTerminalType, ObjectHelper<IfcStackTerminalType,1> { IfcStackTerminalType() : Object("IfcStackTerminalType") {}
- IfcStackTerminalTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCsgPrimitive3D
+ struct IfcCsgPrimitive3D : IfcGeometricRepresentationItem, ObjectHelper<IfcCsgPrimitive3D,1> { IfcCsgPrimitive3D() : Object("IfcCsgPrimitive3D") {}
+ Lazy< IfcAxis2Placement3D > Position;
};
- // C++ wrapper for IfcStructuralItem
- struct IfcStructuralItem : IfcProduct, ObjectHelper<IfcStructuralItem,0> { IfcStructuralItem() : Object("IfcStructuralItem") {}
-
+ // C++ wrapper for IfcBlock
+ struct IfcBlock : IfcCsgPrimitive3D, ObjectHelper<IfcBlock,3> { IfcBlock() : Object("IfcBlock") {}
+ IfcPositiveLengthMeasure::Out XLength;
+ IfcPositiveLengthMeasure::Out YLength;
+ IfcPositiveLengthMeasure::Out ZLength;
};
- // C++ wrapper for IfcStructuralConnection
- struct IfcStructuralConnection : IfcStructuralItem, ObjectHelper<IfcStructuralConnection,1> { IfcStructuralConnection() : Object("IfcStructuralConnection") {}
- Maybe< Lazy< NotImplemented > > AppliedCondition;
+ // C++ wrapper for IfcBoilerType
+ struct IfcBoilerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcBoilerType,1> { IfcBoilerType() : Object("IfcBoilerType") {}
+ IfcBoilerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralCurveConnection
- struct IfcStructuralCurveConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralCurveConnection,0> { IfcStructuralCurveConnection() : Object("IfcStructuralCurveConnection") {}
-
+ // C++ wrapper for IfcBooleanResult
+ struct IfcBooleanResult : IfcGeometricRepresentationItem, ObjectHelper<IfcBooleanResult,3> { IfcBooleanResult() : Object("IfcBooleanResult") {}
+ IfcBooleanOperator::Out Operator;
+ IfcBooleanOperand::Out FirstOperand;
+ IfcBooleanOperand::Out SecondOperand;
};
- // C++ wrapper for IfcJunctionBoxType
- struct IfcJunctionBoxType : IfcFlowFittingType, ObjectHelper<IfcJunctionBoxType,1> { IfcJunctionBoxType() : Object("IfcJunctionBoxType") {}
- IfcJunctionBoxTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcBooleanClippingResult
+ struct IfcBooleanClippingResult : IfcBooleanResult, ObjectHelper<IfcBooleanClippingResult,0> { IfcBooleanClippingResult() : Object("IfcBooleanClippingResult") {}
+
};
- // C++ wrapper for IfcPropertyDefinition
- struct IfcPropertyDefinition : IfcRoot, ObjectHelper<IfcPropertyDefinition,0> { IfcPropertyDefinition() : Object("IfcPropertyDefinition") {}
+ // C++ wrapper for IfcSurface
+ struct IfcSurface : IfcGeometricRepresentationItem, ObjectHelper<IfcSurface,0> { IfcSurface() : Object("IfcSurface") {}
};
- // C++ wrapper for IfcPropertySetDefinition
- struct IfcPropertySetDefinition : IfcPropertyDefinition, ObjectHelper<IfcPropertySetDefinition,0> { IfcPropertySetDefinition() : Object("IfcPropertySetDefinition") {}
+ // C++ wrapper for IfcBoundedSurface
+ struct IfcBoundedSurface : IfcSurface, ObjectHelper<IfcBoundedSurface,0> { IfcBoundedSurface() : Object("IfcBoundedSurface") {}
};
- // C++ wrapper for IfcProcess
- struct IfcProcess : IfcObject, ObjectHelper<IfcProcess,0> { IfcProcess() : Object("IfcProcess") {}
-
+ // C++ wrapper for IfcBoundingBox
+ struct IfcBoundingBox : IfcGeometricRepresentationItem, ObjectHelper<IfcBoundingBox,4> { IfcBoundingBox() : Object("IfcBoundingBox") {}
+ Lazy< IfcCartesianPoint > Corner;
+ IfcPositiveLengthMeasure::Out XDim;
+ IfcPositiveLengthMeasure::Out YDim;
+ IfcPositiveLengthMeasure::Out ZDim;
};
- // C++ wrapper for IfcTask
- struct IfcTask : IfcProcess, ObjectHelper<IfcTask,5> { IfcTask() : Object("IfcTask") {}
- IfcIdentifier::Out TaskId;
- Maybe< IfcLabel::Out > Status;
- Maybe< IfcLabel::Out > WorkMethod;
- BOOLEAN::Out IsMilestone;
- Maybe< INTEGER::Out > Priority;
+ // C++ wrapper for IfcHalfSpaceSolid
+ struct IfcHalfSpaceSolid : IfcGeometricRepresentationItem, ObjectHelper<IfcHalfSpaceSolid,2> { IfcHalfSpaceSolid() : Object("IfcHalfSpaceSolid") {}
+ Lazy< IfcSurface > BaseSurface;
+ BOOLEAN::Out AgreementFlag;
};
- // C++ wrapper for IfcRelFillsElement
- struct IfcRelFillsElement : IfcRelConnects, ObjectHelper<IfcRelFillsElement,2> { IfcRelFillsElement() : Object("IfcRelFillsElement") {}
- Lazy< IfcOpeningElement > RelatingOpeningElement;
- Lazy< IfcElement > RelatedBuildingElement;
+ // C++ wrapper for IfcBoxedHalfSpace
+ struct IfcBoxedHalfSpace : IfcHalfSpaceSolid, ObjectHelper<IfcBoxedHalfSpace,1> { IfcBoxedHalfSpace() : Object("IfcBoxedHalfSpace") {}
+ Lazy< IfcBoundingBox > Enclosure;
};
- // C++ wrapper for IfcProcedure
- struct IfcProcedure : IfcProcess, ObjectHelper<IfcProcedure,3> { IfcProcedure() : Object("IfcProcedure") {}
- IfcIdentifier::Out ProcedureID;
- IfcProcedureTypeEnum::Out ProcedureType;
- Maybe< IfcLabel::Out > UserDefinedProcedureType;
+ // C++ wrapper for IfcSpatialStructureElement
+ struct IfcSpatialStructureElement : IfcProduct, ObjectHelper<IfcSpatialStructureElement,2> { IfcSpatialStructureElement() : Object("IfcSpatialStructureElement") {}
+ Maybe< IfcLabel::Out > LongName;
+ IfcElementCompositionEnum::Out CompositionType;
};
- // C++ wrapper for IfcProxy
- struct IfcProxy : IfcProduct, ObjectHelper<IfcProxy,2> { IfcProxy() : Object("IfcProxy") {}
- IfcObjectTypeEnum::Out ProxyType;
- Maybe< IfcLabel::Out > Tag;
+ // C++ wrapper for IfcBuilding
+ struct IfcBuilding : IfcSpatialStructureElement, ObjectHelper<IfcBuilding,3> { IfcBuilding() : Object("IfcBuilding") {}
+ Maybe< IfcLengthMeasure::Out > ElevationOfRefHeight;
+ Maybe< IfcLengthMeasure::Out > ElevationOfTerrain;
+ Maybe< Lazy< NotImplemented > > BuildingAddress;
};
- // C++ wrapper for IfcResource
- struct IfcResource : IfcObject, ObjectHelper<IfcResource,0> { IfcResource() : Object("IfcResource") {}
+ // C++ wrapper for IfcBuildingElementComponent
+ struct IfcBuildingElementComponent : IfcBuildingElement, ObjectHelper<IfcBuildingElementComponent,0> { IfcBuildingElementComponent() : Object("IfcBuildingElementComponent") {}
};
- // C++ wrapper for IfcConstructionResource
- struct IfcConstructionResource : IfcResource, ObjectHelper<IfcConstructionResource,4> { IfcConstructionResource() : Object("IfcConstructionResource") {}
- Maybe< IfcIdentifier::Out > ResourceIdentifier;
- Maybe< IfcLabel::Out > ResourceGroup;
- Maybe< IfcResourceConsumptionEnum::Out > ResourceConsumption;
- Maybe< Lazy< IfcMeasureWithUnit > > BaseQuantity;
- };
+ // C++ wrapper for IfcBuildingElementPart
+ struct IfcBuildingElementPart : IfcBuildingElementComponent, ObjectHelper<IfcBuildingElementPart,0> { IfcBuildingElementPart() : Object("IfcBuildingElementPart") {}
- // C++ wrapper for IfcSubContractResource
- struct IfcSubContractResource : IfcConstructionResource, ObjectHelper<IfcSubContractResource,2> { IfcSubContractResource() : Object("IfcSubContractResource") {}
- Maybe< IfcActorSelect::Out > SubContractor;
- Maybe< IfcText::Out > JobDescription;
};
- // C++ wrapper for IfcRelContainedInSpatialStructure
- struct IfcRelContainedInSpatialStructure : IfcRelConnects, ObjectHelper<IfcRelContainedInSpatialStructure,2> { IfcRelContainedInSpatialStructure() : Object("IfcRelContainedInSpatialStructure") {}
- ListOf< Lazy< IfcProduct >, 1, 0 > RelatedElements;
- Lazy< IfcSpatialStructureElement > RelatingStructure;
+ // C++ wrapper for IfcBuildingElementProxy
+ struct IfcBuildingElementProxy : IfcBuildingElement, ObjectHelper<IfcBuildingElementProxy,1> { IfcBuildingElementProxy() : Object("IfcBuildingElementProxy") {}
+ Maybe< IfcElementCompositionEnum::Out > CompositionType;
};
- // C++ wrapper for IfcTopologicalRepresentationItem
- struct IfcTopologicalRepresentationItem : IfcRepresentationItem, ObjectHelper<IfcTopologicalRepresentationItem,0> { IfcTopologicalRepresentationItem() : Object("IfcTopologicalRepresentationItem") {}
+ // C++ wrapper for IfcBuildingElementProxyType
+ struct IfcBuildingElementProxyType : IfcBuildingElementType, ObjectHelper<IfcBuildingElementProxyType,1> { IfcBuildingElementProxyType() : Object("IfcBuildingElementProxyType") {}
+ IfcBuildingElementProxyTypeEnum::Out PredefinedType;
+ };
+ // C++ wrapper for IfcBuildingStorey
+ struct IfcBuildingStorey : IfcSpatialStructureElement, ObjectHelper<IfcBuildingStorey,1> { IfcBuildingStorey() : Object("IfcBuildingStorey") {}
+ Maybe< IfcLengthMeasure::Out > Elevation;
};
- // C++ wrapper for IfcEdge
- struct IfcEdge : IfcTopologicalRepresentationItem, ObjectHelper<IfcEdge,2> { IfcEdge() : Object("IfcEdge") {}
- Lazy< IfcVertex > EdgeStart;
- Lazy< IfcVertex > EdgeEnd;
+ // C++ wrapper for IfcCShapeProfileDef
+ struct IfcCShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCShapeProfileDef,6> { IfcCShapeProfileDef() : Object("IfcCShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out Depth;
+ IfcPositiveLengthMeasure::Out Width;
+ IfcPositiveLengthMeasure::Out WallThickness;
+ IfcPositiveLengthMeasure::Out Girth;
+ Maybe< IfcPositiveLengthMeasure::Out > InternalFilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
};
- // C++ wrapper for IfcEdgeCurve
- struct IfcEdgeCurve : IfcEdge, ObjectHelper<IfcEdgeCurve,2> { IfcEdgeCurve() : Object("IfcEdgeCurve") {}
- Lazy< IfcCurve > EdgeGeometry;
- BOOLEAN::Out SameSense;
+ // C++ wrapper for IfcFlowFittingType
+ struct IfcFlowFittingType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowFittingType,0> { IfcFlowFittingType() : Object("IfcFlowFittingType") {}
+
};
- // C++ wrapper for IfcPlateType
- struct IfcPlateType : IfcBuildingElementType, ObjectHelper<IfcPlateType,1> { IfcPlateType() : Object("IfcPlateType") {}
- IfcPlateTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCableCarrierFittingType
+ struct IfcCableCarrierFittingType : IfcFlowFittingType, ObjectHelper<IfcCableCarrierFittingType,1> { IfcCableCarrierFittingType() : Object("IfcCableCarrierFittingType") {}
+ IfcCableCarrierFittingTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcObjectPlacement
- struct IfcObjectPlacement : ObjectHelper<IfcObjectPlacement,0> { IfcObjectPlacement() : Object("IfcObjectPlacement") {}
+ // C++ wrapper for IfcFlowSegmentType
+ struct IfcFlowSegmentType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowSegmentType,0> { IfcFlowSegmentType() : Object("IfcFlowSegmentType") {}
};
- // C++ wrapper for IfcGridPlacement
- struct IfcGridPlacement : IfcObjectPlacement, ObjectHelper<IfcGridPlacement,2> { IfcGridPlacement() : Object("IfcGridPlacement") {}
- Lazy< NotImplemented > PlacementLocation;
- Maybe< Lazy< NotImplemented > > PlacementRefDirection;
+ // C++ wrapper for IfcCableCarrierSegmentType
+ struct IfcCableCarrierSegmentType : IfcFlowSegmentType, ObjectHelper<IfcCableCarrierSegmentType,1> { IfcCableCarrierSegmentType() : Object("IfcCableCarrierSegmentType") {}
+ IfcCableCarrierSegmentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFireSuppressionTerminalType
- struct IfcFireSuppressionTerminalType : IfcFlowTerminalType, ObjectHelper<IfcFireSuppressionTerminalType,1> { IfcFireSuppressionTerminalType() : Object("IfcFireSuppressionTerminalType") {}
- IfcFireSuppressionTerminalTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCableSegmentType
+ struct IfcCableSegmentType : IfcFlowSegmentType, ObjectHelper<IfcCableSegmentType,1> { IfcCableSegmentType() : Object("IfcCableSegmentType") {}
+ IfcCableSegmentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowStorageDevice
- struct IfcFlowStorageDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowStorageDevice,0> { IfcFlowStorageDevice() : Object("IfcFlowStorageDevice") {}
+ // C++ wrapper for IfcPoint
+ struct IfcPoint : IfcGeometricRepresentationItem, ObjectHelper<IfcPoint,0> { IfcPoint() : Object("IfcPoint") {}
};
- // C++ wrapper for IfcSweptSurface
- struct IfcSweptSurface : IfcSurface, ObjectHelper<IfcSweptSurface,2> { IfcSweptSurface() : Object("IfcSweptSurface") {}
- Lazy< IfcProfileDef > SweptCurve;
- Lazy< IfcAxis2Placement3D > Position;
+ // C++ wrapper for IfcCartesianPoint
+ struct IfcCartesianPoint : IfcPoint, ObjectHelper<IfcCartesianPoint,1> { IfcCartesianPoint() : Object("IfcCartesianPoint") {}
+ ListOf< IfcLengthMeasure, 1, 3 >::Out Coordinates;
};
- // C++ wrapper for IfcSurfaceOfRevolution
- struct IfcSurfaceOfRevolution : IfcSweptSurface, ObjectHelper<IfcSurfaceOfRevolution,1> { IfcSurfaceOfRevolution() : Object("IfcSurfaceOfRevolution") {}
- Lazy< IfcAxis1Placement > AxisPosition;
+ // C++ wrapper for IfcCartesianTransformationOperator
+ struct IfcCartesianTransformationOperator : IfcGeometricRepresentationItem, ObjectHelper<IfcCartesianTransformationOperator,4> { IfcCartesianTransformationOperator() : Object("IfcCartesianTransformationOperator") {}
+ Maybe< Lazy< IfcDirection > > Axis1;
+ Maybe< Lazy< IfcDirection > > Axis2;
+ Lazy< IfcCartesianPoint > LocalOrigin;
+ Maybe< REAL::Out > Scale;
};
- // C++ wrapper for IfcOrientedEdge
- struct IfcOrientedEdge : IfcEdge, ObjectHelper<IfcOrientedEdge,2> { IfcOrientedEdge() : Object("IfcOrientedEdge") {}
- Lazy< IfcEdge > EdgeElement;
- BOOLEAN::Out Orientation;
+ // C++ wrapper for IfcCartesianTransformationOperator2D
+ struct IfcCartesianTransformationOperator2D : IfcCartesianTransformationOperator, ObjectHelper<IfcCartesianTransformationOperator2D,0> { IfcCartesianTransformationOperator2D() : Object("IfcCartesianTransformationOperator2D") {}
+
};
- // C++ wrapper for IfcDirection
- struct IfcDirection : IfcGeometricRepresentationItem, ObjectHelper<IfcDirection,1> { IfcDirection() : Object("IfcDirection") {}
- ListOf< REAL, 2, 3 >::Out DirectionRatios;
+ // C++ wrapper for IfcCartesianTransformationOperator2DnonUniform
+ struct IfcCartesianTransformationOperator2DnonUniform : IfcCartesianTransformationOperator2D, ObjectHelper<IfcCartesianTransformationOperator2DnonUniform,1> { IfcCartesianTransformationOperator2DnonUniform() : Object("IfcCartesianTransformationOperator2DnonUniform") {}
+ Maybe< REAL::Out > Scale2;
};
- // C++ wrapper for IfcProfileDef
- struct IfcProfileDef : ObjectHelper<IfcProfileDef,2> { IfcProfileDef() : Object("IfcProfileDef") {}
- IfcProfileTypeEnum::Out ProfileType;
- Maybe< IfcLabel::Out > ProfileName;
+ // C++ wrapper for IfcCartesianTransformationOperator3D
+ struct IfcCartesianTransformationOperator3D : IfcCartesianTransformationOperator, ObjectHelper<IfcCartesianTransformationOperator3D,1> { IfcCartesianTransformationOperator3D() : Object("IfcCartesianTransformationOperator3D") {}
+ Maybe< Lazy< IfcDirection > > Axis3;
};
- // C++ wrapper for IfcParameterizedProfileDef
- struct IfcParameterizedProfileDef : IfcProfileDef, ObjectHelper<IfcParameterizedProfileDef,1> { IfcParameterizedProfileDef() : Object("IfcParameterizedProfileDef") {}
- Lazy< IfcAxis2Placement2D > Position;
+ // C++ wrapper for IfcCartesianTransformationOperator3DnonUniform
+ struct IfcCartesianTransformationOperator3DnonUniform : IfcCartesianTransformationOperator3D, ObjectHelper<IfcCartesianTransformationOperator3DnonUniform,2> { IfcCartesianTransformationOperator3DnonUniform() : Object("IfcCartesianTransformationOperator3DnonUniform") {}
+ Maybe< REAL::Out > Scale2;
+ Maybe< REAL::Out > Scale3;
};
- // C++ wrapper for IfcCShapeProfileDef
- struct IfcCShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCShapeProfileDef,6> { IfcCShapeProfileDef() : Object("IfcCShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out Depth;
- IfcPositiveLengthMeasure::Out Width;
- IfcPositiveLengthMeasure::Out WallThickness;
- IfcPositiveLengthMeasure::Out Girth;
- Maybe< IfcPositiveLengthMeasure::Out > InternalFilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
+ // C++ wrapper for IfcCenterLineProfileDef
+ struct IfcCenterLineProfileDef : IfcArbitraryOpenProfileDef, ObjectHelper<IfcCenterLineProfileDef,1> { IfcCenterLineProfileDef() : Object("IfcCenterLineProfileDef") {}
+ IfcPositiveLengthMeasure::Out Thickness;
};
// C++ wrapper for IfcFeatureElement
@@ -1833,2531 +1895,2469 @@ namespace IFC {
// C++ wrapper for IfcEdgeFeature
struct IfcEdgeFeature : IfcFeatureElementSubtraction, ObjectHelper<IfcEdgeFeature,1> { IfcEdgeFeature() : Object("IfcEdgeFeature") {}
- Maybe< IfcPositiveLengthMeasure::Out > FeatureLength;
+ Maybe< IfcPositiveLengthMeasure::Out > FeatureLength;
};
// C++ wrapper for IfcChamferEdgeFeature
struct IfcChamferEdgeFeature : IfcEdgeFeature, ObjectHelper<IfcChamferEdgeFeature,2> { IfcChamferEdgeFeature() : Object("IfcChamferEdgeFeature") {}
- Maybe< IfcPositiveLengthMeasure::Out > Width;
- Maybe< IfcPositiveLengthMeasure::Out > Height;
+ Maybe< IfcPositiveLengthMeasure::Out > Width;
+ Maybe< IfcPositiveLengthMeasure::Out > Height;
};
- // C++ wrapper for IfcBuildingElement
- struct IfcBuildingElement : IfcElement, ObjectHelper<IfcBuildingElement,0> { IfcBuildingElement() : Object("IfcBuildingElement") {}
-
+ // C++ wrapper for IfcChillerType
+ struct IfcChillerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcChillerType,1> { IfcChillerType() : Object("IfcChillerType") {}
+ IfcChillerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcColumn
- struct IfcColumn : IfcBuildingElement, ObjectHelper<IfcColumn,0> { IfcColumn() : Object("IfcColumn") {}
+ // C++ wrapper for IfcConic
+ struct IfcConic : IfcCurve, ObjectHelper<IfcConic,1> { IfcConic() : Object("IfcConic") {}
+ IfcAxis2Placement::Out Position;
+ };
+ // C++ wrapper for IfcCircle
+ struct IfcCircle : IfcConic, ObjectHelper<IfcCircle,1> { IfcCircle() : Object("IfcCircle") {}
+ IfcPositiveLengthMeasure::Out Radius;
};
- // C++ wrapper for IfcPropertyReferenceValue
- struct IfcPropertyReferenceValue : IfcSimpleProperty, ObjectHelper<IfcPropertyReferenceValue,2> { IfcPropertyReferenceValue() : Object("IfcPropertyReferenceValue") {}
- Maybe< IfcLabel::Out > UsageName;
- IfcObjectReferenceSelect::Out PropertyReference;
+ // C++ wrapper for IfcCircleProfileDef
+ struct IfcCircleProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCircleProfileDef,1> { IfcCircleProfileDef() : Object("IfcCircleProfileDef") {}
+ IfcPositiveLengthMeasure::Out Radius;
};
- // C++ wrapper for IfcElectricMotorType
- struct IfcElectricMotorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcElectricMotorType,1> { IfcElectricMotorType() : Object("IfcElectricMotorType") {}
- IfcElectricMotorTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCircleHollowProfileDef
+ struct IfcCircleHollowProfileDef : IfcCircleProfileDef, ObjectHelper<IfcCircleHollowProfileDef,1> { IfcCircleHollowProfileDef() : Object("IfcCircleHollowProfileDef") {}
+ IfcPositiveLengthMeasure::Out WallThickness;
};
- // C++ wrapper for IfcSpatialStructureElementType
- struct IfcSpatialStructureElementType : IfcElementType, ObjectHelper<IfcSpatialStructureElementType,0> { IfcSpatialStructureElementType() : Object("IfcSpatialStructureElementType") {}
+ // C++ wrapper for IfcTopologicalRepresentationItem
+ struct IfcTopologicalRepresentationItem : IfcRepresentationItem, ObjectHelper<IfcTopologicalRepresentationItem,0> { IfcTopologicalRepresentationItem() : Object("IfcTopologicalRepresentationItem") {}
};
- // C++ wrapper for IfcSpaceType
- struct IfcSpaceType : IfcSpatialStructureElementType, ObjectHelper<IfcSpaceType,1> { IfcSpaceType() : Object("IfcSpaceType") {}
- IfcSpaceTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcConnectedFaceSet
+ struct IfcConnectedFaceSet : IfcTopologicalRepresentationItem, ObjectHelper<IfcConnectedFaceSet,1> { IfcConnectedFaceSet() : Object("IfcConnectedFaceSet") {}
+ ListOf< Lazy< IfcFace >, 1, 0 > CfsFaces;
};
- // C++ wrapper for IfcColumnType
- struct IfcColumnType : IfcBuildingElementType, ObjectHelper<IfcColumnType,1> { IfcColumnType() : Object("IfcColumnType") {}
- IfcColumnTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcClosedShell
+ struct IfcClosedShell : IfcConnectedFaceSet, ObjectHelper<IfcClosedShell,0> { IfcClosedShell() : Object("IfcClosedShell") {}
- // C++ wrapper for IfcCraneRailAShapeProfileDef
- struct IfcCraneRailAShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCraneRailAShapeProfileDef,12> { IfcCraneRailAShapeProfileDef() : Object("IfcCraneRailAShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out OverallHeight;
- IfcPositiveLengthMeasure::Out BaseWidth2;
- Maybe< IfcPositiveLengthMeasure::Out > Radius;
- IfcPositiveLengthMeasure::Out HeadWidth;
- IfcPositiveLengthMeasure::Out HeadDepth2;
- IfcPositiveLengthMeasure::Out HeadDepth3;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out BaseWidth4;
- IfcPositiveLengthMeasure::Out BaseDepth1;
- IfcPositiveLengthMeasure::Out BaseDepth2;
- IfcPositiveLengthMeasure::Out BaseDepth3;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcCondenserType
- struct IfcCondenserType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCondenserType,1> { IfcCondenserType() : Object("IfcCondenserType") {}
- IfcCondenserTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCoilType
+ struct IfcCoilType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCoilType,1> { IfcCoilType() : Object("IfcCoilType") {}
+ IfcCoilTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCircleProfileDef
- struct IfcCircleProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCircleProfileDef,1> { IfcCircleProfileDef() : Object("IfcCircleProfileDef") {}
- IfcPositiveLengthMeasure::Out Radius;
+ // C++ wrapper for IfcColourSpecification
+ struct IfcColourSpecification : ObjectHelper<IfcColourSpecification,1> { IfcColourSpecification() : Object("IfcColourSpecification") {}
+ Maybe< IfcLabel::Out > Name;
};
- // C++ wrapper for IfcCircleHollowProfileDef
- struct IfcCircleHollowProfileDef : IfcCircleProfileDef, ObjectHelper<IfcCircleHollowProfileDef,1> { IfcCircleHollowProfileDef() : Object("IfcCircleHollowProfileDef") {}
- IfcPositiveLengthMeasure::Out WallThickness;
+ // C++ wrapper for IfcColourRgb
+ struct IfcColourRgb : IfcColourSpecification, ObjectHelper<IfcColourRgb,3> { IfcColourRgb() : Object("IfcColourRgb") {}
+ IfcNormalisedRatioMeasure::Out Red;
+ IfcNormalisedRatioMeasure::Out Green;
+ IfcNormalisedRatioMeasure::Out Blue;
};
- // C++ wrapper for IfcPlacement
- struct IfcPlacement : IfcGeometricRepresentationItem, ObjectHelper<IfcPlacement,1> { IfcPlacement() : Object("IfcPlacement") {}
- Lazy< IfcCartesianPoint > Location;
- };
+ // C++ wrapper for IfcColumn
+ struct IfcColumn : IfcBuildingElement, ObjectHelper<IfcColumn,0> { IfcColumn() : Object("IfcColumn") {}
- // C++ wrapper for IfcAxis2Placement3D
- struct IfcAxis2Placement3D : IfcPlacement, ObjectHelper<IfcAxis2Placement3D,2> { IfcAxis2Placement3D() : Object("IfcAxis2Placement3D") {}
- Maybe< Lazy< IfcDirection > > Axis;
- Maybe< Lazy< IfcDirection > > RefDirection;
};
- // C++ wrapper for IfcPresentationStyle
- struct IfcPresentationStyle : ObjectHelper<IfcPresentationStyle,1> { IfcPresentationStyle() : Object("IfcPresentationStyle") {}
- Maybe< IfcLabel::Out > Name;
+ // C++ wrapper for IfcColumnType
+ struct IfcColumnType : IfcBuildingElementType, ObjectHelper<IfcColumnType,1> { IfcColumnType() : Object("IfcColumnType") {}
+ IfcColumnTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcEquipmentElement
- struct IfcEquipmentElement : IfcElement, ObjectHelper<IfcEquipmentElement,0> { IfcEquipmentElement() : Object("IfcEquipmentElement") {}
+ // C++ wrapper for IfcProperty
+ struct IfcProperty : ObjectHelper<IfcProperty,2> { IfcProperty() : Object("IfcProperty") {}
+ IfcIdentifier::Out Name;
+ Maybe< IfcText::Out > Description;
+ };
+ // C++ wrapper for IfcComplexProperty
+ struct IfcComplexProperty : IfcProperty, ObjectHelper<IfcComplexProperty,2> { IfcComplexProperty() : Object("IfcComplexProperty") {}
+ IfcIdentifier::Out UsageName;
+ ListOf< Lazy< IfcProperty >, 1, 0 > HasProperties;
};
// C++ wrapper for IfcCompositeCurveSegment
struct IfcCompositeCurveSegment : IfcGeometricRepresentationItem, ObjectHelper<IfcCompositeCurveSegment,3> { IfcCompositeCurveSegment() : Object("IfcCompositeCurveSegment") {}
- IfcTransitionCode::Out Transition;
- BOOLEAN::Out SameSense;
- Lazy< IfcCurve > ParentCurve;
- };
-
- // C++ wrapper for IfcRectangleProfileDef
- struct IfcRectangleProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcRectangleProfileDef,2> { IfcRectangleProfileDef() : Object("IfcRectangleProfileDef") {}
- IfcPositiveLengthMeasure::Out XDim;
- IfcPositiveLengthMeasure::Out YDim;
+ IfcTransitionCode::Out Transition;
+ BOOLEAN::Out SameSense;
+ Lazy< IfcCurve > ParentCurve;
};
- // C++ wrapper for IfcBuildingElementProxy
- struct IfcBuildingElementProxy : IfcBuildingElement, ObjectHelper<IfcBuildingElementProxy,1> { IfcBuildingElementProxy() : Object("IfcBuildingElementProxy") {}
- Maybe< IfcElementCompositionEnum::Out > CompositionType;
+ // C++ wrapper for IfcCompositeProfileDef
+ struct IfcCompositeProfileDef : IfcProfileDef, ObjectHelper<IfcCompositeProfileDef,2> { IfcCompositeProfileDef() : Object("IfcCompositeProfileDef") {}
+ ListOf< Lazy< IfcProfileDef >, 2, 0 > Profiles;
+ Maybe< IfcLabel::Out > Label;
};
- // C++ wrapper for IfcDistributionControlElementType
- struct IfcDistributionControlElementType : IfcDistributionElementType, ObjectHelper<IfcDistributionControlElementType,0> { IfcDistributionControlElementType() : Object("IfcDistributionControlElementType") {}
+ // C++ wrapper for IfcFlowMovingDeviceType
+ struct IfcFlowMovingDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowMovingDeviceType,0> { IfcFlowMovingDeviceType() : Object("IfcFlowMovingDeviceType") {}
};
- // C++ wrapper for IfcFlowInstrumentType
- struct IfcFlowInstrumentType : IfcDistributionControlElementType, ObjectHelper<IfcFlowInstrumentType,1> { IfcFlowInstrumentType() : Object("IfcFlowInstrumentType") {}
- IfcFlowInstrumentTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCompressorType
+ struct IfcCompressorType : IfcFlowMovingDeviceType, ObjectHelper<IfcCompressorType,1> { IfcCompressorType() : Object("IfcCompressorType") {}
+ IfcCompressorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcDraughtingCallout
- struct IfcDraughtingCallout : IfcGeometricRepresentationItem, ObjectHelper<IfcDraughtingCallout,1> { IfcDraughtingCallout() : Object("IfcDraughtingCallout") {}
- ListOf< IfcDraughtingCalloutElement, 1, 0 >::Out Contents;
+ // C++ wrapper for IfcCondenserType
+ struct IfcCondenserType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCondenserType,1> { IfcCondenserType() : Object("IfcCondenserType") {}
+ IfcCondenserTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcDimensionCurveDirectedCallout
- struct IfcDimensionCurveDirectedCallout : IfcDraughtingCallout, ObjectHelper<IfcDimensionCurveDirectedCallout,0> { IfcDimensionCurveDirectedCallout() : Object("IfcDimensionCurveDirectedCallout") {}
+ // C++ wrapper for IfcCondition
+ struct IfcCondition : IfcGroup, ObjectHelper<IfcCondition,0> { IfcCondition() : Object("IfcCondition") {}
};
- // C++ wrapper for IfcLinearDimension
- struct IfcLinearDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcLinearDimension,0> { IfcLinearDimension() : Object("IfcLinearDimension") {}
-
+ // C++ wrapper for IfcConditionCriterion
+ struct IfcConditionCriterion : IfcControl, ObjectHelper<IfcConditionCriterion,2> { IfcConditionCriterion() : Object("IfcConditionCriterion") {}
+ IfcConditionCriterionSelect::Out Criterion;
+ IfcDateTimeSelect::Out CriterionDateTime;
};
- // C++ wrapper for IfcElementAssembly
- struct IfcElementAssembly : IfcElement, ObjectHelper<IfcElementAssembly,2> { IfcElementAssembly() : Object("IfcElementAssembly") {}
- Maybe< IfcAssemblyPlaceEnum::Out > AssemblyPlace;
- IfcElementAssemblyTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcResource
+ struct IfcResource : IfcObject, ObjectHelper<IfcResource,0> { IfcResource() : Object("IfcResource") {}
- // C++ wrapper for IfcCsgPrimitive3D
- struct IfcCsgPrimitive3D : IfcGeometricRepresentationItem, ObjectHelper<IfcCsgPrimitive3D,1> { IfcCsgPrimitive3D() : Object("IfcCsgPrimitive3D") {}
- Lazy< IfcAxis2Placement3D > Position;
};
- // C++ wrapper for IfcRightCircularCone
- struct IfcRightCircularCone : IfcCsgPrimitive3D, ObjectHelper<IfcRightCircularCone,2> { IfcRightCircularCone() : Object("IfcRightCircularCone") {}
- IfcPositiveLengthMeasure::Out Height;
- IfcPositiveLengthMeasure::Out BottomRadius;
+ // C++ wrapper for IfcConstructionResource
+ struct IfcConstructionResource : IfcResource, ObjectHelper<IfcConstructionResource,4> { IfcConstructionResource() : Object("IfcConstructionResource") {}
+ Maybe< IfcIdentifier::Out > ResourceIdentifier;
+ Maybe< IfcLabel::Out > ResourceGroup;
+ Maybe< IfcResourceConsumptionEnum::Out > ResourceConsumption;
+ Maybe< Lazy< IfcMeasureWithUnit > > BaseQuantity;
};
- // C++ wrapper for IfcProjectOrder
- struct IfcProjectOrder : IfcControl, ObjectHelper<IfcProjectOrder,3> { IfcProjectOrder() : Object("IfcProjectOrder") {}
- IfcIdentifier::Out ID;
- IfcProjectOrderTypeEnum::Out PredefinedType;
- Maybe< IfcLabel::Out > Status;
+ // C++ wrapper for IfcConstructionEquipmentResource
+ struct IfcConstructionEquipmentResource : IfcConstructionResource, ObjectHelper<IfcConstructionEquipmentResource,0> { IfcConstructionEquipmentResource() : Object("IfcConstructionEquipmentResource") {}
+
};
- // C++ wrapper for IfcLShapeProfileDef
- struct IfcLShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcLShapeProfileDef,8> { IfcLShapeProfileDef() : Object("IfcLShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out Depth;
- Maybe< IfcPositiveLengthMeasure::Out > Width;
- IfcPositiveLengthMeasure::Out Thickness;
- Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
- Maybe< IfcPlaneAngleMeasure::Out > LegSlope;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
+ // C++ wrapper for IfcConstructionMaterialResource
+ struct IfcConstructionMaterialResource : IfcConstructionResource, ObjectHelper<IfcConstructionMaterialResource,2> { IfcConstructionMaterialResource() : Object("IfcConstructionMaterialResource") {}
+ Maybe< ListOf< IfcActorSelect, 1, 0 >::Out > Suppliers;
+ Maybe< IfcRatioMeasure::Out > UsageRatio;
};
- // C++ wrapper for IfcAngularDimension
- struct IfcAngularDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcAngularDimension,0> { IfcAngularDimension() : Object("IfcAngularDimension") {}
+ // C++ wrapper for IfcConstructionProductResource
+ struct IfcConstructionProductResource : IfcConstructionResource, ObjectHelper<IfcConstructionProductResource,0> { IfcConstructionProductResource() : Object("IfcConstructionProductResource") {}
};
- // C++ wrapper for IfcLocalPlacement
- struct IfcLocalPlacement : IfcObjectPlacement, ObjectHelper<IfcLocalPlacement,2> { IfcLocalPlacement() : Object("IfcLocalPlacement") {}
- Maybe< Lazy< IfcObjectPlacement > > PlacementRelTo;
- IfcAxis2Placement::Out RelativePlacement;
+ // C++ wrapper for IfcNamedUnit
+ struct IfcNamedUnit : ObjectHelper<IfcNamedUnit,2> { IfcNamedUnit() : Object("IfcNamedUnit") {}
+ Lazy< NotImplemented > Dimensions;
+ IfcUnitEnum::Out UnitType;
};
- // C++ wrapper for IfcSweptAreaSolid
- struct IfcSweptAreaSolid : IfcSolidModel, ObjectHelper<IfcSweptAreaSolid,2> { IfcSweptAreaSolid() : Object("IfcSweptAreaSolid") {}
- Lazy< IfcProfileDef > SweptArea;
- Lazy< IfcAxis2Placement3D > Position;
+ // C++ wrapper for IfcContextDependentUnit
+ struct IfcContextDependentUnit : IfcNamedUnit, ObjectHelper<IfcContextDependentUnit,1> { IfcContextDependentUnit() : Object("IfcContextDependentUnit") {}
+ IfcLabel::Out Name;
};
- // C++ wrapper for IfcRevolvedAreaSolid
- struct IfcRevolvedAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcRevolvedAreaSolid,2> { IfcRevolvedAreaSolid() : Object("IfcRevolvedAreaSolid") {}
- Lazy< IfcAxis1Placement > Axis;
- IfcPlaneAngleMeasure::Out Angle;
+ // C++ wrapper for IfcControllerType
+ struct IfcControllerType : IfcDistributionControlElementType, ObjectHelper<IfcControllerType,1> { IfcControllerType() : Object("IfcControllerType") {}
+ IfcControllerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralSurfaceConnection
- struct IfcStructuralSurfaceConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralSurfaceConnection,0> { IfcStructuralSurfaceConnection() : Object("IfcStructuralSurfaceConnection") {}
-
+ // C++ wrapper for IfcConversionBasedUnit
+ struct IfcConversionBasedUnit : IfcNamedUnit, ObjectHelper<IfcConversionBasedUnit,2> { IfcConversionBasedUnit() : Object("IfcConversionBasedUnit") {}
+ IfcLabel::Out Name;
+ Lazy< IfcMeasureWithUnit > ConversionFactor;
};
- // C++ wrapper for IfcRadiusDimension
- struct IfcRadiusDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcRadiusDimension,0> { IfcRadiusDimension() : Object("IfcRadiusDimension") {}
-
+ // C++ wrapper for IfcCooledBeamType
+ struct IfcCooledBeamType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCooledBeamType,1> { IfcCooledBeamType() : Object("IfcCooledBeamType") {}
+ IfcCooledBeamTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSweptDiskSolid
- struct IfcSweptDiskSolid : IfcSolidModel, ObjectHelper<IfcSweptDiskSolid,5> { IfcSweptDiskSolid() : Object("IfcSweptDiskSolid") {}
- Lazy< IfcCurve > Directrix;
- IfcPositiveLengthMeasure::Out Radius;
- Maybe< IfcPositiveLengthMeasure::Out > InnerRadius;
- IfcParameterValue::Out StartParam;
- IfcParameterValue::Out EndParam;
+ // C++ wrapper for IfcCoolingTowerType
+ struct IfcCoolingTowerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCoolingTowerType,1> { IfcCoolingTowerType() : Object("IfcCoolingTowerType") {}
+ IfcCoolingTowerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcHalfSpaceSolid
- struct IfcHalfSpaceSolid : IfcGeometricRepresentationItem, ObjectHelper<IfcHalfSpaceSolid,2> { IfcHalfSpaceSolid() : Object("IfcHalfSpaceSolid") {}
- Lazy< IfcSurface > BaseSurface;
- BOOLEAN::Out AgreementFlag;
- };
+ // C++ wrapper for IfcCostItem
+ struct IfcCostItem : IfcControl, ObjectHelper<IfcCostItem,0> { IfcCostItem() : Object("IfcCostItem") {}
- // C++ wrapper for IfcPolygonalBoundedHalfSpace
- struct IfcPolygonalBoundedHalfSpace : IfcHalfSpaceSolid, ObjectHelper<IfcPolygonalBoundedHalfSpace,2> { IfcPolygonalBoundedHalfSpace() : Object("IfcPolygonalBoundedHalfSpace") {}
- Lazy< IfcAxis2Placement3D > Position;
- Lazy< IfcBoundedCurve > PolygonalBoundary;
};
- // C++ wrapper for IfcTimeSeriesSchedule
- struct IfcTimeSeriesSchedule : IfcControl, ObjectHelper<IfcTimeSeriesSchedule,3> { IfcTimeSeriesSchedule() : Object("IfcTimeSeriesSchedule") {}
- Maybe< ListOf< IfcDateTimeSelect, 1, 0 >::Out > ApplicableDates;
- IfcTimeSeriesScheduleTypeEnum::Out TimeSeriesScheduleType;
- Lazy< NotImplemented > TimeSeries;
+ // C++ wrapper for IfcCostSchedule
+ struct IfcCostSchedule : IfcControl, ObjectHelper<IfcCostSchedule,8> { IfcCostSchedule() : Object("IfcCostSchedule") {}
+ Maybe< IfcActorSelect::Out > SubmittedBy;
+ Maybe< IfcActorSelect::Out > PreparedBy;
+ Maybe< IfcDateTimeSelect::Out > SubmittedOn;
+ Maybe< IfcLabel::Out > Status;
+ Maybe< ListOf< IfcActorSelect, 1, 0 >::Out > TargetUsers;
+ Maybe< IfcDateTimeSelect::Out > UpdateDate;
+ IfcIdentifier::Out ID;
+ IfcCostScheduleTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCooledBeamType
- struct IfcCooledBeamType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCooledBeamType,1> { IfcCooledBeamType() : Object("IfcCooledBeamType") {}
- IfcCooledBeamTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCovering
+ struct IfcCovering : IfcBuildingElement, ObjectHelper<IfcCovering,1> { IfcCovering() : Object("IfcCovering") {}
+ Maybe< IfcCoveringTypeEnum::Out > PredefinedType;
};
- // C++ wrapper for IfcProject
- struct IfcProject : IfcObject, ObjectHelper<IfcProject,4> { IfcProject() : Object("IfcProject") {}
- Maybe< IfcLabel::Out > LongName;
- Maybe< IfcLabel::Out > Phase;
- ListOf< Lazy< IfcRepresentationContext >, 1, 0 > RepresentationContexts;
- Lazy< IfcUnitAssignment > UnitsInContext;
+ // C++ wrapper for IfcCoveringType
+ struct IfcCoveringType : IfcBuildingElementType, ObjectHelper<IfcCoveringType,1> { IfcCoveringType() : Object("IfcCoveringType") {}
+ IfcCoveringTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcEvaporatorType
- struct IfcEvaporatorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcEvaporatorType,1> { IfcEvaporatorType() : Object("IfcEvaporatorType") {}
- IfcEvaporatorTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCraneRailAShapeProfileDef
+ struct IfcCraneRailAShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCraneRailAShapeProfileDef,12> { IfcCraneRailAShapeProfileDef() : Object("IfcCraneRailAShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out OverallHeight;
+ IfcPositiveLengthMeasure::Out BaseWidth2;
+ Maybe< IfcPositiveLengthMeasure::Out > Radius;
+ IfcPositiveLengthMeasure::Out HeadWidth;
+ IfcPositiveLengthMeasure::Out HeadDepth2;
+ IfcPositiveLengthMeasure::Out HeadDepth3;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out BaseWidth4;
+ IfcPositiveLengthMeasure::Out BaseDepth1;
+ IfcPositiveLengthMeasure::Out BaseDepth2;
+ IfcPositiveLengthMeasure::Out BaseDepth3;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcLaborResource
- struct IfcLaborResource : IfcConstructionResource, ObjectHelper<IfcLaborResource,1> { IfcLaborResource() : Object("IfcLaborResource") {}
- Maybe< IfcText::Out > SkillSet;
+ // C++ wrapper for IfcCraneRailFShapeProfileDef
+ struct IfcCraneRailFShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCraneRailFShapeProfileDef,9> { IfcCraneRailFShapeProfileDef() : Object("IfcCraneRailFShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out OverallHeight;
+ IfcPositiveLengthMeasure::Out HeadWidth;
+ Maybe< IfcPositiveLengthMeasure::Out > Radius;
+ IfcPositiveLengthMeasure::Out HeadDepth2;
+ IfcPositiveLengthMeasure::Out HeadDepth3;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out BaseDepth1;
+ IfcPositiveLengthMeasure::Out BaseDepth2;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcPropertyBoundedValue
- struct IfcPropertyBoundedValue : IfcSimpleProperty, ObjectHelper<IfcPropertyBoundedValue,3> { IfcPropertyBoundedValue() : Object("IfcPropertyBoundedValue") {}
- Maybe< IfcValue::Out > UpperBoundValue;
- Maybe< IfcValue::Out > LowerBoundValue;
- Maybe< IfcUnit::Out > Unit;
- };
+ // C++ wrapper for IfcCrewResource
+ struct IfcCrewResource : IfcConstructionResource, ObjectHelper<IfcCrewResource,0> { IfcCrewResource() : Object("IfcCrewResource") {}
- // C++ wrapper for IfcRampFlightType
- struct IfcRampFlightType : IfcBuildingElementType, ObjectHelper<IfcRampFlightType,1> { IfcRampFlightType() : Object("IfcRampFlightType") {}
- IfcRampFlightTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcMember
- struct IfcMember : IfcBuildingElement, ObjectHelper<IfcMember,0> { IfcMember() : Object("IfcMember") {}
+ // C++ wrapper for IfcSolidModel
+ struct IfcSolidModel : IfcGeometricRepresentationItem, ObjectHelper<IfcSolidModel,0> { IfcSolidModel() : Object("IfcSolidModel") {}
};
- // C++ wrapper for IfcTubeBundleType
- struct IfcTubeBundleType : IfcEnergyConversionDeviceType, ObjectHelper<IfcTubeBundleType,1> { IfcTubeBundleType() : Object("IfcTubeBundleType") {}
- IfcTubeBundleTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcCsgSolid
+ struct IfcCsgSolid : IfcSolidModel, ObjectHelper<IfcCsgSolid,1> { IfcCsgSolid() : Object("IfcCsgSolid") {}
+ IfcCsgSelect::Out TreeRootExpression;
};
- // C++ wrapper for IfcValveType
- struct IfcValveType : IfcFlowControllerType, ObjectHelper<IfcValveType,1> { IfcValveType() : Object("IfcValveType") {}
- IfcValveTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcCurtainWall
+ struct IfcCurtainWall : IfcBuildingElement, ObjectHelper<IfcCurtainWall,0> { IfcCurtainWall() : Object("IfcCurtainWall") {}
- // C++ wrapper for IfcTrimmedCurve
- struct IfcTrimmedCurve : IfcBoundedCurve, ObjectHelper<IfcTrimmedCurve,5> { IfcTrimmedCurve() : Object("IfcTrimmedCurve") {}
- Lazy< IfcCurve > BasisCurve;
- ListOf< IfcTrimmingSelect, 1, 2 >::Out Trim1;
- ListOf< IfcTrimmingSelect, 1, 2 >::Out Trim2;
- BOOLEAN::Out SenseAgreement;
- IfcTrimmingPreference::Out MasterRepresentation;
};
- // C++ wrapper for IfcRelDefines
- struct IfcRelDefines : IfcRelationship, ObjectHelper<IfcRelDefines,1> { IfcRelDefines() : Object("IfcRelDefines") {}
- ListOf< Lazy< IfcObject >, 1, 0 > RelatedObjects;
+ // C++ wrapper for IfcCurtainWallType
+ struct IfcCurtainWallType : IfcBuildingElementType, ObjectHelper<IfcCurtainWallType,1> { IfcCurtainWallType() : Object("IfcCurtainWallType") {}
+ IfcCurtainWallTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcRelDefinesByProperties
- struct IfcRelDefinesByProperties : IfcRelDefines, ObjectHelper<IfcRelDefinesByProperties,1> { IfcRelDefinesByProperties() : Object("IfcRelDefinesByProperties") {}
- Lazy< IfcPropertySetDefinition > RelatingPropertyDefinition;
+ // C++ wrapper for IfcCurveBoundedPlane
+ struct IfcCurveBoundedPlane : IfcBoundedSurface, ObjectHelper<IfcCurveBoundedPlane,3> { IfcCurveBoundedPlane() : Object("IfcCurveBoundedPlane") {}
+ Lazy< IfcPlane > BasisSurface;
+ Lazy< IfcCurve > OuterBoundary;
+ ListOf< Lazy< IfcCurve >, 0, 0 > InnerBoundaries;
};
- // C++ wrapper for IfcActor
- struct IfcActor : IfcObject, ObjectHelper<IfcActor,1> { IfcActor() : Object("IfcActor") {}
- IfcActorSelect::Out TheActor;
+ // C++ wrapper for IfcPresentationStyle
+ struct IfcPresentationStyle : ObjectHelper<IfcPresentationStyle,1> { IfcPresentationStyle() : Object("IfcPresentationStyle") {}
+ Maybe< IfcLabel::Out > Name;
};
- // C++ wrapper for IfcOccupant
- struct IfcOccupant : IfcActor, ObjectHelper<IfcOccupant,1> { IfcOccupant() : Object("IfcOccupant") {}
- IfcOccupantTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDamperType
+ struct IfcDamperType : IfcFlowControllerType, ObjectHelper<IfcDamperType,1> { IfcDamperType() : Object("IfcDamperType") {}
+ IfcDamperTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcHumidifierType
- struct IfcHumidifierType : IfcEnergyConversionDeviceType, ObjectHelper<IfcHumidifierType,1> { IfcHumidifierType() : Object("IfcHumidifierType") {}
- IfcHumidifierTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDefinedSymbol
+ struct IfcDefinedSymbol : IfcGeometricRepresentationItem, ObjectHelper<IfcDefinedSymbol,2> { IfcDefinedSymbol() : Object("IfcDefinedSymbol") {}
+ IfcDefinedSymbolSelect::Out Definition;
+ Lazy< IfcCartesianTransformationOperator2D > Target;
};
- // C++ wrapper for IfcArbitraryOpenProfileDef
- struct IfcArbitraryOpenProfileDef : IfcProfileDef, ObjectHelper<IfcArbitraryOpenProfileDef,1> { IfcArbitraryOpenProfileDef() : Object("IfcArbitraryOpenProfileDef") {}
- Lazy< IfcBoundedCurve > Curve;
+ // C++ wrapper for IfcDerivedProfileDef
+ struct IfcDerivedProfileDef : IfcProfileDef, ObjectHelper<IfcDerivedProfileDef,3> { IfcDerivedProfileDef() : Object("IfcDerivedProfileDef") {}
+ Lazy< IfcProfileDef > ParentProfile;
+ Lazy< IfcCartesianTransformationOperator2D > Operator;
+ Maybe< IfcLabel::Out > Label;
};
- // C++ wrapper for IfcPermit
- struct IfcPermit : IfcControl, ObjectHelper<IfcPermit,1> { IfcPermit() : Object("IfcPermit") {}
- IfcIdentifier::Out PermitID;
+ // C++ wrapper for IfcDiameterDimension
+ struct IfcDiameterDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcDiameterDimension,0> { IfcDiameterDimension() : Object("IfcDiameterDimension") {}
+
};
- // C++ wrapper for IfcOffsetCurve3D
- struct IfcOffsetCurve3D : IfcCurve, ObjectHelper<IfcOffsetCurve3D,4> { IfcOffsetCurve3D() : Object("IfcOffsetCurve3D") {}
- Lazy< IfcCurve > BasisCurve;
- IfcLengthMeasure::Out Distance;
- LOGICAL::Out SelfIntersect;
- Lazy< IfcDirection > RefDirection;
+ // C++ wrapper for IfcDimensionCurve
+ struct IfcDimensionCurve : IfcAnnotationCurveOccurrence, ObjectHelper<IfcDimensionCurve,0> { IfcDimensionCurve() : Object("IfcDimensionCurve") {}
+
};
- // C++ wrapper for IfcLightSource
- struct IfcLightSource : IfcGeometricRepresentationItem, ObjectHelper<IfcLightSource,4> { IfcLightSource() : Object("IfcLightSource") {}
- Maybe< IfcLabel::Out > Name;
- Lazy< IfcColourRgb > LightColour;
- Maybe< IfcNormalisedRatioMeasure::Out > AmbientIntensity;
- Maybe< IfcNormalisedRatioMeasure::Out > Intensity;
+ // C++ wrapper for IfcTerminatorSymbol
+ struct IfcTerminatorSymbol : IfcAnnotationSymbolOccurrence, ObjectHelper<IfcTerminatorSymbol,1> { IfcTerminatorSymbol() : Object("IfcTerminatorSymbol") {}
+ Lazy< IfcAnnotationCurveOccurrence > AnnotatedCurve;
};
- // C++ wrapper for IfcLightSourcePositional
- struct IfcLightSourcePositional : IfcLightSource, ObjectHelper<IfcLightSourcePositional,5> { IfcLightSourcePositional() : Object("IfcLightSourcePositional") {}
- Lazy< IfcCartesianPoint > Position;
- IfcPositiveLengthMeasure::Out Radius;
- IfcReal::Out ConstantAttenuation;
- IfcReal::Out DistanceAttenuation;
- IfcReal::Out QuadricAttenuation;
+ // C++ wrapper for IfcDimensionCurveTerminator
+ struct IfcDimensionCurveTerminator : IfcTerminatorSymbol, ObjectHelper<IfcDimensionCurveTerminator,1> { IfcDimensionCurveTerminator() : Object("IfcDimensionCurveTerminator") {}
+ IfcDimensionExtentUsage::Out Role;
};
- // C++ wrapper for IfcCompositeProfileDef
- struct IfcCompositeProfileDef : IfcProfileDef, ObjectHelper<IfcCompositeProfileDef,2> { IfcCompositeProfileDef() : Object("IfcCompositeProfileDef") {}
- ListOf< Lazy< IfcProfileDef >, 2, 0 > Profiles;
- Maybe< IfcLabel::Out > Label;
+ // C++ wrapper for IfcDirection
+ struct IfcDirection : IfcGeometricRepresentationItem, ObjectHelper<IfcDirection,1> { IfcDirection() : Object("IfcDirection") {}
+ ListOf< REAL, 2, 3 >::Out DirectionRatios;
};
- // C++ wrapper for IfcRamp
- struct IfcRamp : IfcBuildingElement, ObjectHelper<IfcRamp,1> { IfcRamp() : Object("IfcRamp") {}
- IfcRampTypeEnum::Out ShapeType;
+ // C++ wrapper for IfcElementComponent
+ struct IfcElementComponent : IfcElement, ObjectHelper<IfcElementComponent,0> { IfcElementComponent() : Object("IfcElementComponent") {}
+
};
- // C++ wrapper for IfcFlowMovingDevice
- struct IfcFlowMovingDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowMovingDevice,0> { IfcFlowMovingDevice() : Object("IfcFlowMovingDevice") {}
+ // C++ wrapper for IfcDiscreteAccessory
+ struct IfcDiscreteAccessory : IfcElementComponent, ObjectHelper<IfcDiscreteAccessory,0> { IfcDiscreteAccessory() : Object("IfcDiscreteAccessory") {}
};
- // C++ wrapper for IfcSpaceHeaterType
- struct IfcSpaceHeaterType : IfcEnergyConversionDeviceType, ObjectHelper<IfcSpaceHeaterType,1> { IfcSpaceHeaterType() : Object("IfcSpaceHeaterType") {}
- IfcSpaceHeaterTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcElementComponentType
+ struct IfcElementComponentType : IfcElementType, ObjectHelper<IfcElementComponentType,0> { IfcElementComponentType() : Object("IfcElementComponentType") {}
+
};
- // C++ wrapper for IfcLampType
- struct IfcLampType : IfcFlowTerminalType, ObjectHelper<IfcLampType,1> { IfcLampType() : Object("IfcLampType") {}
- IfcLampTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDiscreteAccessoryType
+ struct IfcDiscreteAccessoryType : IfcElementComponentType, ObjectHelper<IfcDiscreteAccessoryType,0> { IfcDiscreteAccessoryType() : Object("IfcDiscreteAccessoryType") {}
+
};
- // C++ wrapper for IfcBuildingElementComponent
- struct IfcBuildingElementComponent : IfcBuildingElement, ObjectHelper<IfcBuildingElementComponent,0> { IfcBuildingElementComponent() : Object("IfcBuildingElementComponent") {}
+ // C++ wrapper for IfcDistributionElement
+ struct IfcDistributionElement : IfcElement, ObjectHelper<IfcDistributionElement,0> { IfcDistributionElement() : Object("IfcDistributionElement") {}
};
- // C++ wrapper for IfcReinforcingElement
- struct IfcReinforcingElement : IfcBuildingElementComponent, ObjectHelper<IfcReinforcingElement,1> { IfcReinforcingElement() : Object("IfcReinforcingElement") {}
- Maybe< IfcLabel::Out > SteelGrade;
+ // C++ wrapper for IfcDistributionFlowElement
+ struct IfcDistributionFlowElement : IfcDistributionElement, ObjectHelper<IfcDistributionFlowElement,0> { IfcDistributionFlowElement() : Object("IfcDistributionFlowElement") {}
+
};
- // C++ wrapper for IfcReinforcingBar
- struct IfcReinforcingBar : IfcReinforcingElement, ObjectHelper<IfcReinforcingBar,5> { IfcReinforcingBar() : Object("IfcReinforcingBar") {}
- IfcPositiveLengthMeasure::Out NominalDiameter;
- IfcAreaMeasure::Out CrossSectionArea;
- Maybe< IfcPositiveLengthMeasure::Out > BarLength;
- IfcReinforcingBarRoleEnum::Out BarRole;
- Maybe< IfcReinforcingBarSurfaceEnum::Out > BarSurface;
+ // C++ wrapper for IfcDistributionChamberElement
+ struct IfcDistributionChamberElement : IfcDistributionFlowElement, ObjectHelper<IfcDistributionChamberElement,0> { IfcDistributionChamberElement() : Object("IfcDistributionChamberElement") {}
+
};
- // C++ wrapper for IfcElectricHeaterType
- struct IfcElectricHeaterType : IfcFlowTerminalType, ObjectHelper<IfcElectricHeaterType,1> { IfcElectricHeaterType() : Object("IfcElectricHeaterType") {}
- IfcElectricHeaterTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDistributionChamberElementType
+ struct IfcDistributionChamberElementType : IfcDistributionFlowElementType, ObjectHelper<IfcDistributionChamberElementType,1> { IfcDistributionChamberElementType() : Object("IfcDistributionChamberElementType") {}
+ IfcDistributionChamberElementTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcTShapeProfileDef
- struct IfcTShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcTShapeProfileDef,10> { IfcTShapeProfileDef() : Object("IfcTShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out Depth;
- IfcPositiveLengthMeasure::Out FlangeWidth;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out FlangeThickness;
- Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > FlangeEdgeRadius;
- Maybe< IfcPositiveLengthMeasure::Out > WebEdgeRadius;
- Maybe< IfcPlaneAngleMeasure::Out > WebSlope;
- Maybe< IfcPlaneAngleMeasure::Out > FlangeSlope;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
+ // C++ wrapper for IfcDistributionControlElement
+ struct IfcDistributionControlElement : IfcDistributionElement, ObjectHelper<IfcDistributionControlElement,1> { IfcDistributionControlElement() : Object("IfcDistributionControlElement") {}
+ Maybe< IfcIdentifier::Out > ControlElementId;
};
- // C++ wrapper for IfcStructuralActivity
- struct IfcStructuralActivity : IfcProduct, ObjectHelper<IfcStructuralActivity,2> { IfcStructuralActivity() : Object("IfcStructuralActivity") {}
- Lazy< NotImplemented > AppliedLoad;
- IfcGlobalOrLocalEnum::Out GlobalOrLocal;
+ // C++ wrapper for IfcPort
+ struct IfcPort : IfcProduct, ObjectHelper<IfcPort,0> { IfcPort() : Object("IfcPort") {}
+
};
- // C++ wrapper for IfcStructuralAction
- struct IfcStructuralAction : IfcStructuralActivity, ObjectHelper<IfcStructuralAction,2> { IfcStructuralAction() : Object("IfcStructuralAction") {}
- BOOLEAN::Out DestabilizingLoad;
- Maybe< Lazy< IfcStructuralReaction > > CausedBy;
+ // C++ wrapper for IfcDistributionPort
+ struct IfcDistributionPort : IfcPort, ObjectHelper<IfcDistributionPort,1> { IfcDistributionPort() : Object("IfcDistributionPort") {}
+ Maybe< IfcFlowDirectionEnum::Out > FlowDirection;
};
- // C++ wrapper for IfcDuctFittingType
- struct IfcDuctFittingType : IfcFlowFittingType, ObjectHelper<IfcDuctFittingType,1> { IfcDuctFittingType() : Object("IfcDuctFittingType") {}
- IfcDuctFittingTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDoor
+ struct IfcDoor : IfcBuildingElement, ObjectHelper<IfcDoor,2> { IfcDoor() : Object("IfcDoor") {}
+ Maybe< IfcPositiveLengthMeasure::Out > OverallHeight;
+ Maybe< IfcPositiveLengthMeasure::Out > OverallWidth;
};
- // C++ wrapper for IfcCartesianTransformationOperator2D
- struct IfcCartesianTransformationOperator2D : IfcCartesianTransformationOperator, ObjectHelper<IfcCartesianTransformationOperator2D,0> { IfcCartesianTransformationOperator2D() : Object("IfcCartesianTransformationOperator2D") {}
+ // C++ wrapper for IfcPropertyDefinition
+ struct IfcPropertyDefinition : IfcRoot, ObjectHelper<IfcPropertyDefinition,0> { IfcPropertyDefinition() : Object("IfcPropertyDefinition") {}
};
- // C++ wrapper for IfcCartesianTransformationOperator2DnonUniform
- struct IfcCartesianTransformationOperator2DnonUniform : IfcCartesianTransformationOperator2D, ObjectHelper<IfcCartesianTransformationOperator2DnonUniform,1> { IfcCartesianTransformationOperator2DnonUniform() : Object("IfcCartesianTransformationOperator2DnonUniform") {}
- Maybe< REAL::Out > Scale2;
- };
+ // C++ wrapper for IfcPropertySetDefinition
+ struct IfcPropertySetDefinition : IfcPropertyDefinition, ObjectHelper<IfcPropertySetDefinition,0> { IfcPropertySetDefinition() : Object("IfcPropertySetDefinition") {}
- // C++ wrapper for IfcVirtualElement
- struct IfcVirtualElement : IfcElement, ObjectHelper<IfcVirtualElement,0> { IfcVirtualElement() : Object("IfcVirtualElement") {}
+ };
+ // C++ wrapper for IfcDoorStyle
+ struct IfcDoorStyle : IfcTypeProduct, ObjectHelper<IfcDoorStyle,4> { IfcDoorStyle() : Object("IfcDoorStyle") {}
+ IfcDoorStyleOperationEnum::Out OperationType;
+ IfcDoorStyleConstructionEnum::Out ConstructionType;
+ BOOLEAN::Out ParameterTakesPrecedence;
+ BOOLEAN::Out Sizeable;
};
- // C++ wrapper for IfcRightCircularCylinder
- struct IfcRightCircularCylinder : IfcCsgPrimitive3D, ObjectHelper<IfcRightCircularCylinder,2> { IfcRightCircularCylinder() : Object("IfcRightCircularCylinder") {}
- IfcPositiveLengthMeasure::Out Height;
- IfcPositiveLengthMeasure::Out Radius;
+ // C++ wrapper for IfcDuctFittingType
+ struct IfcDuctFittingType : IfcFlowFittingType, ObjectHelper<IfcDuctFittingType,1> { IfcDuctFittingType() : Object("IfcDuctFittingType") {}
+ IfcDuctFittingTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcOutletType
- struct IfcOutletType : IfcFlowTerminalType, ObjectHelper<IfcOutletType,1> { IfcOutletType() : Object("IfcOutletType") {}
- IfcOutletTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcDuctSegmentType
+ struct IfcDuctSegmentType : IfcFlowSegmentType, ObjectHelper<IfcDuctSegmentType,1> { IfcDuctSegmentType() : Object("IfcDuctSegmentType") {}
+ IfcDuctSegmentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcRelDecomposes
- struct IfcRelDecomposes : IfcRelationship, ObjectHelper<IfcRelDecomposes,2> { IfcRelDecomposes() : Object("IfcRelDecomposes") {}
- Lazy< IfcObjectDefinition > RelatingObject;
- ListOf< Lazy< IfcObjectDefinition >, 1, 0 > RelatedObjects;
+ // C++ wrapper for IfcFlowTreatmentDeviceType
+ struct IfcFlowTreatmentDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowTreatmentDeviceType,0> { IfcFlowTreatmentDeviceType() : Object("IfcFlowTreatmentDeviceType") {}
+
};
- // C++ wrapper for IfcCovering
- struct IfcCovering : IfcBuildingElement, ObjectHelper<IfcCovering,1> { IfcCovering() : Object("IfcCovering") {}
- Maybe< IfcCoveringTypeEnum::Out > PredefinedType;
+ // C++ wrapper for IfcDuctSilencerType
+ struct IfcDuctSilencerType : IfcFlowTreatmentDeviceType, ObjectHelper<IfcDuctSilencerType,1> { IfcDuctSilencerType() : Object("IfcDuctSilencerType") {}
+ IfcDuctSilencerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcPolyline
- struct IfcPolyline : IfcBoundedCurve, ObjectHelper<IfcPolyline,1> { IfcPolyline() : Object("IfcPolyline") {}
- ListOf< Lazy< IfcCartesianPoint >, 2, 0 > Points;
+ // C++ wrapper for IfcEdge
+ struct IfcEdge : IfcTopologicalRepresentationItem, ObjectHelper<IfcEdge,2> { IfcEdge() : Object("IfcEdge") {}
+ Lazy< IfcVertex > EdgeStart;
+ Lazy< IfcVertex > EdgeEnd;
};
- // C++ wrapper for IfcPath
- struct IfcPath : IfcTopologicalRepresentationItem, ObjectHelper<IfcPath,1> { IfcPath() : Object("IfcPath") {}
- ListOf< Lazy< IfcOrientedEdge >, 1, 0 > EdgeList;
+ // C++ wrapper for IfcEdgeCurve
+ struct IfcEdgeCurve : IfcEdge, ObjectHelper<IfcEdgeCurve,2> { IfcEdgeCurve() : Object("IfcEdgeCurve") {}
+ Lazy< IfcCurve > EdgeGeometry;
+ BOOLEAN::Out SameSense;
};
- // C++ wrapper for IfcElementComponent
- struct IfcElementComponent : IfcElement, ObjectHelper<IfcElementComponent,0> { IfcElementComponent() : Object("IfcElementComponent") {}
+ // C++ wrapper for IfcLoop
+ struct IfcLoop : IfcTopologicalRepresentationItem, ObjectHelper<IfcLoop,0> { IfcLoop() : Object("IfcLoop") {}
};
- // C++ wrapper for IfcFastener
- struct IfcFastener : IfcElementComponent, ObjectHelper<IfcFastener,0> { IfcFastener() : Object("IfcFastener") {}
+ // C++ wrapper for IfcEdgeLoop
+ struct IfcEdgeLoop : IfcLoop, ObjectHelper<IfcEdgeLoop,1> { IfcEdgeLoop() : Object("IfcEdgeLoop") {}
+ ListOf< Lazy< IfcOrientedEdge >, 1, 0 > EdgeList;
+ };
+ // C++ wrapper for IfcElectricApplianceType
+ struct IfcElectricApplianceType : IfcFlowTerminalType, ObjectHelper<IfcElectricApplianceType,1> { IfcElectricApplianceType() : Object("IfcElectricApplianceType") {}
+ IfcElectricApplianceTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcMappedItem
- struct IfcMappedItem : IfcRepresentationItem, ObjectHelper<IfcMappedItem,2> { IfcMappedItem() : Object("IfcMappedItem") {}
- Lazy< IfcRepresentationMap > MappingSource;
- Lazy< IfcCartesianTransformationOperator > MappingTarget;
+ // C++ wrapper for IfcFlowController
+ struct IfcFlowController : IfcDistributionFlowElement, ObjectHelper<IfcFlowController,0> { IfcFlowController() : Object("IfcFlowController") {}
+
};
- // C++ wrapper for IfcRectangularPyramid
- struct IfcRectangularPyramid : IfcCsgPrimitive3D, ObjectHelper<IfcRectangularPyramid,3> { IfcRectangularPyramid() : Object("IfcRectangularPyramid") {}
- IfcPositiveLengthMeasure::Out XLength;
- IfcPositiveLengthMeasure::Out YLength;
- IfcPositiveLengthMeasure::Out Height;
+ // C++ wrapper for IfcElectricDistributionPoint
+ struct IfcElectricDistributionPoint : IfcFlowController, ObjectHelper<IfcElectricDistributionPoint,2> { IfcElectricDistributionPoint() : Object("IfcElectricDistributionPoint") {}
+ IfcElectricDistributionPointFunctionEnum::Out DistributionPointFunction;
+ Maybe< IfcLabel::Out > UserDefinedFunction;
};
- // C++ wrapper for IfcCrewResource
- struct IfcCrewResource : IfcConstructionResource, ObjectHelper<IfcCrewResource,0> { IfcCrewResource() : Object("IfcCrewResource") {}
+ // C++ wrapper for IfcFlowStorageDeviceType
+ struct IfcFlowStorageDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowStorageDeviceType,0> { IfcFlowStorageDeviceType() : Object("IfcFlowStorageDeviceType") {}
};
- // C++ wrapper for IfcNamedUnit
- struct IfcNamedUnit : ObjectHelper<IfcNamedUnit,2> { IfcNamedUnit() : Object("IfcNamedUnit") {}
- Lazy< NotImplemented > Dimensions;
- IfcUnitEnum::Out UnitType;
+ // C++ wrapper for IfcElectricFlowStorageDeviceType
+ struct IfcElectricFlowStorageDeviceType : IfcFlowStorageDeviceType, ObjectHelper<IfcElectricFlowStorageDeviceType,1> { IfcElectricFlowStorageDeviceType() : Object("IfcElectricFlowStorageDeviceType") {}
+ IfcElectricFlowStorageDeviceTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcContextDependentUnit
- struct IfcContextDependentUnit : IfcNamedUnit, ObjectHelper<IfcContextDependentUnit,1> { IfcContextDependentUnit() : Object("IfcContextDependentUnit") {}
- IfcLabel::Out Name;
+ // C++ wrapper for IfcElectricGeneratorType
+ struct IfcElectricGeneratorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcElectricGeneratorType,1> { IfcElectricGeneratorType() : Object("IfcElectricGeneratorType") {}
+ IfcElectricGeneratorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcUnitaryEquipmentType
- struct IfcUnitaryEquipmentType : IfcEnergyConversionDeviceType, ObjectHelper<IfcUnitaryEquipmentType,1> { IfcUnitaryEquipmentType() : Object("IfcUnitaryEquipmentType") {}
- IfcUnitaryEquipmentTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcElectricHeaterType
+ struct IfcElectricHeaterType : IfcFlowTerminalType, ObjectHelper<IfcElectricHeaterType,1> { IfcElectricHeaterType() : Object("IfcElectricHeaterType") {}
+ IfcElectricHeaterTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcRoof
- struct IfcRoof : IfcBuildingElement, ObjectHelper<IfcRoof,1> { IfcRoof() : Object("IfcRoof") {}
- IfcRoofTypeEnum::Out ShapeType;
+ // C++ wrapper for IfcElectricMotorType
+ struct IfcElectricMotorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcElectricMotorType,1> { IfcElectricMotorType() : Object("IfcElectricMotorType") {}
+ IfcElectricMotorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralMember
- struct IfcStructuralMember : IfcStructuralItem, ObjectHelper<IfcStructuralMember,0> { IfcStructuralMember() : Object("IfcStructuralMember") {}
+ // C++ wrapper for IfcElectricTimeControlType
+ struct IfcElectricTimeControlType : IfcFlowControllerType, ObjectHelper<IfcElectricTimeControlType,1> { IfcElectricTimeControlType() : Object("IfcElectricTimeControlType") {}
+ IfcElectricTimeControlTypeEnum::Out PredefinedType;
+ };
+
+ // C++ wrapper for IfcSystem
+ struct IfcSystem : IfcGroup, ObjectHelper<IfcSystem,0> { IfcSystem() : Object("IfcSystem") {}
};
- // C++ wrapper for IfcStyleModel
- struct IfcStyleModel : IfcRepresentation, ObjectHelper<IfcStyleModel,0> { IfcStyleModel() : Object("IfcStyleModel") {}
+ // C++ wrapper for IfcElectricalCircuit
+ struct IfcElectricalCircuit : IfcSystem, ObjectHelper<IfcElectricalCircuit,0> { IfcElectricalCircuit() : Object("IfcElectricalCircuit") {}
};
- // C++ wrapper for IfcStyledRepresentation
- struct IfcStyledRepresentation : IfcStyleModel, ObjectHelper<IfcStyledRepresentation,0> { IfcStyledRepresentation() : Object("IfcStyledRepresentation") {}
+ // C++ wrapper for IfcElectricalElement
+ struct IfcElectricalElement : IfcElement, ObjectHelper<IfcElectricalElement,0> { IfcElectricalElement() : Object("IfcElectricalElement") {}
};
- // C++ wrapper for IfcSpatialStructureElement
- struct IfcSpatialStructureElement : IfcProduct, ObjectHelper<IfcSpatialStructureElement,2> { IfcSpatialStructureElement() : Object("IfcSpatialStructureElement") {}
- Maybe< IfcLabel::Out > LongName;
- IfcElementCompositionEnum::Out CompositionType;
+ // C++ wrapper for IfcElementAssembly
+ struct IfcElementAssembly : IfcElement, ObjectHelper<IfcElementAssembly,2> { IfcElementAssembly() : Object("IfcElementAssembly") {}
+ Maybe< IfcAssemblyPlaceEnum::Out > AssemblyPlace;
+ IfcElementAssemblyTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcBuilding
- struct IfcBuilding : IfcSpatialStructureElement, ObjectHelper<IfcBuilding,3> { IfcBuilding() : Object("IfcBuilding") {}
- Maybe< IfcLengthMeasure::Out > ElevationOfRefHeight;
- Maybe< IfcLengthMeasure::Out > ElevationOfTerrain;
- Maybe< Lazy< NotImplemented > > BuildingAddress;
+ // C++ wrapper for IfcElementQuantity
+ struct IfcElementQuantity : IfcPropertySetDefinition, ObjectHelper<IfcElementQuantity,2> { IfcElementQuantity() : Object("IfcElementQuantity") {}
+ Maybe< IfcLabel::Out > MethodOfMeasurement;
+ ListOf< Lazy< NotImplemented >, 1, 0 > Quantities;
};
- // C++ wrapper for IfcConnectedFaceSet
- struct IfcConnectedFaceSet : IfcTopologicalRepresentationItem, ObjectHelper<IfcConnectedFaceSet,1> { IfcConnectedFaceSet() : Object("IfcConnectedFaceSet") {}
- ListOf< Lazy< IfcFace >, 1, 0 > CfsFaces;
+ // C++ wrapper for IfcElementarySurface
+ struct IfcElementarySurface : IfcSurface, ObjectHelper<IfcElementarySurface,1> { IfcElementarySurface() : Object("IfcElementarySurface") {}
+ Lazy< IfcAxis2Placement3D > Position;
};
- // C++ wrapper for IfcOpenShell
- struct IfcOpenShell : IfcConnectedFaceSet, ObjectHelper<IfcOpenShell,0> { IfcOpenShell() : Object("IfcOpenShell") {}
+ // C++ wrapper for IfcEllipse
+ struct IfcEllipse : IfcConic, ObjectHelper<IfcEllipse,2> { IfcEllipse() : Object("IfcEllipse") {}
+ IfcPositiveLengthMeasure::Out SemiAxis1;
+ IfcPositiveLengthMeasure::Out SemiAxis2;
+ };
+ // C++ wrapper for IfcEllipseProfileDef
+ struct IfcEllipseProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcEllipseProfileDef,2> { IfcEllipseProfileDef() : Object("IfcEllipseProfileDef") {}
+ IfcPositiveLengthMeasure::Out SemiAxis1;
+ IfcPositiveLengthMeasure::Out SemiAxis2;
};
- // C++ wrapper for IfcFacetedBrep
- struct IfcFacetedBrep : IfcManifoldSolidBrep, ObjectHelper<IfcFacetedBrep,0> { IfcFacetedBrep() : Object("IfcFacetedBrep") {}
+ // C++ wrapper for IfcEnergyConversionDevice
+ struct IfcEnergyConversionDevice : IfcDistributionFlowElement, ObjectHelper<IfcEnergyConversionDevice,0> { IfcEnergyConversionDevice() : Object("IfcEnergyConversionDevice") {}
};
- // C++ wrapper for IfcConic
- struct IfcConic : IfcCurve, ObjectHelper<IfcConic,1> { IfcConic() : Object("IfcConic") {}
- IfcAxis2Placement::Out Position;
- };
+ // C++ wrapper for IfcEquipmentElement
+ struct IfcEquipmentElement : IfcElement, ObjectHelper<IfcEquipmentElement,0> { IfcEquipmentElement() : Object("IfcEquipmentElement") {}
- // C++ wrapper for IfcCoveringType
- struct IfcCoveringType : IfcBuildingElementType, ObjectHelper<IfcCoveringType,1> { IfcCoveringType() : Object("IfcCoveringType") {}
- IfcCoveringTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcRoundedRectangleProfileDef
- struct IfcRoundedRectangleProfileDef : IfcRectangleProfileDef, ObjectHelper<IfcRoundedRectangleProfileDef,1> { IfcRoundedRectangleProfileDef() : Object("IfcRoundedRectangleProfileDef") {}
- IfcPositiveLengthMeasure::Out RoundingRadius;
- };
+ // C++ wrapper for IfcEquipmentStandard
+ struct IfcEquipmentStandard : IfcControl, ObjectHelper<IfcEquipmentStandard,0> { IfcEquipmentStandard() : Object("IfcEquipmentStandard") {}
- // C++ wrapper for IfcAirTerminalType
- struct IfcAirTerminalType : IfcFlowTerminalType, ObjectHelper<IfcAirTerminalType,1> { IfcAirTerminalType() : Object("IfcAirTerminalType") {}
- IfcAirTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowMovingDeviceType
- struct IfcFlowMovingDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowMovingDeviceType,0> { IfcFlowMovingDeviceType() : Object("IfcFlowMovingDeviceType") {}
+ // C++ wrapper for IfcEvaporativeCoolerType
+ struct IfcEvaporativeCoolerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcEvaporativeCoolerType,1> { IfcEvaporativeCoolerType() : Object("IfcEvaporativeCoolerType") {}
+ IfcEvaporativeCoolerTypeEnum::Out PredefinedType;
+ };
+ // C++ wrapper for IfcEvaporatorType
+ struct IfcEvaporatorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcEvaporatorType,1> { IfcEvaporatorType() : Object("IfcEvaporatorType") {}
+ IfcEvaporatorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCompressorType
- struct IfcCompressorType : IfcFlowMovingDeviceType, ObjectHelper<IfcCompressorType,1> { IfcCompressorType() : Object("IfcCompressorType") {}
- IfcCompressorTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcSweptAreaSolid
+ struct IfcSweptAreaSolid : IfcSolidModel, ObjectHelper<IfcSweptAreaSolid,2> { IfcSweptAreaSolid() : Object("IfcSweptAreaSolid") {}
+ Lazy< IfcProfileDef > SweptArea;
+ Lazy< IfcAxis2Placement3D > Position;
};
- // C++ wrapper for IfcIShapeProfileDef
- struct IfcIShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcIShapeProfileDef,5> { IfcIShapeProfileDef() : Object("IfcIShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out OverallWidth;
- IfcPositiveLengthMeasure::Out OverallDepth;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out FlangeThickness;
- Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
+ // C++ wrapper for IfcExtrudedAreaSolid
+ struct IfcExtrudedAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcExtrudedAreaSolid,2> { IfcExtrudedAreaSolid() : Object("IfcExtrudedAreaSolid") {}
+ Lazy< IfcDirection > ExtrudedDirection;
+ IfcPositiveLengthMeasure::Out Depth;
};
- // C++ wrapper for IfcAsymmetricIShapeProfileDef
- struct IfcAsymmetricIShapeProfileDef : IfcIShapeProfileDef, ObjectHelper<IfcAsymmetricIShapeProfileDef,4> { IfcAsymmetricIShapeProfileDef() : Object("IfcAsymmetricIShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out TopFlangeWidth;
- Maybe< IfcPositiveLengthMeasure::Out > TopFlangeThickness;
- Maybe< IfcPositiveLengthMeasure::Out > TopFlangeFilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
+ // C++ wrapper for IfcFace
+ struct IfcFace : IfcTopologicalRepresentationItem, ObjectHelper<IfcFace,1> { IfcFace() : Object("IfcFace") {}
+ ListOf< Lazy< IfcFaceBound >, 1, 0 > Bounds;
};
- // C++ wrapper for IfcControllerType
- struct IfcControllerType : IfcDistributionControlElementType, ObjectHelper<IfcControllerType,1> { IfcControllerType() : Object("IfcControllerType") {}
- IfcControllerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcFaceBasedSurfaceModel
+ struct IfcFaceBasedSurfaceModel : IfcGeometricRepresentationItem, ObjectHelper<IfcFaceBasedSurfaceModel,1> { IfcFaceBasedSurfaceModel() : Object("IfcFaceBasedSurfaceModel") {}
+ ListOf< Lazy< IfcConnectedFaceSet >, 1, 0 > FbsmFaces;
};
- // C++ wrapper for IfcRailing
- struct IfcRailing : IfcBuildingElement, ObjectHelper<IfcRailing,1> { IfcRailing() : Object("IfcRailing") {}
- Maybe< IfcRailingTypeEnum::Out > PredefinedType;
+ // C++ wrapper for IfcFaceBound
+ struct IfcFaceBound : IfcTopologicalRepresentationItem, ObjectHelper<IfcFaceBound,2> { IfcFaceBound() : Object("IfcFaceBound") {}
+ Lazy< IfcLoop > Bound;
+ BOOLEAN::Out Orientation;
};
- // C++ wrapper for IfcGroup
- struct IfcGroup : IfcObject, ObjectHelper<IfcGroup,0> { IfcGroup() : Object("IfcGroup") {}
+ // C++ wrapper for IfcFaceOuterBound
+ struct IfcFaceOuterBound : IfcFaceBound, ObjectHelper<IfcFaceOuterBound,0> { IfcFaceOuterBound() : Object("IfcFaceOuterBound") {}
};
- // C++ wrapper for IfcAsset
- struct IfcAsset : IfcGroup, ObjectHelper<IfcAsset,9> { IfcAsset() : Object("IfcAsset") {}
- IfcIdentifier::Out AssetID;
- Lazy< NotImplemented > OriginalValue;
- Lazy< NotImplemented > CurrentValue;
- Lazy< NotImplemented > TotalReplacementCost;
- IfcActorSelect::Out Owner;
- IfcActorSelect::Out User;
- Lazy< NotImplemented > ResponsiblePerson;
- Lazy< NotImplemented > IncorporationDate;
- Lazy< NotImplemented > DepreciatedValue;
+ // C++ wrapper for IfcFaceSurface
+ struct IfcFaceSurface : IfcFace, ObjectHelper<IfcFaceSurface,2> { IfcFaceSurface() : Object("IfcFaceSurface") {}
+ Lazy< IfcSurface > FaceSurface;
+ BOOLEAN::Out SameSense;
};
- // C++ wrapper for IfcMaterialDefinitionRepresentation
- struct IfcMaterialDefinitionRepresentation : IfcProductRepresentation, ObjectHelper<IfcMaterialDefinitionRepresentation,1> { IfcMaterialDefinitionRepresentation() : Object("IfcMaterialDefinitionRepresentation") {}
- Lazy< NotImplemented > RepresentedMaterial;
+ // C++ wrapper for IfcManifoldSolidBrep
+ struct IfcManifoldSolidBrep : IfcSolidModel, ObjectHelper<IfcManifoldSolidBrep,1> { IfcManifoldSolidBrep() : Object("IfcManifoldSolidBrep") {}
+ Lazy< IfcClosedShell > Outer;
};
- // C++ wrapper for IfcRailingType
- struct IfcRailingType : IfcBuildingElementType, ObjectHelper<IfcRailingType,1> { IfcRailingType() : Object("IfcRailingType") {}
- IfcRailingTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcFacetedBrep
+ struct IfcFacetedBrep : IfcManifoldSolidBrep, ObjectHelper<IfcFacetedBrep,0> { IfcFacetedBrep() : Object("IfcFacetedBrep") {}
+
};
- // C++ wrapper for IfcWall
- struct IfcWall : IfcBuildingElement, ObjectHelper<IfcWall,0> { IfcWall() : Object("IfcWall") {}
+ // C++ wrapper for IfcFacetedBrepWithVoids
+ struct IfcFacetedBrepWithVoids : IfcManifoldSolidBrep, ObjectHelper<IfcFacetedBrepWithVoids,1> { IfcFacetedBrepWithVoids() : Object("IfcFacetedBrepWithVoids") {}
+ ListOf< Lazy< IfcClosedShell >, 1, 0 > Voids;
+ };
+ // C++ wrapper for IfcFanType
+ struct IfcFanType : IfcFlowMovingDeviceType, ObjectHelper<IfcFanType,1> { IfcFanType() : Object("IfcFanType") {}
+ IfcFanTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralPointConnection
- struct IfcStructuralPointConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralPointConnection,0> { IfcStructuralPointConnection() : Object("IfcStructuralPointConnection") {}
+ // C++ wrapper for IfcFastener
+ struct IfcFastener : IfcElementComponent, ObjectHelper<IfcFastener,0> { IfcFastener() : Object("IfcFastener") {}
};
- // C++ wrapper for IfcPropertyListValue
- struct IfcPropertyListValue : IfcSimpleProperty, ObjectHelper<IfcPropertyListValue,2> { IfcPropertyListValue() : Object("IfcPropertyListValue") {}
- ListOf< IfcValue, 1, 0 >::Out ListValues;
- Maybe< IfcUnit::Out > Unit;
+ // C++ wrapper for IfcFastenerType
+ struct IfcFastenerType : IfcElementComponentType, ObjectHelper<IfcFastenerType,0> { IfcFastenerType() : Object("IfcFastenerType") {}
+
};
- // C++ wrapper for IfcFurnitureStandard
- struct IfcFurnitureStandard : IfcControl, ObjectHelper<IfcFurnitureStandard,0> { IfcFurnitureStandard() : Object("IfcFurnitureStandard") {}
+ // C++ wrapper for IfcFeatureElementAddition
+ struct IfcFeatureElementAddition : IfcFeatureElement, ObjectHelper<IfcFeatureElementAddition,0> { IfcFeatureElementAddition() : Object("IfcFeatureElementAddition") {}
};
- // C++ wrapper for IfcElectricGeneratorType
- struct IfcElectricGeneratorType : IfcEnergyConversionDeviceType, ObjectHelper<IfcElectricGeneratorType,1> { IfcElectricGeneratorType() : Object("IfcElectricGeneratorType") {}
- IfcElectricGeneratorTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcFillAreaStyleHatching
+ struct IfcFillAreaStyleHatching : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleHatching,5> { IfcFillAreaStyleHatching() : Object("IfcFillAreaStyleHatching") {}
+ Lazy< NotImplemented > HatchLineAppearance;
+ IfcHatchLineDistanceSelect::Out StartOfNextHatchLine;
+ Maybe< Lazy< IfcCartesianPoint > > PointOfReferenceHatchLine;
+ Maybe< Lazy< IfcCartesianPoint > > PatternStart;
+ IfcPlaneAngleMeasure::Out HatchLineAngle;
};
- // C++ wrapper for IfcDoor
- struct IfcDoor : IfcBuildingElement, ObjectHelper<IfcDoor,2> { IfcDoor() : Object("IfcDoor") {}
- Maybe< IfcPositiveLengthMeasure::Out > OverallHeight;
- Maybe< IfcPositiveLengthMeasure::Out > OverallWidth;
+ // C++ wrapper for IfcFillAreaStyleTileSymbolWithStyle
+ struct IfcFillAreaStyleTileSymbolWithStyle : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleTileSymbolWithStyle,1> { IfcFillAreaStyleTileSymbolWithStyle() : Object("IfcFillAreaStyleTileSymbolWithStyle") {}
+ Lazy< IfcAnnotationSymbolOccurrence > Symbol;
};
- // C++ wrapper for IfcStyledItem
- struct IfcStyledItem : IfcRepresentationItem, ObjectHelper<IfcStyledItem,3> { IfcStyledItem() : Object("IfcStyledItem") {}
- Maybe< Lazy< IfcRepresentationItem > > Item;
- ListOf< Lazy< IfcPresentationStyleAssignment >, 1, 0 > Styles;
- Maybe< IfcLabel::Out > Name;
+ // C++ wrapper for IfcFillAreaStyleTiles
+ struct IfcFillAreaStyleTiles : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleTiles,3> { IfcFillAreaStyleTiles() : Object("IfcFillAreaStyleTiles") {}
+ Lazy< IfcOneDirectionRepeatFactor > TilingPattern;
+ ListOf< IfcFillAreaStyleTileShapeSelect, 1, 0 >::Out Tiles;
+ IfcPositiveRatioMeasure::Out TilingScale;
};
- // C++ wrapper for IfcAnnotationOccurrence
- struct IfcAnnotationOccurrence : IfcStyledItem, ObjectHelper<IfcAnnotationOccurrence,0> { IfcAnnotationOccurrence() : Object("IfcAnnotationOccurrence") {}
-
+ // C++ wrapper for IfcFilterType
+ struct IfcFilterType : IfcFlowTreatmentDeviceType, ObjectHelper<IfcFilterType,1> { IfcFilterType() : Object("IfcFilterType") {}
+ IfcFilterTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcAnnotationSymbolOccurrence
- struct IfcAnnotationSymbolOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationSymbolOccurrence,0> { IfcAnnotationSymbolOccurrence() : Object("IfcAnnotationSymbolOccurrence") {}
-
+ // C++ wrapper for IfcFireSuppressionTerminalType
+ struct IfcFireSuppressionTerminalType : IfcFlowTerminalType, ObjectHelper<IfcFireSuppressionTerminalType,1> { IfcFireSuppressionTerminalType() : Object("IfcFireSuppressionTerminalType") {}
+ IfcFireSuppressionTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcArbitraryClosedProfileDef
- struct IfcArbitraryClosedProfileDef : IfcProfileDef, ObjectHelper<IfcArbitraryClosedProfileDef,1> { IfcArbitraryClosedProfileDef() : Object("IfcArbitraryClosedProfileDef") {}
- Lazy< IfcCurve > OuterCurve;
+ // C++ wrapper for IfcFlowFitting
+ struct IfcFlowFitting : IfcDistributionFlowElement, ObjectHelper<IfcFlowFitting,0> { IfcFlowFitting() : Object("IfcFlowFitting") {}
+
};
- // C++ wrapper for IfcArbitraryProfileDefWithVoids
- struct IfcArbitraryProfileDefWithVoids : IfcArbitraryClosedProfileDef, ObjectHelper<IfcArbitraryProfileDefWithVoids,1> { IfcArbitraryProfileDefWithVoids() : Object("IfcArbitraryProfileDefWithVoids") {}
- ListOf< Lazy< IfcCurve >, 1, 0 > InnerCurves;
+ // C++ wrapper for IfcFlowInstrumentType
+ struct IfcFlowInstrumentType : IfcDistributionControlElementType, ObjectHelper<IfcFlowInstrumentType,1> { IfcFlowInstrumentType() : Object("IfcFlowInstrumentType") {}
+ IfcFlowInstrumentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcLine
- struct IfcLine : IfcCurve, ObjectHelper<IfcLine,2> { IfcLine() : Object("IfcLine") {}
- Lazy< IfcCartesianPoint > Pnt;
- Lazy< IfcVector > Dir;
+ // C++ wrapper for IfcFlowMeterType
+ struct IfcFlowMeterType : IfcFlowControllerType, ObjectHelper<IfcFlowMeterType,1> { IfcFlowMeterType() : Object("IfcFlowMeterType") {}
+ IfcFlowMeterTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowSegmentType
- struct IfcFlowSegmentType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowSegmentType,0> { IfcFlowSegmentType() : Object("IfcFlowSegmentType") {}
+ // C++ wrapper for IfcFlowMovingDevice
+ struct IfcFlowMovingDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowMovingDevice,0> { IfcFlowMovingDevice() : Object("IfcFlowMovingDevice") {}
};
- // C++ wrapper for IfcAirTerminalBoxType
- struct IfcAirTerminalBoxType : IfcFlowControllerType, ObjectHelper<IfcAirTerminalBoxType,1> { IfcAirTerminalBoxType() : Object("IfcAirTerminalBoxType") {}
- IfcAirTerminalBoxTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcFlowSegment
+ struct IfcFlowSegment : IfcDistributionFlowElement, ObjectHelper<IfcFlowSegment,0> { IfcFlowSegment() : Object("IfcFlowSegment") {}
- // C++ wrapper for IfcPropertySingleValue
- struct IfcPropertySingleValue : IfcSimpleProperty, ObjectHelper<IfcPropertySingleValue,2> { IfcPropertySingleValue() : Object("IfcPropertySingleValue") {}
- Maybe< IfcValue::Out > NominalValue;
- Maybe< IfcUnit::Out > Unit;
};
- // C++ wrapper for IfcAlarmType
- struct IfcAlarmType : IfcDistributionControlElementType, ObjectHelper<IfcAlarmType,1> { IfcAlarmType() : Object("IfcAlarmType") {}
- IfcAlarmTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcFlowStorageDevice
+ struct IfcFlowStorageDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowStorageDevice,0> { IfcFlowStorageDevice() : Object("IfcFlowStorageDevice") {}
- // C++ wrapper for IfcEllipseProfileDef
- struct IfcEllipseProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcEllipseProfileDef,2> { IfcEllipseProfileDef() : Object("IfcEllipseProfileDef") {}
- IfcPositiveLengthMeasure::Out SemiAxis1;
- IfcPositiveLengthMeasure::Out SemiAxis2;
};
- // C++ wrapper for IfcStair
- struct IfcStair : IfcBuildingElement, ObjectHelper<IfcStair,1> { IfcStair() : Object("IfcStair") {}
- IfcStairTypeEnum::Out ShapeType;
- };
+ // C++ wrapper for IfcFlowTerminal
+ struct IfcFlowTerminal : IfcDistributionFlowElement, ObjectHelper<IfcFlowTerminal,0> { IfcFlowTerminal() : Object("IfcFlowTerminal") {}
- // C++ wrapper for IfcSurfaceStyleShading
- struct IfcSurfaceStyleShading : ObjectHelper<IfcSurfaceStyleShading,1> { IfcSurfaceStyleShading() : Object("IfcSurfaceStyleShading") {}
- Lazy< IfcColourRgb > SurfaceColour;
};
- // C++ wrapper for IfcPumpType
- struct IfcPumpType : IfcFlowMovingDeviceType, ObjectHelper<IfcPumpType,1> { IfcPumpType() : Object("IfcPumpType") {}
- IfcPumpTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcFlowTreatmentDevice
+ struct IfcFlowTreatmentDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowTreatmentDevice,0> { IfcFlowTreatmentDevice() : Object("IfcFlowTreatmentDevice") {}
+
};
- // C++ wrapper for IfcDefinedSymbol
- struct IfcDefinedSymbol : IfcGeometricRepresentationItem, ObjectHelper<IfcDefinedSymbol,2> { IfcDefinedSymbol() : Object("IfcDefinedSymbol") {}
- IfcDefinedSymbolSelect::Out Definition;
- Lazy< IfcCartesianTransformationOperator2D > Target;
+ // C++ wrapper for IfcFooting
+ struct IfcFooting : IfcBuildingElement, ObjectHelper<IfcFooting,1> { IfcFooting() : Object("IfcFooting") {}
+ IfcFootingTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcElementComponentType
- struct IfcElementComponentType : IfcElementType, ObjectHelper<IfcElementComponentType,0> { IfcElementComponentType() : Object("IfcElementComponentType") {}
+ // C++ wrapper for IfcFurnishingElement
+ struct IfcFurnishingElement : IfcElement, ObjectHelper<IfcFurnishingElement,0> { IfcFurnishingElement() : Object("IfcFurnishingElement") {}
};
- // C++ wrapper for IfcFastenerType
- struct IfcFastenerType : IfcElementComponentType, ObjectHelper<IfcFastenerType,0> { IfcFastenerType() : Object("IfcFastenerType") {}
+ // C++ wrapper for IfcFurnishingElementType
+ struct IfcFurnishingElementType : IfcElementType, ObjectHelper<IfcFurnishingElementType,0> { IfcFurnishingElementType() : Object("IfcFurnishingElementType") {}
};
- // C++ wrapper for IfcMechanicalFastenerType
- struct IfcMechanicalFastenerType : IfcFastenerType, ObjectHelper<IfcMechanicalFastenerType,0> { IfcMechanicalFastenerType() : Object("IfcMechanicalFastenerType") {}
+ // C++ wrapper for IfcFurnitureStandard
+ struct IfcFurnitureStandard : IfcControl, ObjectHelper<IfcFurnitureStandard,0> { IfcFurnitureStandard() : Object("IfcFurnitureStandard") {}
};
- // C++ wrapper for IfcFlowFitting
- struct IfcFlowFitting : IfcDistributionFlowElement, ObjectHelper<IfcFlowFitting,0> { IfcFlowFitting() : Object("IfcFlowFitting") {}
-
+ // C++ wrapper for IfcFurnitureType
+ struct IfcFurnitureType : IfcFurnishingElementType, ObjectHelper<IfcFurnitureType,1> { IfcFurnitureType() : Object("IfcFurnitureType") {}
+ IfcAssemblyPlaceEnum::Out AssemblyPlace;
};
- // C++ wrapper for IfcLightSourceDirectional
- struct IfcLightSourceDirectional : IfcLightSource, ObjectHelper<IfcLightSourceDirectional,1> { IfcLightSourceDirectional() : Object("IfcLightSourceDirectional") {}
- Lazy< IfcDirection > Orientation;
+ // C++ wrapper for IfcGasTerminalType
+ struct IfcGasTerminalType : IfcFlowTerminalType, ObjectHelper<IfcGasTerminalType,1> { IfcGasTerminalType() : Object("IfcGasTerminalType") {}
+ IfcGasTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSurfaceStyle
- struct IfcSurfaceStyle : IfcPresentationStyle, ObjectHelper<IfcSurfaceStyle,2> { IfcSurfaceStyle() : Object("IfcSurfaceStyle") {}
- IfcSurfaceSide::Out Side;
- ListOf< IfcSurfaceStyleElementSelect, 1, 5 >::Out Styles;
+ // C++ wrapper for IfcGeometricSet
+ struct IfcGeometricSet : IfcGeometricRepresentationItem, ObjectHelper<IfcGeometricSet,1> { IfcGeometricSet() : Object("IfcGeometricSet") {}
+ ListOf< IfcGeometricSetSelect, 1, 0 >::Out Elements;
};
- // C++ wrapper for IfcAnnotationSurface
- struct IfcAnnotationSurface : IfcGeometricRepresentationItem, ObjectHelper<IfcAnnotationSurface,2> { IfcAnnotationSurface() : Object("IfcAnnotationSurface") {}
- Lazy< IfcGeometricRepresentationItem > Item;
- Maybe< Lazy< NotImplemented > > TextureCoordinates;
+ // C++ wrapper for IfcGeometricCurveSet
+ struct IfcGeometricCurveSet : IfcGeometricSet, ObjectHelper<IfcGeometricCurveSet,0> { IfcGeometricCurveSet() : Object("IfcGeometricCurveSet") {}
+
};
- // C++ wrapper for IfcFlowController
- struct IfcFlowController : IfcDistributionFlowElement, ObjectHelper<IfcFlowController,0> { IfcFlowController() : Object("IfcFlowController") {}
+ // C++ wrapper for IfcRepresentationContext
+ struct IfcRepresentationContext : ObjectHelper<IfcRepresentationContext,2> { IfcRepresentationContext() : Object("IfcRepresentationContext") {}
+ Maybe< IfcLabel::Out > ContextIdentifier;
+ Maybe< IfcLabel::Out > ContextType;
+ };
+ // C++ wrapper for IfcGeometricRepresentationContext
+ struct IfcGeometricRepresentationContext : IfcRepresentationContext, ObjectHelper<IfcGeometricRepresentationContext,4> { IfcGeometricRepresentationContext() : Object("IfcGeometricRepresentationContext") {}
+ IfcDimensionCount::Out CoordinateSpaceDimension;
+ Maybe< REAL::Out > Precision;
+ IfcAxis2Placement::Out WorldCoordinateSystem;
+ Maybe< Lazy< IfcDirection > > TrueNorth;
};
- // C++ wrapper for IfcBuildingStorey
- struct IfcBuildingStorey : IfcSpatialStructureElement, ObjectHelper<IfcBuildingStorey,1> { IfcBuildingStorey() : Object("IfcBuildingStorey") {}
- Maybe< IfcLengthMeasure::Out > Elevation;
+ // C++ wrapper for IfcGeometricRepresentationSubContext
+ struct IfcGeometricRepresentationSubContext : IfcGeometricRepresentationContext, ObjectHelper<IfcGeometricRepresentationSubContext,4> { IfcGeometricRepresentationSubContext() : Object("IfcGeometricRepresentationSubContext") {}
+ Lazy< IfcGeometricRepresentationContext > ParentContext;
+ Maybe< IfcPositiveRatioMeasure::Out > TargetScale;
+ IfcGeometricProjectionEnum::Out TargetView;
+ Maybe< IfcLabel::Out > UserDefinedTargetView;
};
- // C++ wrapper for IfcWorkControl
- struct IfcWorkControl : IfcControl, ObjectHelper<IfcWorkControl,10> { IfcWorkControl() : Object("IfcWorkControl") {}
- IfcIdentifier::Out Identifier;
- IfcDateTimeSelect::Out CreationDate;
- Maybe< ListOf< Lazy< NotImplemented >, 1, 0 > > Creators;
- Maybe< IfcLabel::Out > Purpose;
- Maybe< IfcTimeMeasure::Out > Duration;
- Maybe< IfcTimeMeasure::Out > TotalFloat;
- IfcDateTimeSelect::Out StartTime;
- Maybe< IfcDateTimeSelect::Out > FinishTime;
- Maybe< IfcWorkControlTypeEnum::Out > WorkControlType;
- Maybe< IfcLabel::Out > UserDefinedControlType;
+ // C++ wrapper for IfcGrid
+ struct IfcGrid : IfcProduct, ObjectHelper<IfcGrid,3> { IfcGrid() : Object("IfcGrid") {}
+ ListOf< Lazy< NotImplemented >, 1, 0 > UAxes;
+ ListOf< Lazy< NotImplemented >, 1, 0 > VAxes;
+ Maybe< ListOf< Lazy< NotImplemented >, 1, 0 > > WAxes;
};
- // C++ wrapper for IfcWorkSchedule
- struct IfcWorkSchedule : IfcWorkControl, ObjectHelper<IfcWorkSchedule,0> { IfcWorkSchedule() : Object("IfcWorkSchedule") {}
+ // C++ wrapper for IfcObjectPlacement
+ struct IfcObjectPlacement : ObjectHelper<IfcObjectPlacement,0> { IfcObjectPlacement() : Object("IfcObjectPlacement") {}
};
- // C++ wrapper for IfcDuctSegmentType
- struct IfcDuctSegmentType : IfcFlowSegmentType, ObjectHelper<IfcDuctSegmentType,1> { IfcDuctSegmentType() : Object("IfcDuctSegmentType") {}
- IfcDuctSegmentTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcGridPlacement
+ struct IfcGridPlacement : IfcObjectPlacement, ObjectHelper<IfcGridPlacement,2> { IfcGridPlacement() : Object("IfcGridPlacement") {}
+ Lazy< NotImplemented > PlacementLocation;
+ Maybe< Lazy< NotImplemented > > PlacementRefDirection;
};
- // C++ wrapper for IfcFace
- struct IfcFace : IfcTopologicalRepresentationItem, ObjectHelper<IfcFace,1> { IfcFace() : Object("IfcFace") {}
- ListOf< Lazy< IfcFaceBound >, 1, 0 > Bounds;
+ // C++ wrapper for IfcHeatExchangerType
+ struct IfcHeatExchangerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcHeatExchangerType,1> { IfcHeatExchangerType() : Object("IfcHeatExchangerType") {}
+ IfcHeatExchangerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralSurfaceMember
- struct IfcStructuralSurfaceMember : IfcStructuralMember, ObjectHelper<IfcStructuralSurfaceMember,2> { IfcStructuralSurfaceMember() : Object("IfcStructuralSurfaceMember") {}
- IfcStructuralSurfaceTypeEnum::Out PredefinedType;
- Maybe< IfcPositiveLengthMeasure::Out > Thickness;
+ // C++ wrapper for IfcHumidifierType
+ struct IfcHumidifierType : IfcEnergyConversionDeviceType, ObjectHelper<IfcHumidifierType,1> { IfcHumidifierType() : Object("IfcHumidifierType") {}
+ IfcHumidifierTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralSurfaceMemberVarying
- struct IfcStructuralSurfaceMemberVarying : IfcStructuralSurfaceMember, ObjectHelper<IfcStructuralSurfaceMemberVarying,2> { IfcStructuralSurfaceMemberVarying() : Object("IfcStructuralSurfaceMemberVarying") {}
- ListOf< IfcPositiveLengthMeasure, 2, 0 >::Out SubsequentThickness;
- Lazy< NotImplemented > VaryingThicknessLocation;
+ // C++ wrapper for IfcInventory
+ struct IfcInventory : IfcGroup, ObjectHelper<IfcInventory,6> { IfcInventory() : Object("IfcInventory") {}
+ IfcInventoryTypeEnum::Out InventoryType;
+ IfcActorSelect::Out Jurisdiction;
+ ListOf< Lazy< NotImplemented >, 1, 0 > ResponsiblePersons;
+ Lazy< NotImplemented > LastUpdateDate;
+ Maybe< Lazy< NotImplemented > > CurrentValue;
+ Maybe< Lazy< NotImplemented > > OriginalValue;
};
- // C++ wrapper for IfcFaceSurface
- struct IfcFaceSurface : IfcFace, ObjectHelper<IfcFaceSurface,2> { IfcFaceSurface() : Object("IfcFaceSurface") {}
- Lazy< IfcSurface > FaceSurface;
- BOOLEAN::Out SameSense;
+ // C++ wrapper for IfcJunctionBoxType
+ struct IfcJunctionBoxType : IfcFlowFittingType, ObjectHelper<IfcJunctionBoxType,1> { IfcJunctionBoxType() : Object("IfcJunctionBoxType") {}
+ IfcJunctionBoxTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCostSchedule
- struct IfcCostSchedule : IfcControl, ObjectHelper<IfcCostSchedule,8> { IfcCostSchedule() : Object("IfcCostSchedule") {}
- Maybe< IfcActorSelect::Out > SubmittedBy;
- Maybe< IfcActorSelect::Out > PreparedBy;
- Maybe< IfcDateTimeSelect::Out > SubmittedOn;
- Maybe< IfcLabel::Out > Status;
- Maybe< ListOf< IfcActorSelect, 1, 0 >::Out > TargetUsers;
- Maybe< IfcDateTimeSelect::Out > UpdateDate;
- IfcIdentifier::Out ID;
- IfcCostScheduleTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcLShapeProfileDef
+ struct IfcLShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcLShapeProfileDef,8> { IfcLShapeProfileDef() : Object("IfcLShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out Depth;
+ Maybe< IfcPositiveLengthMeasure::Out > Width;
+ IfcPositiveLengthMeasure::Out Thickness;
+ Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
+ Maybe< IfcPlaneAngleMeasure::Out > LegSlope;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcPlanarExtent
- struct IfcPlanarExtent : IfcGeometricRepresentationItem, ObjectHelper<IfcPlanarExtent,2> { IfcPlanarExtent() : Object("IfcPlanarExtent") {}
- IfcLengthMeasure::Out SizeInX;
- IfcLengthMeasure::Out SizeInY;
+ // C++ wrapper for IfcLaborResource
+ struct IfcLaborResource : IfcConstructionResource, ObjectHelper<IfcLaborResource,1> { IfcLaborResource() : Object("IfcLaborResource") {}
+ Maybe< IfcText::Out > SkillSet;
};
- // C++ wrapper for IfcPlanarBox
- struct IfcPlanarBox : IfcPlanarExtent, ObjectHelper<IfcPlanarBox,1> { IfcPlanarBox() : Object("IfcPlanarBox") {}
- IfcAxis2Placement::Out Placement;
+ // C++ wrapper for IfcLampType
+ struct IfcLampType : IfcFlowTerminalType, ObjectHelper<IfcLampType,1> { IfcLampType() : Object("IfcLampType") {}
+ IfcLampTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcColourSpecification
- struct IfcColourSpecification : ObjectHelper<IfcColourSpecification,1> { IfcColourSpecification() : Object("IfcColourSpecification") {}
- Maybe< IfcLabel::Out > Name;
+ // C++ wrapper for IfcLightFixtureType
+ struct IfcLightFixtureType : IfcFlowTerminalType, ObjectHelper<IfcLightFixtureType,1> { IfcLightFixtureType() : Object("IfcLightFixtureType") {}
+ IfcLightFixtureTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcVector
- struct IfcVector : IfcGeometricRepresentationItem, ObjectHelper<IfcVector,2> { IfcVector() : Object("IfcVector") {}
- Lazy< IfcDirection > Orientation;
- IfcLengthMeasure::Out Magnitude;
+ // C++ wrapper for IfcLightSource
+ struct IfcLightSource : IfcGeometricRepresentationItem, ObjectHelper<IfcLightSource,4> { IfcLightSource() : Object("IfcLightSource") {}
+ Maybe< IfcLabel::Out > Name;
+ Lazy< IfcColourRgb > LightColour;
+ Maybe< IfcNormalisedRatioMeasure::Out > AmbientIntensity;
+ Maybe< IfcNormalisedRatioMeasure::Out > Intensity;
};
- // C++ wrapper for IfcBeam
- struct IfcBeam : IfcBuildingElement, ObjectHelper<IfcBeam,0> { IfcBeam() : Object("IfcBeam") {}
+ // C++ wrapper for IfcLightSourceAmbient
+ struct IfcLightSourceAmbient : IfcLightSource, ObjectHelper<IfcLightSourceAmbient,0> { IfcLightSourceAmbient() : Object("IfcLightSourceAmbient") {}
};
- // C++ wrapper for IfcColourRgb
- struct IfcColourRgb : IfcColourSpecification, ObjectHelper<IfcColourRgb,3> { IfcColourRgb() : Object("IfcColourRgb") {}
- IfcNormalisedRatioMeasure::Out Red;
- IfcNormalisedRatioMeasure::Out Green;
- IfcNormalisedRatioMeasure::Out Blue;
+ // C++ wrapper for IfcLightSourceDirectional
+ struct IfcLightSourceDirectional : IfcLightSource, ObjectHelper<IfcLightSourceDirectional,1> { IfcLightSourceDirectional() : Object("IfcLightSourceDirectional") {}
+ Lazy< IfcDirection > Orientation;
};
- // C++ wrapper for IfcStructuralPlanarAction
- struct IfcStructuralPlanarAction : IfcStructuralAction, ObjectHelper<IfcStructuralPlanarAction,1> { IfcStructuralPlanarAction() : Object("IfcStructuralPlanarAction") {}
- IfcProjectedOrTrueLengthEnum::Out ProjectedOrTrue;
+ // C++ wrapper for IfcLightSourceGoniometric
+ struct IfcLightSourceGoniometric : IfcLightSource, ObjectHelper<IfcLightSourceGoniometric,6> { IfcLightSourceGoniometric() : Object("IfcLightSourceGoniometric") {}
+ Lazy< IfcAxis2Placement3D > Position;
+ Maybe< Lazy< IfcColourRgb > > ColourAppearance;
+ IfcThermodynamicTemperatureMeasure::Out ColourTemperature;
+ IfcLuminousFluxMeasure::Out LuminousFlux;
+ IfcLightEmissionSourceEnum::Out LightEmissionSource;
+ IfcLightDistributionDataSourceSelect::Out LightDistributionDataSource;
};
- // C++ wrapper for IfcStructuralPlanarActionVarying
- struct IfcStructuralPlanarActionVarying : IfcStructuralPlanarAction, ObjectHelper<IfcStructuralPlanarActionVarying,2> { IfcStructuralPlanarActionVarying() : Object("IfcStructuralPlanarActionVarying") {}
- Lazy< NotImplemented > VaryingAppliedLoadLocation;
- ListOf< Lazy< NotImplemented >, 2, 0 > SubsequentAppliedLoads;
+ // C++ wrapper for IfcLightSourcePositional
+ struct IfcLightSourcePositional : IfcLightSource, ObjectHelper<IfcLightSourcePositional,5> { IfcLightSourcePositional() : Object("IfcLightSourcePositional") {}
+ Lazy< IfcCartesianPoint > Position;
+ IfcPositiveLengthMeasure::Out Radius;
+ IfcReal::Out ConstantAttenuation;
+ IfcReal::Out DistanceAttenuation;
+ IfcReal::Out QuadricAttenuation;
};
- // C++ wrapper for IfcSite
- struct IfcSite : IfcSpatialStructureElement, ObjectHelper<IfcSite,5> { IfcSite() : Object("IfcSite") {}
- Maybe< IfcCompoundPlaneAngleMeasure::Out > RefLatitude;
- Maybe< IfcCompoundPlaneAngleMeasure::Out > RefLongitude;
- Maybe< IfcLengthMeasure::Out > RefElevation;
- Maybe< IfcLabel::Out > LandTitleNumber;
- Maybe< Lazy< NotImplemented > > SiteAddress;
+ // C++ wrapper for IfcLightSourceSpot
+ struct IfcLightSourceSpot : IfcLightSourcePositional, ObjectHelper<IfcLightSourceSpot,4> { IfcLightSourceSpot() : Object("IfcLightSourceSpot") {}
+ Lazy< IfcDirection > Orientation;
+ Maybe< IfcReal::Out > ConcentrationExponent;
+ IfcPositivePlaneAngleMeasure::Out SpreadAngle;
+ IfcPositivePlaneAngleMeasure::Out BeamWidthAngle;
};
- // C++ wrapper for IfcDiscreteAccessoryType
- struct IfcDiscreteAccessoryType : IfcElementComponentType, ObjectHelper<IfcDiscreteAccessoryType,0> { IfcDiscreteAccessoryType() : Object("IfcDiscreteAccessoryType") {}
-
+ // C++ wrapper for IfcLine
+ struct IfcLine : IfcCurve, ObjectHelper<IfcLine,2> { IfcLine() : Object("IfcLine") {}
+ Lazy< IfcCartesianPoint > Pnt;
+ Lazy< IfcVector > Dir;
};
- // C++ wrapper for IfcVibrationIsolatorType
- struct IfcVibrationIsolatorType : IfcDiscreteAccessoryType, ObjectHelper<IfcVibrationIsolatorType,1> { IfcVibrationIsolatorType() : Object("IfcVibrationIsolatorType") {}
- IfcVibrationIsolatorTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcLinearDimension
+ struct IfcLinearDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcLinearDimension,0> { IfcLinearDimension() : Object("IfcLinearDimension") {}
- // C++ wrapper for IfcEvaporativeCoolerType
- struct IfcEvaporativeCoolerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcEvaporativeCoolerType,1> { IfcEvaporativeCoolerType() : Object("IfcEvaporativeCoolerType") {}
- IfcEvaporativeCoolerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcDistributionChamberElementType
- struct IfcDistributionChamberElementType : IfcDistributionFlowElementType, ObjectHelper<IfcDistributionChamberElementType,1> { IfcDistributionChamberElementType() : Object("IfcDistributionChamberElementType") {}
- IfcDistributionChamberElementTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcLocalPlacement
+ struct IfcLocalPlacement : IfcObjectPlacement, ObjectHelper<IfcLocalPlacement,2> { IfcLocalPlacement() : Object("IfcLocalPlacement") {}
+ Maybe< Lazy< IfcObjectPlacement > > PlacementRelTo;
+ IfcAxis2Placement::Out RelativePlacement;
};
- // C++ wrapper for IfcFeatureElementAddition
- struct IfcFeatureElementAddition : IfcFeatureElement, ObjectHelper<IfcFeatureElementAddition,0> { IfcFeatureElementAddition() : Object("IfcFeatureElementAddition") {}
-
+ // C++ wrapper for IfcMappedItem
+ struct IfcMappedItem : IfcRepresentationItem, ObjectHelper<IfcMappedItem,2> { IfcMappedItem() : Object("IfcMappedItem") {}
+ Lazy< IfcRepresentationMap > MappingSource;
+ Lazy< IfcCartesianTransformationOperator > MappingTarget;
};
- // C++ wrapper for IfcStructuredDimensionCallout
- struct IfcStructuredDimensionCallout : IfcDraughtingCallout, ObjectHelper<IfcStructuredDimensionCallout,0> { IfcStructuredDimensionCallout() : Object("IfcStructuredDimensionCallout") {}
-
+ // C++ wrapper for IfcProductRepresentation
+ struct IfcProductRepresentation : ObjectHelper<IfcProductRepresentation,3> { IfcProductRepresentation() : Object("IfcProductRepresentation") {}
+ Maybe< IfcLabel::Out > Name;
+ Maybe< IfcText::Out > Description;
+ ListOf< Lazy< IfcRepresentation >, 1, 0 > Representations;
};
- // C++ wrapper for IfcCoolingTowerType
- struct IfcCoolingTowerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcCoolingTowerType,1> { IfcCoolingTowerType() : Object("IfcCoolingTowerType") {}
- IfcCoolingTowerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcMaterialDefinitionRepresentation
+ struct IfcMaterialDefinitionRepresentation : IfcProductRepresentation, ObjectHelper<IfcMaterialDefinitionRepresentation,1> { IfcMaterialDefinitionRepresentation() : Object("IfcMaterialDefinitionRepresentation") {}
+ Lazy< NotImplemented > RepresentedMaterial;
};
- // C++ wrapper for IfcCenterLineProfileDef
- struct IfcCenterLineProfileDef : IfcArbitraryOpenProfileDef, ObjectHelper<IfcCenterLineProfileDef,1> { IfcCenterLineProfileDef() : Object("IfcCenterLineProfileDef") {}
- IfcPositiveLengthMeasure::Out Thickness;
+ // C++ wrapper for IfcMeasureWithUnit
+ struct IfcMeasureWithUnit : ObjectHelper<IfcMeasureWithUnit,2> { IfcMeasureWithUnit() : Object("IfcMeasureWithUnit") {}
+ IfcValue::Out ValueComponent;
+ IfcUnit::Out UnitComponent;
};
- // C++ wrapper for IfcWindowStyle
- struct IfcWindowStyle : IfcTypeProduct, ObjectHelper<IfcWindowStyle,4> { IfcWindowStyle() : Object("IfcWindowStyle") {}
- IfcWindowStyleConstructionEnum::Out ConstructionType;
- IfcWindowStyleOperationEnum::Out OperationType;
- BOOLEAN::Out ParameterTakesPrecedence;
- BOOLEAN::Out Sizeable;
+ // C++ wrapper for IfcMechanicalFastener
+ struct IfcMechanicalFastener : IfcFastener, ObjectHelper<IfcMechanicalFastener,2> { IfcMechanicalFastener() : Object("IfcMechanicalFastener") {}
+ Maybe< IfcPositiveLengthMeasure::Out > NominalDiameter;
+ Maybe< IfcPositiveLengthMeasure::Out > NominalLength;
};
- // C++ wrapper for IfcLightSourceGoniometric
- struct IfcLightSourceGoniometric : IfcLightSource, ObjectHelper<IfcLightSourceGoniometric,6> { IfcLightSourceGoniometric() : Object("IfcLightSourceGoniometric") {}
- Lazy< IfcAxis2Placement3D > Position;
- Maybe< Lazy< IfcColourRgb > > ColourAppearance;
- IfcThermodynamicTemperatureMeasure::Out ColourTemperature;
- IfcLuminousFluxMeasure::Out LuminousFlux;
- IfcLightEmissionSourceEnum::Out LightEmissionSource;
- IfcLightDistributionDataSourceSelect::Out LightDistributionDataSource;
+ // C++ wrapper for IfcMechanicalFastenerType
+ struct IfcMechanicalFastenerType : IfcFastenerType, ObjectHelper<IfcMechanicalFastenerType,0> { IfcMechanicalFastenerType() : Object("IfcMechanicalFastenerType") {}
+
};
- // C++ wrapper for IfcTransformerType
- struct IfcTransformerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcTransformerType,1> { IfcTransformerType() : Object("IfcTransformerType") {}
- IfcTransformerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcMember
+ struct IfcMember : IfcBuildingElement, ObjectHelper<IfcMember,0> { IfcMember() : Object("IfcMember") {}
+
};
// C++ wrapper for IfcMemberType
struct IfcMemberType : IfcBuildingElementType, ObjectHelper<IfcMemberType,1> { IfcMemberType() : Object("IfcMemberType") {}
- IfcMemberTypeEnum::Out PredefinedType;
- };
-
- // C++ wrapper for IfcSurfaceOfLinearExtrusion
- struct IfcSurfaceOfLinearExtrusion : IfcSweptSurface, ObjectHelper<IfcSurfaceOfLinearExtrusion,2> { IfcSurfaceOfLinearExtrusion() : Object("IfcSurfaceOfLinearExtrusion") {}
- Lazy< IfcDirection > ExtrudedDirection;
- IfcLengthMeasure::Out Depth;
+ IfcMemberTypeEnum::Out PredefinedType;
};
// C++ wrapper for IfcMotorConnectionType
struct IfcMotorConnectionType : IfcEnergyConversionDeviceType, ObjectHelper<IfcMotorConnectionType,1> { IfcMotorConnectionType() : Object("IfcMotorConnectionType") {}
- IfcMotorConnectionTypeEnum::Out PredefinedType;
+ IfcMotorConnectionTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFlowTreatmentDeviceType
- struct IfcFlowTreatmentDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowTreatmentDeviceType,0> { IfcFlowTreatmentDeviceType() : Object("IfcFlowTreatmentDeviceType") {}
+ // C++ wrapper for IfcProcess
+ struct IfcProcess : IfcObject, ObjectHelper<IfcProcess,0> { IfcProcess() : Object("IfcProcess") {}
};
- // C++ wrapper for IfcDuctSilencerType
- struct IfcDuctSilencerType : IfcFlowTreatmentDeviceType, ObjectHelper<IfcDuctSilencerType,1> { IfcDuctSilencerType() : Object("IfcDuctSilencerType") {}
- IfcDuctSilencerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcTask
+ struct IfcTask : IfcProcess, ObjectHelper<IfcTask,5> { IfcTask() : Object("IfcTask") {}
+ IfcIdentifier::Out TaskId;
+ Maybe< IfcLabel::Out > Status;
+ Maybe< IfcLabel::Out > WorkMethod;
+ BOOLEAN::Out IsMilestone;
+ Maybe< INTEGER::Out > Priority;
};
- // C++ wrapper for IfcFurnishingElementType
- struct IfcFurnishingElementType : IfcElementType, ObjectHelper<IfcFurnishingElementType,0> { IfcFurnishingElementType() : Object("IfcFurnishingElementType") {}
-
+ // C++ wrapper for IfcMove
+ struct IfcMove : IfcTask, ObjectHelper<IfcMove,3> { IfcMove() : Object("IfcMove") {}
+ Lazy< IfcSpatialStructureElement > MoveFrom;
+ Lazy< IfcSpatialStructureElement > MoveTo;
+ Maybe< ListOf< IfcText, 1, 0 >::Out > PunchList;
};
- // C++ wrapper for IfcSystemFurnitureElementType
- struct IfcSystemFurnitureElementType : IfcFurnishingElementType, ObjectHelper<IfcSystemFurnitureElementType,0> { IfcSystemFurnitureElementType() : Object("IfcSystemFurnitureElementType") {}
-
+ // C++ wrapper for IfcOccupant
+ struct IfcOccupant : IfcActor, ObjectHelper<IfcOccupant,1> { IfcOccupant() : Object("IfcOccupant") {}
+ IfcOccupantTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcWasteTerminalType
- struct IfcWasteTerminalType : IfcFlowTerminalType, ObjectHelper<IfcWasteTerminalType,1> { IfcWasteTerminalType() : Object("IfcWasteTerminalType") {}
- IfcWasteTerminalTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcOffsetCurve2D
+ struct IfcOffsetCurve2D : IfcCurve, ObjectHelper<IfcOffsetCurve2D,3> { IfcOffsetCurve2D() : Object("IfcOffsetCurve2D") {}
+ Lazy< IfcCurve > BasisCurve;
+ IfcLengthMeasure::Out Distance;
+ LOGICAL::Out SelfIntersect;
};
- // C++ wrapper for IfcBSplineCurve
- struct IfcBSplineCurve : IfcBoundedCurve, ObjectHelper<IfcBSplineCurve,5> { IfcBSplineCurve() : Object("IfcBSplineCurve") {}
- INTEGER::Out Degree;
- ListOf< Lazy< IfcCartesianPoint >, 2, 0 > ControlPointsList;
- IfcBSplineCurveForm::Out CurveForm;
- LOGICAL::Out ClosedCurve;
- LOGICAL::Out SelfIntersect;
+ // C++ wrapper for IfcOffsetCurve3D
+ struct IfcOffsetCurve3D : IfcCurve, ObjectHelper<IfcOffsetCurve3D,4> { IfcOffsetCurve3D() : Object("IfcOffsetCurve3D") {}
+ Lazy< IfcCurve > BasisCurve;
+ IfcLengthMeasure::Out Distance;
+ LOGICAL::Out SelfIntersect;
+ Lazy< IfcDirection > RefDirection;
};
- // C++ wrapper for IfcBezierCurve
- struct IfcBezierCurve : IfcBSplineCurve, ObjectHelper<IfcBezierCurve,0> { IfcBezierCurve() : Object("IfcBezierCurve") {}
-
+ // C++ wrapper for IfcOneDirectionRepeatFactor
+ struct IfcOneDirectionRepeatFactor : IfcGeometricRepresentationItem, ObjectHelper<IfcOneDirectionRepeatFactor,1> { IfcOneDirectionRepeatFactor() : Object("IfcOneDirectionRepeatFactor") {}
+ Lazy< IfcVector > RepeatFactor;
};
- // C++ wrapper for IfcActuatorType
- struct IfcActuatorType : IfcDistributionControlElementType, ObjectHelper<IfcActuatorType,1> { IfcActuatorType() : Object("IfcActuatorType") {}
- IfcActuatorTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcOpenShell
+ struct IfcOpenShell : IfcConnectedFaceSet, ObjectHelper<IfcOpenShell,0> { IfcOpenShell() : Object("IfcOpenShell") {}
- // C++ wrapper for IfcDistributionControlElement
- struct IfcDistributionControlElement : IfcDistributionElement, ObjectHelper<IfcDistributionControlElement,1> { IfcDistributionControlElement() : Object("IfcDistributionControlElement") {}
- Maybe< IfcIdentifier::Out > ControlElementId;
};
- // C++ wrapper for IfcAnnotation
- struct IfcAnnotation : IfcProduct, ObjectHelper<IfcAnnotation,0> { IfcAnnotation() : Object("IfcAnnotation") {}
+ // C++ wrapper for IfcOpeningElement
+ struct IfcOpeningElement : IfcFeatureElementSubtraction, ObjectHelper<IfcOpeningElement,0> { IfcOpeningElement() : Object("IfcOpeningElement") {}
};
- // C++ wrapper for IfcShellBasedSurfaceModel
- struct IfcShellBasedSurfaceModel : IfcGeometricRepresentationItem, ObjectHelper<IfcShellBasedSurfaceModel,1> { IfcShellBasedSurfaceModel() : Object("IfcShellBasedSurfaceModel") {}
- ListOf< IfcShell, 1, 0 >::Out SbsmBoundary;
+ // C++ wrapper for IfcOrderAction
+ struct IfcOrderAction : IfcTask, ObjectHelper<IfcOrderAction,1> { IfcOrderAction() : Object("IfcOrderAction") {}
+ IfcIdentifier::Out ActionID;
};
- // C++ wrapper for IfcActionRequest
- struct IfcActionRequest : IfcControl, ObjectHelper<IfcActionRequest,1> { IfcActionRequest() : Object("IfcActionRequest") {}
- IfcIdentifier::Out RequestID;
+ // C++ wrapper for IfcOrientedEdge
+ struct IfcOrientedEdge : IfcEdge, ObjectHelper<IfcOrientedEdge,2> { IfcOrientedEdge() : Object("IfcOrientedEdge") {}
+ Lazy< IfcEdge > EdgeElement;
+ BOOLEAN::Out Orientation;
};
- // C++ wrapper for IfcExtrudedAreaSolid
- struct IfcExtrudedAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcExtrudedAreaSolid,2> { IfcExtrudedAreaSolid() : Object("IfcExtrudedAreaSolid") {}
- Lazy< IfcDirection > ExtrudedDirection;
- IfcPositiveLengthMeasure::Out Depth;
+ // C++ wrapper for IfcOutletType
+ struct IfcOutletType : IfcFlowTerminalType, ObjectHelper<IfcOutletType,1> { IfcOutletType() : Object("IfcOutletType") {}
+ IfcOutletTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSystem
- struct IfcSystem : IfcGroup, ObjectHelper<IfcSystem,0> { IfcSystem() : Object("IfcSystem") {}
-
+ // C++ wrapper for IfcPath
+ struct IfcPath : IfcTopologicalRepresentationItem, ObjectHelper<IfcPath,1> { IfcPath() : Object("IfcPath") {}
+ ListOf< Lazy< IfcOrientedEdge >, 1, 0 > EdgeList;
};
- // C++ wrapper for IfcFillAreaStyleHatching
- struct IfcFillAreaStyleHatching : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleHatching,5> { IfcFillAreaStyleHatching() : Object("IfcFillAreaStyleHatching") {}
- Lazy< NotImplemented > HatchLineAppearance;
- IfcHatchLineDistanceSelect::Out StartOfNextHatchLine;
- Maybe< Lazy< IfcCartesianPoint > > PointOfReferenceHatchLine;
- Maybe< Lazy< IfcCartesianPoint > > PatternStart;
- IfcPlaneAngleMeasure::Out HatchLineAngle;
+ // C++ wrapper for IfcPerformanceHistory
+ struct IfcPerformanceHistory : IfcControl, ObjectHelper<IfcPerformanceHistory,1> { IfcPerformanceHistory() : Object("IfcPerformanceHistory") {}
+ IfcLabel::Out LifeCyclePhase;
};
- // C++ wrapper for IfcRelVoidsElement
- struct IfcRelVoidsElement : IfcRelConnects, ObjectHelper<IfcRelVoidsElement,2> { IfcRelVoidsElement() : Object("IfcRelVoidsElement") {}
- Lazy< IfcElement > RelatingBuildingElement;
- Lazy< IfcFeatureElementSubtraction > RelatedOpeningElement;
+ // C++ wrapper for IfcPermit
+ struct IfcPermit : IfcControl, ObjectHelper<IfcPermit,1> { IfcPermit() : Object("IfcPermit") {}
+ IfcIdentifier::Out PermitID;
};
- // C++ wrapper for IfcSurfaceCurveSweptAreaSolid
- struct IfcSurfaceCurveSweptAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcSurfaceCurveSweptAreaSolid,4> { IfcSurfaceCurveSweptAreaSolid() : Object("IfcSurfaceCurveSweptAreaSolid") {}
- Lazy< IfcCurve > Directrix;
- IfcParameterValue::Out StartParam;
- IfcParameterValue::Out EndParam;
- Lazy< IfcSurface > ReferenceSurface;
+ // C++ wrapper for IfcPile
+ struct IfcPile : IfcBuildingElement, ObjectHelper<IfcPile,2> { IfcPile() : Object("IfcPile") {}
+ IfcPileTypeEnum::Out PredefinedType;
+ Maybe< IfcPileConstructionEnum::Out > ConstructionType;
};
- // C++ wrapper for IfcCartesianTransformationOperator3DnonUniform
- struct IfcCartesianTransformationOperator3DnonUniform : IfcCartesianTransformationOperator3D, ObjectHelper<IfcCartesianTransformationOperator3DnonUniform,2> { IfcCartesianTransformationOperator3DnonUniform() : Object("IfcCartesianTransformationOperator3DnonUniform") {}
- Maybe< REAL::Out > Scale2;
- Maybe< REAL::Out > Scale3;
+ // C++ wrapper for IfcPipeFittingType
+ struct IfcPipeFittingType : IfcFlowFittingType, ObjectHelper<IfcPipeFittingType,1> { IfcPipeFittingType() : Object("IfcPipeFittingType") {}
+ IfcPipeFittingTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcCurtainWallType
- struct IfcCurtainWallType : IfcBuildingElementType, ObjectHelper<IfcCurtainWallType,1> { IfcCurtainWallType() : Object("IfcCurtainWallType") {}
- IfcCurtainWallTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcPipeSegmentType
+ struct IfcPipeSegmentType : IfcFlowSegmentType, ObjectHelper<IfcPipeSegmentType,1> { IfcPipeSegmentType() : Object("IfcPipeSegmentType") {}
+ IfcPipeSegmentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcEquipmentStandard
- struct IfcEquipmentStandard : IfcControl, ObjectHelper<IfcEquipmentStandard,0> { IfcEquipmentStandard() : Object("IfcEquipmentStandard") {}
+ // C++ wrapper for IfcPlanarExtent
+ struct IfcPlanarExtent : IfcGeometricRepresentationItem, ObjectHelper<IfcPlanarExtent,2> { IfcPlanarExtent() : Object("IfcPlanarExtent") {}
+ IfcLengthMeasure::Out SizeInX;
+ IfcLengthMeasure::Out SizeInY;
+ };
+ // C++ wrapper for IfcPlanarBox
+ struct IfcPlanarBox : IfcPlanarExtent, ObjectHelper<IfcPlanarBox,1> { IfcPlanarBox() : Object("IfcPlanarBox") {}
+ IfcAxis2Placement::Out Placement;
};
- // C++ wrapper for IfcFlowStorageDeviceType
- struct IfcFlowStorageDeviceType : IfcDistributionFlowElementType, ObjectHelper<IfcFlowStorageDeviceType,0> { IfcFlowStorageDeviceType() : Object("IfcFlowStorageDeviceType") {}
+ // C++ wrapper for IfcPlane
+ struct IfcPlane : IfcElementarySurface, ObjectHelper<IfcPlane,0> { IfcPlane() : Object("IfcPlane") {}
};
- // C++ wrapper for IfcDiameterDimension
- struct IfcDiameterDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcDiameterDimension,0> { IfcDiameterDimension() : Object("IfcDiameterDimension") {}
+ // C++ wrapper for IfcPlate
+ struct IfcPlate : IfcBuildingElement, ObjectHelper<IfcPlate,0> { IfcPlate() : Object("IfcPlate") {}
};
- // C++ wrapper for IfcSwitchingDeviceType
- struct IfcSwitchingDeviceType : IfcFlowControllerType, ObjectHelper<IfcSwitchingDeviceType,1> { IfcSwitchingDeviceType() : Object("IfcSwitchingDeviceType") {}
- IfcSwitchingDeviceTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcPlateType
+ struct IfcPlateType : IfcBuildingElementType, ObjectHelper<IfcPlateType,1> { IfcPlateType() : Object("IfcPlateType") {}
+ IfcPlateTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcWindow
- struct IfcWindow : IfcBuildingElement, ObjectHelper<IfcWindow,2> { IfcWindow() : Object("IfcWindow") {}
- Maybe< IfcPositiveLengthMeasure::Out > OverallHeight;
- Maybe< IfcPositiveLengthMeasure::Out > OverallWidth;
+ // C++ wrapper for IfcPointOnCurve
+ struct IfcPointOnCurve : IfcPoint, ObjectHelper<IfcPointOnCurve,2> { IfcPointOnCurve() : Object("IfcPointOnCurve") {}
+ Lazy< IfcCurve > BasisCurve;
+ IfcParameterValue::Out PointParameter;
};
- // C++ wrapper for IfcFlowTreatmentDevice
- struct IfcFlowTreatmentDevice : IfcDistributionFlowElement, ObjectHelper<IfcFlowTreatmentDevice,0> { IfcFlowTreatmentDevice() : Object("IfcFlowTreatmentDevice") {}
-
+ // C++ wrapper for IfcPointOnSurface
+ struct IfcPointOnSurface : IfcPoint, ObjectHelper<IfcPointOnSurface,3> { IfcPointOnSurface() : Object("IfcPointOnSurface") {}
+ Lazy< IfcSurface > BasisSurface;
+ IfcParameterValue::Out PointParameterU;
+ IfcParameterValue::Out PointParameterV;
};
- // C++ wrapper for IfcChillerType
- struct IfcChillerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcChillerType,1> { IfcChillerType() : Object("IfcChillerType") {}
- IfcChillerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcPolyLoop
+ struct IfcPolyLoop : IfcLoop, ObjectHelper<IfcPolyLoop,1> { IfcPolyLoop() : Object("IfcPolyLoop") {}
+ ListOf< Lazy< IfcCartesianPoint >, 3, 0 > Polygon;
};
- // C++ wrapper for IfcRectangleHollowProfileDef
- struct IfcRectangleHollowProfileDef : IfcRectangleProfileDef, ObjectHelper<IfcRectangleHollowProfileDef,3> { IfcRectangleHollowProfileDef() : Object("IfcRectangleHollowProfileDef") {}
- IfcPositiveLengthMeasure::Out WallThickness;
- Maybe< IfcPositiveLengthMeasure::Out > InnerFilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > OuterFilletRadius;
+ // C++ wrapper for IfcPolygonalBoundedHalfSpace
+ struct IfcPolygonalBoundedHalfSpace : IfcHalfSpaceSolid, ObjectHelper<IfcPolygonalBoundedHalfSpace,2> { IfcPolygonalBoundedHalfSpace() : Object("IfcPolygonalBoundedHalfSpace") {}
+ Lazy< IfcAxis2Placement3D > Position;
+ Lazy< IfcBoundedCurve > PolygonalBoundary;
};
- // C++ wrapper for IfcBoxedHalfSpace
- struct IfcBoxedHalfSpace : IfcHalfSpaceSolid, ObjectHelper<IfcBoxedHalfSpace,1> { IfcBoxedHalfSpace() : Object("IfcBoxedHalfSpace") {}
- Lazy< IfcBoundingBox > Enclosure;
+ // C++ wrapper for IfcPolyline
+ struct IfcPolyline : IfcBoundedCurve, ObjectHelper<IfcPolyline,1> { IfcPolyline() : Object("IfcPolyline") {}
+ ListOf< Lazy< IfcCartesianPoint >, 2, 0 > Points;
};
- // C++ wrapper for IfcAxis2Placement2D
- struct IfcAxis2Placement2D : IfcPlacement, ObjectHelper<IfcAxis2Placement2D,1> { IfcAxis2Placement2D() : Object("IfcAxis2Placement2D") {}
- Maybe< Lazy< IfcDirection > > RefDirection;
+ // C++ wrapper for IfcPresentationStyleAssignment
+ struct IfcPresentationStyleAssignment : ObjectHelper<IfcPresentationStyleAssignment,1> { IfcPresentationStyleAssignment() : Object("IfcPresentationStyleAssignment") {}
+ ListOf< IfcPresentationStyleSelect, 1, 0 >::Out Styles;
};
- // C++ wrapper for IfcSpaceProgram
- struct IfcSpaceProgram : IfcControl, ObjectHelper<IfcSpaceProgram,5> { IfcSpaceProgram() : Object("IfcSpaceProgram") {}
- IfcIdentifier::Out SpaceProgramIdentifier;
- Maybe< IfcAreaMeasure::Out > MaxRequiredArea;
- Maybe< IfcAreaMeasure::Out > MinRequiredArea;
- Maybe< Lazy< IfcSpatialStructureElement > > RequestedLocation;
- IfcAreaMeasure::Out StandardRequiredArea;
+ // C++ wrapper for IfcProcedure
+ struct IfcProcedure : IfcProcess, ObjectHelper<IfcProcedure,3> { IfcProcedure() : Object("IfcProcedure") {}
+ IfcIdentifier::Out ProcedureID;
+ IfcProcedureTypeEnum::Out ProcedureType;
+ Maybe< IfcLabel::Out > UserDefinedProcedureType;
};
- // C++ wrapper for IfcPoint
- struct IfcPoint : IfcGeometricRepresentationItem, ObjectHelper<IfcPoint,0> { IfcPoint() : Object("IfcPoint") {}
+ // C++ wrapper for IfcProductDefinitionShape
+ struct IfcProductDefinitionShape : IfcProductRepresentation, ObjectHelper<IfcProductDefinitionShape,0> { IfcProductDefinitionShape() : Object("IfcProductDefinitionShape") {}
};
- // C++ wrapper for IfcCartesianPoint
- struct IfcCartesianPoint : IfcPoint, ObjectHelper<IfcCartesianPoint,1> { IfcCartesianPoint() : Object("IfcCartesianPoint") {}
- ListOf< IfcLengthMeasure, 1, 3 >::Out Coordinates;
+ // C++ wrapper for IfcProject
+ struct IfcProject : IfcObject, ObjectHelper<IfcProject,4> { IfcProject() : Object("IfcProject") {}
+ Maybe< IfcLabel::Out > LongName;
+ Maybe< IfcLabel::Out > Phase;
+ ListOf< Lazy< IfcRepresentationContext >, 1, 0 > RepresentationContexts;
+ Lazy< IfcUnitAssignment > UnitsInContext;
};
- // C++ wrapper for IfcBoundedSurface
- struct IfcBoundedSurface : IfcSurface, ObjectHelper<IfcBoundedSurface,0> { IfcBoundedSurface() : Object("IfcBoundedSurface") {}
+ // C++ wrapper for IfcProjectOrder
+ struct IfcProjectOrder : IfcControl, ObjectHelper<IfcProjectOrder,3> { IfcProjectOrder() : Object("IfcProjectOrder") {}
+ IfcIdentifier::Out ID;
+ IfcProjectOrderTypeEnum::Out PredefinedType;
+ Maybe< IfcLabel::Out > Status;
+ };
+ // C++ wrapper for IfcProjectOrderRecord
+ struct IfcProjectOrderRecord : IfcControl, ObjectHelper<IfcProjectOrderRecord,2> { IfcProjectOrderRecord() : Object("IfcProjectOrderRecord") {}
+ ListOf< Lazy< NotImplemented >, 1, 0 > Records;
+ IfcProjectOrderRecordTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcLoop
- struct IfcLoop : IfcTopologicalRepresentationItem, ObjectHelper<IfcLoop,0> { IfcLoop() : Object("IfcLoop") {}
+ // C++ wrapper for IfcProjectionCurve
+ struct IfcProjectionCurve : IfcAnnotationCurveOccurrence, ObjectHelper<IfcProjectionCurve,0> { IfcProjectionCurve() : Object("IfcProjectionCurve") {}
};
- // C++ wrapper for IfcPolyLoop
- struct IfcPolyLoop : IfcLoop, ObjectHelper<IfcPolyLoop,1> { IfcPolyLoop() : Object("IfcPolyLoop") {}
- ListOf< Lazy< IfcCartesianPoint >, 3, 0 > Polygon;
- };
+ // C++ wrapper for IfcProjectionElement
+ struct IfcProjectionElement : IfcFeatureElementAddition, ObjectHelper<IfcProjectionElement,0> { IfcProjectionElement() : Object("IfcProjectionElement") {}
- // C++ wrapper for IfcTerminatorSymbol
- struct IfcTerminatorSymbol : IfcAnnotationSymbolOccurrence, ObjectHelper<IfcTerminatorSymbol,1> { IfcTerminatorSymbol() : Object("IfcTerminatorSymbol") {}
- Lazy< IfcAnnotationCurveOccurrence > AnnotatedCurve;
};
- // C++ wrapper for IfcDimensionCurveTerminator
- struct IfcDimensionCurveTerminator : IfcTerminatorSymbol, ObjectHelper<IfcDimensionCurveTerminator,1> { IfcDimensionCurveTerminator() : Object("IfcDimensionCurveTerminator") {}
- IfcDimensionExtentUsage::Out Role;
- };
+ // C++ wrapper for IfcSimpleProperty
+ struct IfcSimpleProperty : IfcProperty, ObjectHelper<IfcSimpleProperty,0> { IfcSimpleProperty() : Object("IfcSimpleProperty") {}
- // C++ wrapper for IfcTrapeziumProfileDef
- struct IfcTrapeziumProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcTrapeziumProfileDef,4> { IfcTrapeziumProfileDef() : Object("IfcTrapeziumProfileDef") {}
- IfcPositiveLengthMeasure::Out BottomXDim;
- IfcPositiveLengthMeasure::Out TopXDim;
- IfcPositiveLengthMeasure::Out YDim;
- IfcLengthMeasure::Out TopXOffset;
};
- // C++ wrapper for IfcRepresentationContext
- struct IfcRepresentationContext : ObjectHelper<IfcRepresentationContext,2> { IfcRepresentationContext() : Object("IfcRepresentationContext") {}
- Maybe< IfcLabel::Out > ContextIdentifier;
- Maybe< IfcLabel::Out > ContextType;
+ // C++ wrapper for IfcPropertyBoundedValue
+ struct IfcPropertyBoundedValue : IfcSimpleProperty, ObjectHelper<IfcPropertyBoundedValue,3> { IfcPropertyBoundedValue() : Object("IfcPropertyBoundedValue") {}
+ Maybe< IfcValue::Out > UpperBoundValue;
+ Maybe< IfcValue::Out > LowerBoundValue;
+ Maybe< IfcUnit::Out > Unit;
};
- // C++ wrapper for IfcGeometricRepresentationContext
- struct IfcGeometricRepresentationContext : IfcRepresentationContext, ObjectHelper<IfcGeometricRepresentationContext,4> { IfcGeometricRepresentationContext() : Object("IfcGeometricRepresentationContext") {}
- IfcDimensionCount::Out CoordinateSpaceDimension;
- Maybe< REAL::Out > Precision;
- IfcAxis2Placement::Out WorldCoordinateSystem;
- Maybe< Lazy< IfcDirection > > TrueNorth;
+ // C++ wrapper for IfcPropertyEnumeratedValue
+ struct IfcPropertyEnumeratedValue : IfcSimpleProperty, ObjectHelper<IfcPropertyEnumeratedValue,2> { IfcPropertyEnumeratedValue() : Object("IfcPropertyEnumeratedValue") {}
+ ListOf< IfcValue, 1, 0 >::Out EnumerationValues;
+ Maybe< Lazy< NotImplemented > > EnumerationReference;
};
- // C++ wrapper for IfcCurveBoundedPlane
- struct IfcCurveBoundedPlane : IfcBoundedSurface, ObjectHelper<IfcCurveBoundedPlane,3> { IfcCurveBoundedPlane() : Object("IfcCurveBoundedPlane") {}
- Lazy< IfcPlane > BasisSurface;
- Lazy< IfcCurve > OuterBoundary;
- ListOf< Lazy< IfcCurve >, 0, 0 > InnerBoundaries;
+ // C++ wrapper for IfcPropertyListValue
+ struct IfcPropertyListValue : IfcSimpleProperty, ObjectHelper<IfcPropertyListValue,2> { IfcPropertyListValue() : Object("IfcPropertyListValue") {}
+ ListOf< IfcValue, 1, 0 >::Out ListValues;
+ Maybe< IfcUnit::Out > Unit;
};
- // C++ wrapper for IfcSIUnit
- struct IfcSIUnit : IfcNamedUnit, ObjectHelper<IfcSIUnit,2> { IfcSIUnit() : Object("IfcSIUnit") {}
- Maybe< IfcSIPrefix::Out > Prefix;
- IfcSIUnitName::Out Name;
+ // C++ wrapper for IfcPropertyReferenceValue
+ struct IfcPropertyReferenceValue : IfcSimpleProperty, ObjectHelper<IfcPropertyReferenceValue,2> { IfcPropertyReferenceValue() : Object("IfcPropertyReferenceValue") {}
+ Maybe< IfcLabel::Out > UsageName;
+ IfcObjectReferenceSelect::Out PropertyReference;
};
- // C++ wrapper for IfcStructuralReaction
- struct IfcStructuralReaction : IfcStructuralActivity, ObjectHelper<IfcStructuralReaction,0> { IfcStructuralReaction() : Object("IfcStructuralReaction") {}
-
+ // C++ wrapper for IfcPropertySet
+ struct IfcPropertySet : IfcPropertySetDefinition, ObjectHelper<IfcPropertySet,1> { IfcPropertySet() : Object("IfcPropertySet") {}
+ ListOf< Lazy< IfcProperty >, 1, 0 > HasProperties;
};
- // C++ wrapper for IfcStructuralPointReaction
- struct IfcStructuralPointReaction : IfcStructuralReaction, ObjectHelper<IfcStructuralPointReaction,0> { IfcStructuralPointReaction() : Object("IfcStructuralPointReaction") {}
-
+ // C++ wrapper for IfcPropertySingleValue
+ struct IfcPropertySingleValue : IfcSimpleProperty, ObjectHelper<IfcPropertySingleValue,2> { IfcPropertySingleValue() : Object("IfcPropertySingleValue") {}
+ Maybe< IfcValue::Out > NominalValue;
+ Maybe< IfcUnit::Out > Unit;
};
- // C++ wrapper for IfcAxis1Placement
- struct IfcAxis1Placement : IfcPlacement, ObjectHelper<IfcAxis1Placement,1> { IfcAxis1Placement() : Object("IfcAxis1Placement") {}
- Maybe< Lazy< IfcDirection > > Axis;
+ // C++ wrapper for IfcPropertyTableValue
+ struct IfcPropertyTableValue : IfcSimpleProperty, ObjectHelper<IfcPropertyTableValue,5> { IfcPropertyTableValue() : Object("IfcPropertyTableValue") {}
+ ListOf< IfcValue, 1, 0 >::Out DefiningValues;
+ ListOf< IfcValue, 1, 0 >::Out DefinedValues;
+ Maybe< IfcText::Out > Expression;
+ Maybe< IfcUnit::Out > DefiningUnit;
+ Maybe< IfcUnit::Out > DefinedUnit;
};
- // C++ wrapper for IfcElectricApplianceType
- struct IfcElectricApplianceType : IfcFlowTerminalType, ObjectHelper<IfcElectricApplianceType,1> { IfcElectricApplianceType() : Object("IfcElectricApplianceType") {}
- IfcElectricApplianceTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcProtectiveDeviceType
+ struct IfcProtectiveDeviceType : IfcFlowControllerType, ObjectHelper<IfcProtectiveDeviceType,1> { IfcProtectiveDeviceType() : Object("IfcProtectiveDeviceType") {}
+ IfcProtectiveDeviceTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSensorType
- struct IfcSensorType : IfcDistributionControlElementType, ObjectHelper<IfcSensorType,1> { IfcSensorType() : Object("IfcSensorType") {}
- IfcSensorTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcProxy
+ struct IfcProxy : IfcProduct, ObjectHelper<IfcProxy,2> { IfcProxy() : Object("IfcProxy") {}
+ IfcObjectTypeEnum::Out ProxyType;
+ Maybe< IfcLabel::Out > Tag;
};
- // C++ wrapper for IfcFurnishingElement
- struct IfcFurnishingElement : IfcElement, ObjectHelper<IfcFurnishingElement,0> { IfcFurnishingElement() : Object("IfcFurnishingElement") {}
-
+ // C++ wrapper for IfcPumpType
+ struct IfcPumpType : IfcFlowMovingDeviceType, ObjectHelper<IfcPumpType,1> { IfcPumpType() : Object("IfcPumpType") {}
+ IfcPumpTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcProtectiveDeviceType
- struct IfcProtectiveDeviceType : IfcFlowControllerType, ObjectHelper<IfcProtectiveDeviceType,1> { IfcProtectiveDeviceType() : Object("IfcProtectiveDeviceType") {}
- IfcProtectiveDeviceTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcRadiusDimension
+ struct IfcRadiusDimension : IfcDimensionCurveDirectedCallout, ObjectHelper<IfcRadiusDimension,0> { IfcRadiusDimension() : Object("IfcRadiusDimension") {}
- // C++ wrapper for IfcZShapeProfileDef
- struct IfcZShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcZShapeProfileDef,6> { IfcZShapeProfileDef() : Object("IfcZShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out Depth;
- IfcPositiveLengthMeasure::Out FlangeWidth;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out FlangeThickness;
- Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
};
- // C++ wrapper for IfcScheduleTimeControl
- struct IfcScheduleTimeControl : IfcControl, ObjectHelper<IfcScheduleTimeControl,18> { IfcScheduleTimeControl() : Object("IfcScheduleTimeControl") {}
- Maybe< IfcDateTimeSelect::Out > ActualStart;
- Maybe< IfcDateTimeSelect::Out > EarlyStart;
- Maybe< IfcDateTimeSelect::Out > LateStart;
- Maybe< IfcDateTimeSelect::Out > ScheduleStart;
- Maybe< IfcDateTimeSelect::Out > ActualFinish;
- Maybe< IfcDateTimeSelect::Out > EarlyFinish;
- Maybe< IfcDateTimeSelect::Out > LateFinish;
- Maybe< IfcDateTimeSelect::Out > ScheduleFinish;
- Maybe< IfcTimeMeasure::Out > ScheduleDuration;
- Maybe< IfcTimeMeasure::Out > ActualDuration;
- Maybe< IfcTimeMeasure::Out > RemainingTime;
- Maybe< IfcTimeMeasure::Out > FreeFloat;
- Maybe< IfcTimeMeasure::Out > TotalFloat;
- Maybe< BOOLEAN::Out > IsCritical;
- Maybe< IfcDateTimeSelect::Out > StatusTime;
- Maybe< IfcTimeMeasure::Out > StartFloat;
- Maybe< IfcTimeMeasure::Out > FinishFloat;
- Maybe< IfcPositiveRatioMeasure::Out > Completion;
+ // C++ wrapper for IfcRailing
+ struct IfcRailing : IfcBuildingElement, ObjectHelper<IfcRailing,1> { IfcRailing() : Object("IfcRailing") {}
+ Maybe< IfcRailingTypeEnum::Out > PredefinedType;
};
- // C++ wrapper for IfcRepresentationMap
- struct IfcRepresentationMap : ObjectHelper<IfcRepresentationMap,2> { IfcRepresentationMap() : Object("IfcRepresentationMap") {}
- IfcAxis2Placement::Out MappingOrigin;
- Lazy< IfcRepresentation > MappedRepresentation;
+ // C++ wrapper for IfcRailingType
+ struct IfcRailingType : IfcBuildingElementType, ObjectHelper<IfcRailingType,1> { IfcRailingType() : Object("IfcRailingType") {}
+ IfcRailingTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcClosedShell
- struct IfcClosedShell : IfcConnectedFaceSet, ObjectHelper<IfcClosedShell,0> { IfcClosedShell() : Object("IfcClosedShell") {}
-
+ // C++ wrapper for IfcRamp
+ struct IfcRamp : IfcBuildingElement, ObjectHelper<IfcRamp,1> { IfcRamp() : Object("IfcRamp") {}
+ IfcRampTypeEnum::Out ShapeType;
};
- // C++ wrapper for IfcBuildingElementPart
- struct IfcBuildingElementPart : IfcBuildingElementComponent, ObjectHelper<IfcBuildingElementPart,0> { IfcBuildingElementPart() : Object("IfcBuildingElementPart") {}
+ // C++ wrapper for IfcRampFlight
+ struct IfcRampFlight : IfcBuildingElement, ObjectHelper<IfcRampFlight,0> { IfcRampFlight() : Object("IfcRampFlight") {}
};
- // C++ wrapper for IfcBlock
- struct IfcBlock : IfcCsgPrimitive3D, ObjectHelper<IfcBlock,3> { IfcBlock() : Object("IfcBlock") {}
- IfcPositiveLengthMeasure::Out XLength;
- IfcPositiveLengthMeasure::Out YLength;
- IfcPositiveLengthMeasure::Out ZLength;
+ // C++ wrapper for IfcRampFlightType
+ struct IfcRampFlightType : IfcBuildingElementType, ObjectHelper<IfcRampFlightType,1> { IfcRampFlightType() : Object("IfcRampFlightType") {}
+ IfcRampFlightTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcLightFixtureType
- struct IfcLightFixtureType : IfcFlowTerminalType, ObjectHelper<IfcLightFixtureType,1> { IfcLightFixtureType() : Object("IfcLightFixtureType") {}
- IfcLightFixtureTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRationalBezierCurve
+ struct IfcRationalBezierCurve : IfcBezierCurve, ObjectHelper<IfcRationalBezierCurve,1> { IfcRationalBezierCurve() : Object("IfcRationalBezierCurve") {}
+ ListOf< REAL, 2, 0 >::Out WeightsData;
};
- // C++ wrapper for IfcOpeningElement
- struct IfcOpeningElement : IfcFeatureElementSubtraction, ObjectHelper<IfcOpeningElement,0> { IfcOpeningElement() : Object("IfcOpeningElement") {}
-
+ // C++ wrapper for IfcRectangleProfileDef
+ struct IfcRectangleProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcRectangleProfileDef,2> { IfcRectangleProfileDef() : Object("IfcRectangleProfileDef") {}
+ IfcPositiveLengthMeasure::Out XDim;
+ IfcPositiveLengthMeasure::Out YDim;
};
- // C++ wrapper for IfcLightSourceSpot
- struct IfcLightSourceSpot : IfcLightSourcePositional, ObjectHelper<IfcLightSourceSpot,4> { IfcLightSourceSpot() : Object("IfcLightSourceSpot") {}
- Lazy< IfcDirection > Orientation;
- Maybe< IfcReal::Out > ConcentrationExponent;
- IfcPositivePlaneAngleMeasure::Out SpreadAngle;
- IfcPositivePlaneAngleMeasure::Out BeamWidthAngle;
+ // C++ wrapper for IfcRectangleHollowProfileDef
+ struct IfcRectangleHollowProfileDef : IfcRectangleProfileDef, ObjectHelper<IfcRectangleHollowProfileDef,3> { IfcRectangleHollowProfileDef() : Object("IfcRectangleHollowProfileDef") {}
+ IfcPositiveLengthMeasure::Out WallThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > InnerFilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > OuterFilletRadius;
};
- // C++ wrapper for IfcTendonAnchor
- struct IfcTendonAnchor : IfcReinforcingElement, ObjectHelper<IfcTendonAnchor,0> { IfcTendonAnchor() : Object("IfcTendonAnchor") {}
-
+ // C++ wrapper for IfcRectangularPyramid
+ struct IfcRectangularPyramid : IfcCsgPrimitive3D, ObjectHelper<IfcRectangularPyramid,3> { IfcRectangularPyramid() : Object("IfcRectangularPyramid") {}
+ IfcPositiveLengthMeasure::Out XLength;
+ IfcPositiveLengthMeasure::Out YLength;
+ IfcPositiveLengthMeasure::Out Height;
};
- // C++ wrapper for IfcElectricFlowStorageDeviceType
- struct IfcElectricFlowStorageDeviceType : IfcFlowStorageDeviceType, ObjectHelper<IfcElectricFlowStorageDeviceType,1> { IfcElectricFlowStorageDeviceType() : Object("IfcElectricFlowStorageDeviceType") {}
- IfcElectricFlowStorageDeviceTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRectangularTrimmedSurface
+ struct IfcRectangularTrimmedSurface : IfcBoundedSurface, ObjectHelper<IfcRectangularTrimmedSurface,7> { IfcRectangularTrimmedSurface() : Object("IfcRectangularTrimmedSurface") {}
+ Lazy< IfcSurface > BasisSurface;
+ IfcParameterValue::Out U1;
+ IfcParameterValue::Out V1;
+ IfcParameterValue::Out U2;
+ IfcParameterValue::Out V2;
+ BOOLEAN::Out Usense;
+ BOOLEAN::Out Vsense;
};
- // C++ wrapper for IfcSphere
- struct IfcSphere : IfcCsgPrimitive3D, ObjectHelper<IfcSphere,1> { IfcSphere() : Object("IfcSphere") {}
- IfcPositiveLengthMeasure::Out Radius;
+ // C++ wrapper for IfcReinforcingElement
+ struct IfcReinforcingElement : IfcBuildingElementComponent, ObjectHelper<IfcReinforcingElement,1> { IfcReinforcingElement() : Object("IfcReinforcingElement") {}
+ Maybe< IfcLabel::Out > SteelGrade;
};
- // C++ wrapper for IfcDamperType
- struct IfcDamperType : IfcFlowControllerType, ObjectHelper<IfcDamperType,1> { IfcDamperType() : Object("IfcDamperType") {}
- IfcDamperTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcReinforcingBar
+ struct IfcReinforcingBar : IfcReinforcingElement, ObjectHelper<IfcReinforcingBar,5> { IfcReinforcingBar() : Object("IfcReinforcingBar") {}
+ IfcPositiveLengthMeasure::Out NominalDiameter;
+ IfcAreaMeasure::Out CrossSectionArea;
+ Maybe< IfcPositiveLengthMeasure::Out > BarLength;
+ IfcReinforcingBarRoleEnum::Out BarRole;
+ Maybe< IfcReinforcingBarSurfaceEnum::Out > BarSurface;
};
- // C++ wrapper for IfcProjectOrderRecord
- struct IfcProjectOrderRecord : IfcControl, ObjectHelper<IfcProjectOrderRecord,2> { IfcProjectOrderRecord() : Object("IfcProjectOrderRecord") {}
- ListOf< Lazy< NotImplemented >, 1, 0 > Records;
- IfcProjectOrderRecordTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcReinforcingMesh
+ struct IfcReinforcingMesh : IfcReinforcingElement, ObjectHelper<IfcReinforcingMesh,8> { IfcReinforcingMesh() : Object("IfcReinforcingMesh") {}
+ Maybe< IfcPositiveLengthMeasure::Out > MeshLength;
+ Maybe< IfcPositiveLengthMeasure::Out > MeshWidth;
+ IfcPositiveLengthMeasure::Out LongitudinalBarNominalDiameter;
+ IfcPositiveLengthMeasure::Out TransverseBarNominalDiameter;
+ IfcAreaMeasure::Out LongitudinalBarCrossSectionArea;
+ IfcAreaMeasure::Out TransverseBarCrossSectionArea;
+ IfcPositiveLengthMeasure::Out LongitudinalBarSpacing;
+ IfcPositiveLengthMeasure::Out TransverseBarSpacing;
};
- // C++ wrapper for IfcDistributionChamberElement
- struct IfcDistributionChamberElement : IfcDistributionFlowElement, ObjectHelper<IfcDistributionChamberElement,0> { IfcDistributionChamberElement() : Object("IfcDistributionChamberElement") {}
+ // C++ wrapper for IfcRelationship
+ struct IfcRelationship : IfcRoot, ObjectHelper<IfcRelationship,0> { IfcRelationship() : Object("IfcRelationship") {}
};
- // C++ wrapper for IfcMechanicalFastener
- struct IfcMechanicalFastener : IfcFastener, ObjectHelper<IfcMechanicalFastener,2> { IfcMechanicalFastener() : Object("IfcMechanicalFastener") {}
- Maybe< IfcPositiveLengthMeasure::Out > NominalDiameter;
- Maybe< IfcPositiveLengthMeasure::Out > NominalLength;
+ // C++ wrapper for IfcRelDecomposes
+ struct IfcRelDecomposes : IfcRelationship, ObjectHelper<IfcRelDecomposes,2> { IfcRelDecomposes() : Object("IfcRelDecomposes") {}
+ Lazy< IfcObjectDefinition > RelatingObject;
+ ListOf< Lazy< IfcObjectDefinition >, 1, 0 > RelatedObjects;
};
- // C++ wrapper for IfcRectangularTrimmedSurface
- struct IfcRectangularTrimmedSurface : IfcBoundedSurface, ObjectHelper<IfcRectangularTrimmedSurface,7> { IfcRectangularTrimmedSurface() : Object("IfcRectangularTrimmedSurface") {}
- Lazy< IfcSurface > BasisSurface;
- IfcParameterValue::Out U1;
- IfcParameterValue::Out V1;
- IfcParameterValue::Out U2;
- IfcParameterValue::Out V2;
- BOOLEAN::Out Usense;
- BOOLEAN::Out Vsense;
+ // C++ wrapper for IfcRelAggregates
+ struct IfcRelAggregates : IfcRelDecomposes, ObjectHelper<IfcRelAggregates,0> { IfcRelAggregates() : Object("IfcRelAggregates") {}
+
};
- // C++ wrapper for IfcZone
- struct IfcZone : IfcGroup, ObjectHelper<IfcZone,0> { IfcZone() : Object("IfcZone") {}
+ // C++ wrapper for IfcRelConnects
+ struct IfcRelConnects : IfcRelationship, ObjectHelper<IfcRelConnects,0> { IfcRelConnects() : Object("IfcRelConnects") {}
};
- // C++ wrapper for IfcFanType
- struct IfcFanType : IfcFlowMovingDeviceType, ObjectHelper<IfcFanType,1> { IfcFanType() : Object("IfcFanType") {}
- IfcFanTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRelContainedInSpatialStructure
+ struct IfcRelContainedInSpatialStructure : IfcRelConnects, ObjectHelper<IfcRelContainedInSpatialStructure,2> { IfcRelContainedInSpatialStructure() : Object("IfcRelContainedInSpatialStructure") {}
+ ListOf< Lazy< IfcProduct >, 1, 0 > RelatedElements;
+ Lazy< IfcSpatialStructureElement > RelatingStructure;
};
- // C++ wrapper for IfcGeometricSet
- struct IfcGeometricSet : IfcGeometricRepresentationItem, ObjectHelper<IfcGeometricSet,1> { IfcGeometricSet() : Object("IfcGeometricSet") {}
- ListOf< IfcGeometricSetSelect, 1, 0 >::Out Elements;
+ // C++ wrapper for IfcRelDefines
+ struct IfcRelDefines : IfcRelationship, ObjectHelper<IfcRelDefines,1> { IfcRelDefines() : Object("IfcRelDefines") {}
+ ListOf< Lazy< IfcObject >, 1, 0 > RelatedObjects;
};
- // C++ wrapper for IfcFillAreaStyleTiles
- struct IfcFillAreaStyleTiles : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleTiles,3> { IfcFillAreaStyleTiles() : Object("IfcFillAreaStyleTiles") {}
- Lazy< IfcOneDirectionRepeatFactor > TilingPattern;
- ListOf< IfcFillAreaStyleTileShapeSelect, 1, 0 >::Out Tiles;
- IfcPositiveRatioMeasure::Out TilingScale;
+ // C++ wrapper for IfcRelDefinesByProperties
+ struct IfcRelDefinesByProperties : IfcRelDefines, ObjectHelper<IfcRelDefinesByProperties,1> { IfcRelDefinesByProperties() : Object("IfcRelDefinesByProperties") {}
+ Lazy< IfcPropertySetDefinition > RelatingPropertyDefinition;
};
- // C++ wrapper for IfcCableSegmentType
- struct IfcCableSegmentType : IfcFlowSegmentType, ObjectHelper<IfcCableSegmentType,1> { IfcCableSegmentType() : Object("IfcCableSegmentType") {}
- IfcCableSegmentTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRelFillsElement
+ struct IfcRelFillsElement : IfcRelConnects, ObjectHelper<IfcRelFillsElement,2> { IfcRelFillsElement() : Object("IfcRelFillsElement") {}
+ Lazy< IfcOpeningElement > RelatingOpeningElement;
+ Lazy< IfcElement > RelatedBuildingElement;
};
// C++ wrapper for IfcRelOverridesProperties
struct IfcRelOverridesProperties : IfcRelDefinesByProperties, ObjectHelper<IfcRelOverridesProperties,1> { IfcRelOverridesProperties() : Object("IfcRelOverridesProperties") {}
- ListOf< Lazy< IfcProperty >, 1, 0 > OverridingProperties;
- };
-
- // C++ wrapper for IfcMeasureWithUnit
- struct IfcMeasureWithUnit : ObjectHelper<IfcMeasureWithUnit,2> { IfcMeasureWithUnit() : Object("IfcMeasureWithUnit") {}
- IfcValue::Out ValueComponent;
- IfcUnit::Out UnitComponent;
+ ListOf< Lazy< IfcProperty >, 1, 0 > OverridingProperties;
};
- // C++ wrapper for IfcSlabType
- struct IfcSlabType : IfcBuildingElementType, ObjectHelper<IfcSlabType,1> { IfcSlabType() : Object("IfcSlabType") {}
- IfcSlabTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRelVoidsElement
+ struct IfcRelVoidsElement : IfcRelConnects, ObjectHelper<IfcRelVoidsElement,2> { IfcRelVoidsElement() : Object("IfcRelVoidsElement") {}
+ Lazy< IfcElement > RelatingBuildingElement;
+ Lazy< IfcFeatureElementSubtraction > RelatedOpeningElement;
};
- // C++ wrapper for IfcServiceLife
- struct IfcServiceLife : IfcControl, ObjectHelper<IfcServiceLife,2> { IfcServiceLife() : Object("IfcServiceLife") {}
- IfcServiceLifeTypeEnum::Out ServiceLifeType;
- IfcTimeMeasure::Out ServiceLifeDuration;
+ // C++ wrapper for IfcRepresentation
+ struct IfcRepresentation : ObjectHelper<IfcRepresentation,4> { IfcRepresentation() : Object("IfcRepresentation") {}
+ Lazy< IfcRepresentationContext > ContextOfItems;
+ Maybe< IfcLabel::Out > RepresentationIdentifier;
+ Maybe< IfcLabel::Out > RepresentationType;
+ ListOf< Lazy< IfcRepresentationItem >, 1, 0 > Items;
};
- // C++ wrapper for IfcFurnitureType
- struct IfcFurnitureType : IfcFurnishingElementType, ObjectHelper<IfcFurnitureType,1> { IfcFurnitureType() : Object("IfcFurnitureType") {}
- IfcAssemblyPlaceEnum::Out AssemblyPlace;
+ // C++ wrapper for IfcRepresentationMap
+ struct IfcRepresentationMap : ObjectHelper<IfcRepresentationMap,2> { IfcRepresentationMap() : Object("IfcRepresentationMap") {}
+ IfcAxis2Placement::Out MappingOrigin;
+ Lazy< IfcRepresentation > MappedRepresentation;
};
- // C++ wrapper for IfcCostItem
- struct IfcCostItem : IfcControl, ObjectHelper<IfcCostItem,0> { IfcCostItem() : Object("IfcCostItem") {}
-
+ // C++ wrapper for IfcRevolvedAreaSolid
+ struct IfcRevolvedAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcRevolvedAreaSolid,2> { IfcRevolvedAreaSolid() : Object("IfcRevolvedAreaSolid") {}
+ Lazy< IfcAxis1Placement > Axis;
+ IfcPlaneAngleMeasure::Out Angle;
};
- // C++ wrapper for IfcReinforcingMesh
- struct IfcReinforcingMesh : IfcReinforcingElement, ObjectHelper<IfcReinforcingMesh,8> { IfcReinforcingMesh() : Object("IfcReinforcingMesh") {}
- Maybe< IfcPositiveLengthMeasure::Out > MeshLength;
- Maybe< IfcPositiveLengthMeasure::Out > MeshWidth;
- IfcPositiveLengthMeasure::Out LongitudinalBarNominalDiameter;
- IfcPositiveLengthMeasure::Out TransverseBarNominalDiameter;
- IfcAreaMeasure::Out LongitudinalBarCrossSectionArea;
- IfcAreaMeasure::Out TransverseBarCrossSectionArea;
- IfcPositiveLengthMeasure::Out LongitudinalBarSpacing;
- IfcPositiveLengthMeasure::Out TransverseBarSpacing;
+ // C++ wrapper for IfcRightCircularCone
+ struct IfcRightCircularCone : IfcCsgPrimitive3D, ObjectHelper<IfcRightCircularCone,2> { IfcRightCircularCone() : Object("IfcRightCircularCone") {}
+ IfcPositiveLengthMeasure::Out Height;
+ IfcPositiveLengthMeasure::Out BottomRadius;
};
- // C++ wrapper for IfcFacetedBrepWithVoids
- struct IfcFacetedBrepWithVoids : IfcManifoldSolidBrep, ObjectHelper<IfcFacetedBrepWithVoids,1> { IfcFacetedBrepWithVoids() : Object("IfcFacetedBrepWithVoids") {}
- ListOf< Lazy< IfcClosedShell >, 1, 0 > Voids;
+ // C++ wrapper for IfcRightCircularCylinder
+ struct IfcRightCircularCylinder : IfcCsgPrimitive3D, ObjectHelper<IfcRightCircularCylinder,2> { IfcRightCircularCylinder() : Object("IfcRightCircularCylinder") {}
+ IfcPositiveLengthMeasure::Out Height;
+ IfcPositiveLengthMeasure::Out Radius;
};
- // C++ wrapper for IfcGasTerminalType
- struct IfcGasTerminalType : IfcFlowTerminalType, ObjectHelper<IfcGasTerminalType,1> { IfcGasTerminalType() : Object("IfcGasTerminalType") {}
- IfcGasTerminalTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcRoof
+ struct IfcRoof : IfcBuildingElement, ObjectHelper<IfcRoof,1> { IfcRoof() : Object("IfcRoof") {}
+ IfcRoofTypeEnum::Out ShapeType;
};
- // C++ wrapper for IfcPile
- struct IfcPile : IfcBuildingElement, ObjectHelper<IfcPile,2> { IfcPile() : Object("IfcPile") {}
- IfcPileTypeEnum::Out PredefinedType;
- Maybe< IfcPileConstructionEnum::Out > ConstructionType;
+ // C++ wrapper for IfcRoundedEdgeFeature
+ struct IfcRoundedEdgeFeature : IfcEdgeFeature, ObjectHelper<IfcRoundedEdgeFeature,1> { IfcRoundedEdgeFeature() : Object("IfcRoundedEdgeFeature") {}
+ Maybe< IfcPositiveLengthMeasure::Out > Radius;
};
- // C++ wrapper for IfcFillAreaStyleTileSymbolWithStyle
- struct IfcFillAreaStyleTileSymbolWithStyle : IfcGeometricRepresentationItem, ObjectHelper<IfcFillAreaStyleTileSymbolWithStyle,1> { IfcFillAreaStyleTileSymbolWithStyle() : Object("IfcFillAreaStyleTileSymbolWithStyle") {}
- Lazy< IfcAnnotationSymbolOccurrence > Symbol;
+ // C++ wrapper for IfcRoundedRectangleProfileDef
+ struct IfcRoundedRectangleProfileDef : IfcRectangleProfileDef, ObjectHelper<IfcRoundedRectangleProfileDef,1> { IfcRoundedRectangleProfileDef() : Object("IfcRoundedRectangleProfileDef") {}
+ IfcPositiveLengthMeasure::Out RoundingRadius;
};
- // C++ wrapper for IfcConstructionMaterialResource
- struct IfcConstructionMaterialResource : IfcConstructionResource, ObjectHelper<IfcConstructionMaterialResource,2> { IfcConstructionMaterialResource() : Object("IfcConstructionMaterialResource") {}
- Maybe< ListOf< IfcActorSelect, 1, 0 >::Out > Suppliers;
- Maybe< IfcRatioMeasure::Out > UsageRatio;
+ // C++ wrapper for IfcSIUnit
+ struct IfcSIUnit : IfcNamedUnit, ObjectHelper<IfcSIUnit,2> { IfcSIUnit() : Object("IfcSIUnit") {}
+ Maybe< IfcSIPrefix::Out > Prefix;
+ IfcSIUnitName::Out Name;
};
- // C++ wrapper for IfcAnnotationCurveOccurrence
- struct IfcAnnotationCurveOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationCurveOccurrence,0> { IfcAnnotationCurveOccurrence() : Object("IfcAnnotationCurveOccurrence") {}
-
+ // C++ wrapper for IfcSanitaryTerminalType
+ struct IfcSanitaryTerminalType : IfcFlowTerminalType, ObjectHelper<IfcSanitaryTerminalType,1> { IfcSanitaryTerminalType() : Object("IfcSanitaryTerminalType") {}
+ IfcSanitaryTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcDimensionCurve
- struct IfcDimensionCurve : IfcAnnotationCurveOccurrence, ObjectHelper<IfcDimensionCurve,0> { IfcDimensionCurve() : Object("IfcDimensionCurve") {}
-
+ // C++ wrapper for IfcScheduleTimeControl
+ struct IfcScheduleTimeControl : IfcControl, ObjectHelper<IfcScheduleTimeControl,18> { IfcScheduleTimeControl() : Object("IfcScheduleTimeControl") {}
+ Maybe< IfcDateTimeSelect::Out > ActualStart;
+ Maybe< IfcDateTimeSelect::Out > EarlyStart;
+ Maybe< IfcDateTimeSelect::Out > LateStart;
+ Maybe< IfcDateTimeSelect::Out > ScheduleStart;
+ Maybe< IfcDateTimeSelect::Out > ActualFinish;
+ Maybe< IfcDateTimeSelect::Out > EarlyFinish;
+ Maybe< IfcDateTimeSelect::Out > LateFinish;
+ Maybe< IfcDateTimeSelect::Out > ScheduleFinish;
+ Maybe< IfcTimeMeasure::Out > ScheduleDuration;
+ Maybe< IfcTimeMeasure::Out > ActualDuration;
+ Maybe< IfcTimeMeasure::Out > RemainingTime;
+ Maybe< IfcTimeMeasure::Out > FreeFloat;
+ Maybe< IfcTimeMeasure::Out > TotalFloat;
+ Maybe< BOOLEAN::Out > IsCritical;
+ Maybe< IfcDateTimeSelect::Out > StatusTime;
+ Maybe< IfcTimeMeasure::Out > StartFloat;
+ Maybe< IfcTimeMeasure::Out > FinishFloat;
+ Maybe< IfcPositiveRatioMeasure::Out > Completion;
};
- // C++ wrapper for IfcGeometricCurveSet
- struct IfcGeometricCurveSet : IfcGeometricSet, ObjectHelper<IfcGeometricCurveSet,0> { IfcGeometricCurveSet() : Object("IfcGeometricCurveSet") {}
-
+ // C++ wrapper for IfcSectionedSpine
+ struct IfcSectionedSpine : IfcGeometricRepresentationItem, ObjectHelper<IfcSectionedSpine,3> { IfcSectionedSpine() : Object("IfcSectionedSpine") {}
+ Lazy< IfcCompositeCurve > SpineCurve;
+ ListOf< Lazy< IfcProfileDef >, 2, 0 > CrossSections;
+ ListOf< Lazy< IfcAxis2Placement3D >, 2, 0 > CrossSectionPositions;
};
- // C++ wrapper for IfcRelAggregates
- struct IfcRelAggregates : IfcRelDecomposes, ObjectHelper<IfcRelAggregates,0> { IfcRelAggregates() : Object("IfcRelAggregates") {}
-
+ // C++ wrapper for IfcSensorType
+ struct IfcSensorType : IfcDistributionControlElementType, ObjectHelper<IfcSensorType,1> { IfcSensorType() : Object("IfcSensorType") {}
+ IfcSensorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFaceBasedSurfaceModel
- struct IfcFaceBasedSurfaceModel : IfcGeometricRepresentationItem, ObjectHelper<IfcFaceBasedSurfaceModel,1> { IfcFaceBasedSurfaceModel() : Object("IfcFaceBasedSurfaceModel") {}
- ListOf< Lazy< IfcConnectedFaceSet >, 1, 0 > FbsmFaces;
+ // C++ wrapper for IfcServiceLife
+ struct IfcServiceLife : IfcControl, ObjectHelper<IfcServiceLife,2> { IfcServiceLife() : Object("IfcServiceLife") {}
+ IfcServiceLifeTypeEnum::Out ServiceLifeType;
+ IfcTimeMeasure::Out ServiceLifeDuration;
};
- // C++ wrapper for IfcEnergyConversionDevice
- struct IfcEnergyConversionDevice : IfcDistributionFlowElement, ObjectHelper<IfcEnergyConversionDevice,0> { IfcEnergyConversionDevice() : Object("IfcEnergyConversionDevice") {}
+ // C++ wrapper for IfcShapeModel
+ struct IfcShapeModel : IfcRepresentation, ObjectHelper<IfcShapeModel,0> { IfcShapeModel() : Object("IfcShapeModel") {}
};
- // C++ wrapper for IfcRampFlight
- struct IfcRampFlight : IfcBuildingElement, ObjectHelper<IfcRampFlight,0> { IfcRampFlight() : Object("IfcRampFlight") {}
+ // C++ wrapper for IfcShapeRepresentation
+ struct IfcShapeRepresentation : IfcShapeModel, ObjectHelper<IfcShapeRepresentation,0> { IfcShapeRepresentation() : Object("IfcShapeRepresentation") {}
};
- // C++ wrapper for IfcVertexLoop
- struct IfcVertexLoop : IfcLoop, ObjectHelper<IfcVertexLoop,1> { IfcVertexLoop() : Object("IfcVertexLoop") {}
- Lazy< IfcVertex > LoopVertex;
+ // C++ wrapper for IfcShellBasedSurfaceModel
+ struct IfcShellBasedSurfaceModel : IfcGeometricRepresentationItem, ObjectHelper<IfcShellBasedSurfaceModel,1> { IfcShellBasedSurfaceModel() : Object("IfcShellBasedSurfaceModel") {}
+ ListOf< IfcShell, 1, 0 >::Out SbsmBoundary;
};
- // C++ wrapper for IfcPlate
- struct IfcPlate : IfcBuildingElement, ObjectHelper<IfcPlate,0> { IfcPlate() : Object("IfcPlate") {}
-
+ // C++ wrapper for IfcSite
+ struct IfcSite : IfcSpatialStructureElement, ObjectHelper<IfcSite,5> { IfcSite() : Object("IfcSite") {}
+ Maybe< IfcCompoundPlaneAngleMeasure::Out > RefLatitude;
+ Maybe< IfcCompoundPlaneAngleMeasure::Out > RefLongitude;
+ Maybe< IfcLengthMeasure::Out > RefElevation;
+ Maybe< IfcLabel::Out > LandTitleNumber;
+ Maybe< Lazy< NotImplemented > > SiteAddress;
};
- // C++ wrapper for IfcUShapeProfileDef
- struct IfcUShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcUShapeProfileDef,8> { IfcUShapeProfileDef() : Object("IfcUShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out Depth;
- IfcPositiveLengthMeasure::Out FlangeWidth;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out FlangeThickness;
- Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
- Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
- Maybe< IfcPlaneAngleMeasure::Out > FlangeSlope;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
+ // C++ wrapper for IfcSlab
+ struct IfcSlab : IfcBuildingElement, ObjectHelper<IfcSlab,1> { IfcSlab() : Object("IfcSlab") {}
+ Maybe< IfcSlabTypeEnum::Out > PredefinedType;
};
- // C++ wrapper for IfcFaceBound
- struct IfcFaceBound : IfcTopologicalRepresentationItem, ObjectHelper<IfcFaceBound,2> { IfcFaceBound() : Object("IfcFaceBound") {}
- Lazy< IfcLoop > Bound;
- BOOLEAN::Out Orientation;
+ // C++ wrapper for IfcSlabType
+ struct IfcSlabType : IfcBuildingElementType, ObjectHelper<IfcSlabType,1> { IfcSlabType() : Object("IfcSlabType") {}
+ IfcSlabTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcFaceOuterBound
- struct IfcFaceOuterBound : IfcFaceBound, ObjectHelper<IfcFaceOuterBound,0> { IfcFaceOuterBound() : Object("IfcFaceOuterBound") {}
-
+ // C++ wrapper for IfcSpace
+ struct IfcSpace : IfcSpatialStructureElement, ObjectHelper<IfcSpace,2> { IfcSpace() : Object("IfcSpace") {}
+ IfcInternalOrExternalEnum::Out InteriorOrExteriorSpace;
+ Maybe< IfcLengthMeasure::Out > ElevationWithFlooring;
};
- // C++ wrapper for IfcOneDirectionRepeatFactor
- struct IfcOneDirectionRepeatFactor : IfcGeometricRepresentationItem, ObjectHelper<IfcOneDirectionRepeatFactor,1> { IfcOneDirectionRepeatFactor() : Object("IfcOneDirectionRepeatFactor") {}
- Lazy< IfcVector > RepeatFactor;
+ // C++ wrapper for IfcSpaceHeaterType
+ struct IfcSpaceHeaterType : IfcEnergyConversionDeviceType, ObjectHelper<IfcSpaceHeaterType,1> { IfcSpaceHeaterType() : Object("IfcSpaceHeaterType") {}
+ IfcSpaceHeaterTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcBoilerType
- struct IfcBoilerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcBoilerType,1> { IfcBoilerType() : Object("IfcBoilerType") {}
- IfcBoilerTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcSpaceProgram
+ struct IfcSpaceProgram : IfcControl, ObjectHelper<IfcSpaceProgram,5> { IfcSpaceProgram() : Object("IfcSpaceProgram") {}
+ IfcIdentifier::Out SpaceProgramIdentifier;
+ Maybe< IfcAreaMeasure::Out > MaxRequiredArea;
+ Maybe< IfcAreaMeasure::Out > MinRequiredArea;
+ Maybe< Lazy< IfcSpatialStructureElement > > RequestedLocation;
+ IfcAreaMeasure::Out StandardRequiredArea;
};
- // C++ wrapper for IfcConstructionEquipmentResource
- struct IfcConstructionEquipmentResource : IfcConstructionResource, ObjectHelper<IfcConstructionEquipmentResource,0> { IfcConstructionEquipmentResource() : Object("IfcConstructionEquipmentResource") {}
+ // C++ wrapper for IfcSpatialStructureElementType
+ struct IfcSpatialStructureElementType : IfcElementType, ObjectHelper<IfcSpatialStructureElementType,0> { IfcSpatialStructureElementType() : Object("IfcSpatialStructureElementType") {}
};
- // C++ wrapper for IfcComplexProperty
- struct IfcComplexProperty : IfcProperty, ObjectHelper<IfcComplexProperty,2> { IfcComplexProperty() : Object("IfcComplexProperty") {}
- IfcIdentifier::Out UsageName;
- ListOf< Lazy< IfcProperty >, 1, 0 > HasProperties;
- };
-
- // C++ wrapper for IfcFooting
- struct IfcFooting : IfcBuildingElement, ObjectHelper<IfcFooting,1> { IfcFooting() : Object("IfcFooting") {}
- IfcFootingTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcSpaceType
+ struct IfcSpaceType : IfcSpatialStructureElementType, ObjectHelper<IfcSpaceType,1> { IfcSpaceType() : Object("IfcSpaceType") {}
+ IfcSpaceTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcConstructionProductResource
- struct IfcConstructionProductResource : IfcConstructionResource, ObjectHelper<IfcConstructionProductResource,0> { IfcConstructionProductResource() : Object("IfcConstructionProductResource") {}
-
+ // C++ wrapper for IfcSphere
+ struct IfcSphere : IfcCsgPrimitive3D, ObjectHelper<IfcSphere,1> { IfcSphere() : Object("IfcSphere") {}
+ IfcPositiveLengthMeasure::Out Radius;
};
- // C++ wrapper for IfcDerivedProfileDef
- struct IfcDerivedProfileDef : IfcProfileDef, ObjectHelper<IfcDerivedProfileDef,3> { IfcDerivedProfileDef() : Object("IfcDerivedProfileDef") {}
- Lazy< IfcProfileDef > ParentProfile;
- Lazy< IfcCartesianTransformationOperator2D > Operator;
- Maybe< IfcLabel::Out > Label;
+ // C++ wrapper for IfcStackTerminalType
+ struct IfcStackTerminalType : IfcFlowTerminalType, ObjectHelper<IfcStackTerminalType,1> { IfcStackTerminalType() : Object("IfcStackTerminalType") {}
+ IfcStackTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcPropertyTableValue
- struct IfcPropertyTableValue : IfcSimpleProperty, ObjectHelper<IfcPropertyTableValue,5> { IfcPropertyTableValue() : Object("IfcPropertyTableValue") {}
- ListOf< IfcValue, 1, 0 >::Out DefiningValues;
- ListOf< IfcValue, 1, 0 >::Out DefinedValues;
- Maybe< IfcText::Out > Expression;
- Maybe< IfcUnit::Out > DefiningUnit;
- Maybe< IfcUnit::Out > DefinedUnit;
+ // C++ wrapper for IfcStair
+ struct IfcStair : IfcBuildingElement, ObjectHelper<IfcStair,1> { IfcStair() : Object("IfcStair") {}
+ IfcStairTypeEnum::Out ShapeType;
};
- // C++ wrapper for IfcFlowMeterType
- struct IfcFlowMeterType : IfcFlowControllerType, ObjectHelper<IfcFlowMeterType,1> { IfcFlowMeterType() : Object("IfcFlowMeterType") {}
- IfcFlowMeterTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcStairFlight
+ struct IfcStairFlight : IfcBuildingElement, ObjectHelper<IfcStairFlight,4> { IfcStairFlight() : Object("IfcStairFlight") {}
+ Maybe< INTEGER::Out > NumberOfRiser;
+ Maybe< INTEGER::Out > NumberOfTreads;
+ Maybe< IfcPositiveLengthMeasure::Out > RiserHeight;
+ Maybe< IfcPositiveLengthMeasure::Out > TreadLength;
};
- // C++ wrapper for IfcDoorStyle
- struct IfcDoorStyle : IfcTypeProduct, ObjectHelper<IfcDoorStyle,4> { IfcDoorStyle() : Object("IfcDoorStyle") {}
- IfcDoorStyleOperationEnum::Out OperationType;
- IfcDoorStyleConstructionEnum::Out ConstructionType;
- BOOLEAN::Out ParameterTakesPrecedence;
- BOOLEAN::Out Sizeable;
+ // C++ wrapper for IfcStairFlightType
+ struct IfcStairFlightType : IfcBuildingElementType, ObjectHelper<IfcStairFlightType,1> { IfcStairFlightType() : Object("IfcStairFlightType") {}
+ IfcStairFlightTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcUnitAssignment
- struct IfcUnitAssignment : ObjectHelper<IfcUnitAssignment,1> { IfcUnitAssignment() : Object("IfcUnitAssignment") {}
- ListOf< IfcUnit, 1, 0 >::Out Units;
+ // C++ wrapper for IfcStructuralActivity
+ struct IfcStructuralActivity : IfcProduct, ObjectHelper<IfcStructuralActivity,2> { IfcStructuralActivity() : Object("IfcStructuralActivity") {}
+ Lazy< NotImplemented > AppliedLoad;
+ IfcGlobalOrLocalEnum::Out GlobalOrLocal;
};
- // C++ wrapper for IfcFlowTerminal
- struct IfcFlowTerminal : IfcDistributionFlowElement, ObjectHelper<IfcFlowTerminal,0> { IfcFlowTerminal() : Object("IfcFlowTerminal") {}
-
+ // C++ wrapper for IfcStructuralAction
+ struct IfcStructuralAction : IfcStructuralActivity, ObjectHelper<IfcStructuralAction,2> { IfcStructuralAction() : Object("IfcStructuralAction") {}
+ BOOLEAN::Out DestabilizingLoad;
+ Maybe< Lazy< IfcStructuralReaction > > CausedBy;
};
- // C++ wrapper for IfcCraneRailFShapeProfileDef
- struct IfcCraneRailFShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcCraneRailFShapeProfileDef,9> { IfcCraneRailFShapeProfileDef() : Object("IfcCraneRailFShapeProfileDef") {}
- IfcPositiveLengthMeasure::Out OverallHeight;
- IfcPositiveLengthMeasure::Out HeadWidth;
- Maybe< IfcPositiveLengthMeasure::Out > Radius;
- IfcPositiveLengthMeasure::Out HeadDepth2;
- IfcPositiveLengthMeasure::Out HeadDepth3;
- IfcPositiveLengthMeasure::Out WebThickness;
- IfcPositiveLengthMeasure::Out BaseDepth1;
- IfcPositiveLengthMeasure::Out BaseDepth2;
- Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
+ // C++ wrapper for IfcStructuralAnalysisModel
+ struct IfcStructuralAnalysisModel : IfcSystem, ObjectHelper<IfcStructuralAnalysisModel,4> { IfcStructuralAnalysisModel() : Object("IfcStructuralAnalysisModel") {}
+ IfcAnalysisModelTypeEnum::Out PredefinedType;
+ Maybe< Lazy< IfcAxis2Placement3D > > OrientationOf2DPlane;
+ Maybe< ListOf< Lazy< IfcStructuralLoadGroup >, 1, 0 > > LoadedBy;
+ Maybe< ListOf< Lazy< IfcStructuralResultGroup >, 1, 0 > > HasResults;
};
- // C++ wrapper for IfcFlowSegment
- struct IfcFlowSegment : IfcDistributionFlowElement, ObjectHelper<IfcFlowSegment,0> { IfcFlowSegment() : Object("IfcFlowSegment") {}
+ // C++ wrapper for IfcStructuralItem
+ struct IfcStructuralItem : IfcProduct, ObjectHelper<IfcStructuralItem,0> { IfcStructuralItem() : Object("IfcStructuralItem") {}
};
- // C++ wrapper for IfcElementQuantity
- struct IfcElementQuantity : IfcPropertySetDefinition, ObjectHelper<IfcElementQuantity,2> { IfcElementQuantity() : Object("IfcElementQuantity") {}
- Maybe< IfcLabel::Out > MethodOfMeasurement;
- ListOf< Lazy< NotImplemented >, 1, 0 > Quantities;
+ // C++ wrapper for IfcStructuralConnection
+ struct IfcStructuralConnection : IfcStructuralItem, ObjectHelper<IfcStructuralConnection,1> { IfcStructuralConnection() : Object("IfcStructuralConnection") {}
+ Maybe< Lazy< NotImplemented > > AppliedCondition;
};
- // C++ wrapper for IfcCurtainWall
- struct IfcCurtainWall : IfcBuildingElement, ObjectHelper<IfcCurtainWall,0> { IfcCurtainWall() : Object("IfcCurtainWall") {}
+ // C++ wrapper for IfcStructuralCurveConnection
+ struct IfcStructuralCurveConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralCurveConnection,0> { IfcStructuralCurveConnection() : Object("IfcStructuralCurveConnection") {}
};
- // C++ wrapper for IfcDiscreteAccessory
- struct IfcDiscreteAccessory : IfcElementComponent, ObjectHelper<IfcDiscreteAccessory,0> { IfcDiscreteAccessory() : Object("IfcDiscreteAccessory") {}
+ // C++ wrapper for IfcStructuralMember
+ struct IfcStructuralMember : IfcStructuralItem, ObjectHelper<IfcStructuralMember,0> { IfcStructuralMember() : Object("IfcStructuralMember") {}
};
- // C++ wrapper for IfcGrid
- struct IfcGrid : IfcProduct, ObjectHelper<IfcGrid,3> { IfcGrid() : Object("IfcGrid") {}
- ListOf< Lazy< NotImplemented >, 1, 0 > UAxes;
- ListOf< Lazy< NotImplemented >, 1, 0 > VAxes;
- Maybe< ListOf< Lazy< NotImplemented >, 1, 0 > > WAxes;
+ // C++ wrapper for IfcStructuralCurveMember
+ struct IfcStructuralCurveMember : IfcStructuralMember, ObjectHelper<IfcStructuralCurveMember,1> { IfcStructuralCurveMember() : Object("IfcStructuralCurveMember") {}
+ IfcStructuralCurveTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSanitaryTerminalType
- struct IfcSanitaryTerminalType : IfcFlowTerminalType, ObjectHelper<IfcSanitaryTerminalType,1> { IfcSanitaryTerminalType() : Object("IfcSanitaryTerminalType") {}
- IfcSanitaryTerminalTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcStructuralCurveMemberVarying
+ struct IfcStructuralCurveMemberVarying : IfcStructuralCurveMember, ObjectHelper<IfcStructuralCurveMemberVarying,0> { IfcStructuralCurveMemberVarying() : Object("IfcStructuralCurveMemberVarying") {}
- // C++ wrapper for IfcSubedge
- struct IfcSubedge : IfcEdge, ObjectHelper<IfcSubedge,1> { IfcSubedge() : Object("IfcSubedge") {}
- Lazy< IfcEdge > ParentEdge;
};
- // C++ wrapper for IfcFilterType
- struct IfcFilterType : IfcFlowTreatmentDeviceType, ObjectHelper<IfcFilterType,1> { IfcFilterType() : Object("IfcFilterType") {}
- IfcFilterTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcStructuralLinearAction
+ struct IfcStructuralLinearAction : IfcStructuralAction, ObjectHelper<IfcStructuralLinearAction,1> { IfcStructuralLinearAction() : Object("IfcStructuralLinearAction") {}
+ IfcProjectedOrTrueLengthEnum::Out ProjectedOrTrue;
};
- // C++ wrapper for IfcTendon
- struct IfcTendon : IfcReinforcingElement, ObjectHelper<IfcTendon,8> { IfcTendon() : Object("IfcTendon") {}
- IfcTendonTypeEnum::Out PredefinedType;
- IfcPositiveLengthMeasure::Out NominalDiameter;
- IfcAreaMeasure::Out CrossSectionArea;
- Maybe< IfcForceMeasure::Out > TensionForce;
- Maybe< IfcPressureMeasure::Out > PreStress;
- Maybe< IfcNormalisedRatioMeasure::Out > FrictionCoefficient;
- Maybe< IfcPositiveLengthMeasure::Out > AnchorageSlip;
- Maybe< IfcPositiveLengthMeasure::Out > MinCurvatureRadius;
+ // C++ wrapper for IfcStructuralLinearActionVarying
+ struct IfcStructuralLinearActionVarying : IfcStructuralLinearAction, ObjectHelper<IfcStructuralLinearActionVarying,2> { IfcStructuralLinearActionVarying() : Object("IfcStructuralLinearActionVarying") {}
+ Lazy< NotImplemented > VaryingAppliedLoadLocation;
+ ListOf< Lazy< NotImplemented >, 1, 0 > SubsequentAppliedLoads;
};
// C++ wrapper for IfcStructuralLoadGroup
struct IfcStructuralLoadGroup : IfcGroup, ObjectHelper<IfcStructuralLoadGroup,5> { IfcStructuralLoadGroup() : Object("IfcStructuralLoadGroup") {}
- IfcLoadGroupTypeEnum::Out PredefinedType;
- IfcActionTypeEnum::Out ActionType;
- IfcActionSourceTypeEnum::Out ActionSource;
- Maybe< IfcPositiveRatioMeasure::Out > Coefficient;
- Maybe< IfcLabel::Out > Purpose;
+ IfcLoadGroupTypeEnum::Out PredefinedType;
+ IfcActionTypeEnum::Out ActionType;
+ IfcActionSourceTypeEnum::Out ActionSource;
+ Maybe< IfcPositiveRatioMeasure::Out > Coefficient;
+ Maybe< IfcLabel::Out > Purpose;
};
- // C++ wrapper for IfcPresentationStyleAssignment
- struct IfcPresentationStyleAssignment : ObjectHelper<IfcPresentationStyleAssignment,1> { IfcPresentationStyleAssignment() : Object("IfcPresentationStyleAssignment") {}
- ListOf< IfcPresentationStyleSelect, 1, 0 >::Out Styles;
+ // C++ wrapper for IfcStructuralPlanarAction
+ struct IfcStructuralPlanarAction : IfcStructuralAction, ObjectHelper<IfcStructuralPlanarAction,1> { IfcStructuralPlanarAction() : Object("IfcStructuralPlanarAction") {}
+ IfcProjectedOrTrueLengthEnum::Out ProjectedOrTrue;
};
- // C++ wrapper for IfcStructuralCurveMember
- struct IfcStructuralCurveMember : IfcStructuralMember, ObjectHelper<IfcStructuralCurveMember,1> { IfcStructuralCurveMember() : Object("IfcStructuralCurveMember") {}
- IfcStructuralCurveTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcStructuralPlanarActionVarying
+ struct IfcStructuralPlanarActionVarying : IfcStructuralPlanarAction, ObjectHelper<IfcStructuralPlanarActionVarying,2> { IfcStructuralPlanarActionVarying() : Object("IfcStructuralPlanarActionVarying") {}
+ Lazy< NotImplemented > VaryingAppliedLoadLocation;
+ ListOf< Lazy< NotImplemented >, 2, 0 > SubsequentAppliedLoads;
};
- // C++ wrapper for IfcLightSourceAmbient
- struct IfcLightSourceAmbient : IfcLightSource, ObjectHelper<IfcLightSourceAmbient,0> { IfcLightSourceAmbient() : Object("IfcLightSourceAmbient") {}
+ // C++ wrapper for IfcStructuralPointAction
+ struct IfcStructuralPointAction : IfcStructuralAction, ObjectHelper<IfcStructuralPointAction,0> { IfcStructuralPointAction() : Object("IfcStructuralPointAction") {}
};
- // C++ wrapper for IfcCondition
- struct IfcCondition : IfcGroup, ObjectHelper<IfcCondition,0> { IfcCondition() : Object("IfcCondition") {}
+ // C++ wrapper for IfcStructuralPointConnection
+ struct IfcStructuralPointConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralPointConnection,0> { IfcStructuralPointConnection() : Object("IfcStructuralPointConnection") {}
};
- // C++ wrapper for IfcPort
- struct IfcPort : IfcProduct, ObjectHelper<IfcPort,0> { IfcPort() : Object("IfcPort") {}
+ // C++ wrapper for IfcStructuralReaction
+ struct IfcStructuralReaction : IfcStructuralActivity, ObjectHelper<IfcStructuralReaction,0> { IfcStructuralReaction() : Object("IfcStructuralReaction") {}
};
- // C++ wrapper for IfcSpace
- struct IfcSpace : IfcSpatialStructureElement, ObjectHelper<IfcSpace,2> { IfcSpace() : Object("IfcSpace") {}
- IfcInternalOrExternalEnum::Out InteriorOrExteriorSpace;
- Maybe< IfcLengthMeasure::Out > ElevationWithFlooring;
- };
+ // C++ wrapper for IfcStructuralPointReaction
+ struct IfcStructuralPointReaction : IfcStructuralReaction, ObjectHelper<IfcStructuralPointReaction,0> { IfcStructuralPointReaction() : Object("IfcStructuralPointReaction") {}
- // C++ wrapper for IfcHeatExchangerType
- struct IfcHeatExchangerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcHeatExchangerType,1> { IfcHeatExchangerType() : Object("IfcHeatExchangerType") {}
- IfcHeatExchangerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcTankType
- struct IfcTankType : IfcFlowStorageDeviceType, ObjectHelper<IfcTankType,1> { IfcTankType() : Object("IfcTankType") {}
- IfcTankTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcStructuralResultGroup
+ struct IfcStructuralResultGroup : IfcGroup, ObjectHelper<IfcStructuralResultGroup,3> { IfcStructuralResultGroup() : Object("IfcStructuralResultGroup") {}
+ IfcAnalysisTheoryTypeEnum::Out TheoryType;
+ Maybe< Lazy< IfcStructuralLoadGroup > > ResultForLoadGroup;
+ BOOLEAN::Out IsLinear;
};
- // C++ wrapper for IfcInventory
- struct IfcInventory : IfcGroup, ObjectHelper<IfcInventory,6> { IfcInventory() : Object("IfcInventory") {}
- IfcInventoryTypeEnum::Out InventoryType;
- IfcActorSelect::Out Jurisdiction;
- ListOf< Lazy< NotImplemented >, 1, 0 > ResponsiblePersons;
- Lazy< NotImplemented > LastUpdateDate;
- Maybe< Lazy< NotImplemented > > CurrentValue;
- Maybe< Lazy< NotImplemented > > OriginalValue;
- };
+ // C++ wrapper for IfcStructuralSurfaceConnection
+ struct IfcStructuralSurfaceConnection : IfcStructuralConnection, ObjectHelper<IfcStructuralSurfaceConnection,0> { IfcStructuralSurfaceConnection() : Object("IfcStructuralSurfaceConnection") {}
- // C++ wrapper for IfcTransportElementType
- struct IfcTransportElementType : IfcElementType, ObjectHelper<IfcTransportElementType,1> { IfcTransportElementType() : Object("IfcTransportElementType") {}
- IfcTransportElementTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcAirToAirHeatRecoveryType
- struct IfcAirToAirHeatRecoveryType : IfcEnergyConversionDeviceType, ObjectHelper<IfcAirToAirHeatRecoveryType,1> { IfcAirToAirHeatRecoveryType() : Object("IfcAirToAirHeatRecoveryType") {}
- IfcAirToAirHeatRecoveryTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcStructuralSurfaceMember
+ struct IfcStructuralSurfaceMember : IfcStructuralMember, ObjectHelper<IfcStructuralSurfaceMember,2> { IfcStructuralSurfaceMember() : Object("IfcStructuralSurfaceMember") {}
+ IfcStructuralSurfaceTypeEnum::Out PredefinedType;
+ Maybe< IfcPositiveLengthMeasure::Out > Thickness;
};
- // C++ wrapper for IfcStairFlight
- struct IfcStairFlight : IfcBuildingElement, ObjectHelper<IfcStairFlight,4> { IfcStairFlight() : Object("IfcStairFlight") {}
- Maybe< INTEGER::Out > NumberOfRiser;
- Maybe< INTEGER::Out > NumberOfTreads;
- Maybe< IfcPositiveLengthMeasure::Out > RiserHeight;
- Maybe< IfcPositiveLengthMeasure::Out > TreadLength;
+ // C++ wrapper for IfcStructuralSurfaceMemberVarying
+ struct IfcStructuralSurfaceMemberVarying : IfcStructuralSurfaceMember, ObjectHelper<IfcStructuralSurfaceMemberVarying,2> { IfcStructuralSurfaceMemberVarying() : Object("IfcStructuralSurfaceMemberVarying") {}
+ ListOf< IfcPositiveLengthMeasure, 2, 0 >::Out SubsequentThickness;
+ Lazy< NotImplemented > VaryingThicknessLocation;
};
- // C++ wrapper for IfcElectricalElement
- struct IfcElectricalElement : IfcElement, ObjectHelper<IfcElectricalElement,0> { IfcElectricalElement() : Object("IfcElectricalElement") {}
+ // C++ wrapper for IfcStructuredDimensionCallout
+ struct IfcStructuredDimensionCallout : IfcDraughtingCallout, ObjectHelper<IfcStructuredDimensionCallout,0> { IfcStructuredDimensionCallout() : Object("IfcStructuredDimensionCallout") {}
};
- // C++ wrapper for IfcSurfaceStyleWithTextures
- struct IfcSurfaceStyleWithTextures : ObjectHelper<IfcSurfaceStyleWithTextures,1> { IfcSurfaceStyleWithTextures() : Object("IfcSurfaceStyleWithTextures") {}
- ListOf< Lazy< NotImplemented >, 1, 0 > Textures;
- };
+ // C++ wrapper for IfcStyleModel
+ struct IfcStyleModel : IfcRepresentation, ObjectHelper<IfcStyleModel,0> { IfcStyleModel() : Object("IfcStyleModel") {}
- // C++ wrapper for IfcBoundingBox
- struct IfcBoundingBox : IfcGeometricRepresentationItem, ObjectHelper<IfcBoundingBox,4> { IfcBoundingBox() : Object("IfcBoundingBox") {}
- Lazy< IfcCartesianPoint > Corner;
- IfcPositiveLengthMeasure::Out XDim;
- IfcPositiveLengthMeasure::Out YDim;
- IfcPositiveLengthMeasure::Out ZDim;
};
- // C++ wrapper for IfcWallType
- struct IfcWallType : IfcBuildingElementType, ObjectHelper<IfcWallType,1> { IfcWallType() : Object("IfcWallType") {}
- IfcWallTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcStyledRepresentation
+ struct IfcStyledRepresentation : IfcStyleModel, ObjectHelper<IfcStyledRepresentation,0> { IfcStyledRepresentation() : Object("IfcStyledRepresentation") {}
- // C++ wrapper for IfcMove
- struct IfcMove : IfcTask, ObjectHelper<IfcMove,3> { IfcMove() : Object("IfcMove") {}
- Lazy< IfcSpatialStructureElement > MoveFrom;
- Lazy< IfcSpatialStructureElement > MoveTo;
- Maybe< ListOf< IfcText, 1, 0 >::Out > PunchList;
};
- // C++ wrapper for IfcCircle
- struct IfcCircle : IfcConic, ObjectHelper<IfcCircle,1> { IfcCircle() : Object("IfcCircle") {}
- IfcPositiveLengthMeasure::Out Radius;
+ // C++ wrapper for IfcSubContractResource
+ struct IfcSubContractResource : IfcConstructionResource, ObjectHelper<IfcSubContractResource,2> { IfcSubContractResource() : Object("IfcSubContractResource") {}
+ Maybe< IfcActorSelect::Out > SubContractor;
+ Maybe< IfcText::Out > JobDescription;
};
- // C++ wrapper for IfcOffsetCurve2D
- struct IfcOffsetCurve2D : IfcCurve, ObjectHelper<IfcOffsetCurve2D,3> { IfcOffsetCurve2D() : Object("IfcOffsetCurve2D") {}
- Lazy< IfcCurve > BasisCurve;
- IfcLengthMeasure::Out Distance;
- LOGICAL::Out SelfIntersect;
+ // C++ wrapper for IfcSubedge
+ struct IfcSubedge : IfcEdge, ObjectHelper<IfcSubedge,1> { IfcSubedge() : Object("IfcSubedge") {}
+ Lazy< IfcEdge > ParentEdge;
};
- // C++ wrapper for IfcPointOnCurve
- struct IfcPointOnCurve : IfcPoint, ObjectHelper<IfcPointOnCurve,2> { IfcPointOnCurve() : Object("IfcPointOnCurve") {}
- Lazy< IfcCurve > BasisCurve;
- IfcParameterValue::Out PointParameter;
+ // C++ wrapper for IfcSurfaceCurveSweptAreaSolid
+ struct IfcSurfaceCurveSweptAreaSolid : IfcSweptAreaSolid, ObjectHelper<IfcSurfaceCurveSweptAreaSolid,4> { IfcSurfaceCurveSweptAreaSolid() : Object("IfcSurfaceCurveSweptAreaSolid") {}
+ Lazy< IfcCurve > Directrix;
+ IfcParameterValue::Out StartParam;
+ IfcParameterValue::Out EndParam;
+ Lazy< IfcSurface > ReferenceSurface;
};
- // C++ wrapper for IfcStructuralResultGroup
- struct IfcStructuralResultGroup : IfcGroup, ObjectHelper<IfcStructuralResultGroup,3> { IfcStructuralResultGroup() : Object("IfcStructuralResultGroup") {}
- IfcAnalysisTheoryTypeEnum::Out TheoryType;
- Maybe< Lazy< IfcStructuralLoadGroup > > ResultForLoadGroup;
- BOOLEAN::Out IsLinear;
+ // C++ wrapper for IfcSweptSurface
+ struct IfcSweptSurface : IfcSurface, ObjectHelper<IfcSweptSurface,2> { IfcSweptSurface() : Object("IfcSweptSurface") {}
+ Lazy< IfcProfileDef > SweptCurve;
+ Lazy< IfcAxis2Placement3D > Position;
};
- // C++ wrapper for IfcSectionedSpine
- struct IfcSectionedSpine : IfcGeometricRepresentationItem, ObjectHelper<IfcSectionedSpine,3> { IfcSectionedSpine() : Object("IfcSectionedSpine") {}
- Lazy< IfcCompositeCurve > SpineCurve;
- ListOf< Lazy< IfcProfileDef >, 2, 0 > CrossSections;
- ListOf< Lazy< IfcAxis2Placement3D >, 2, 0 > CrossSectionPositions;
+ // C++ wrapper for IfcSurfaceOfLinearExtrusion
+ struct IfcSurfaceOfLinearExtrusion : IfcSweptSurface, ObjectHelper<IfcSurfaceOfLinearExtrusion,2> { IfcSurfaceOfLinearExtrusion() : Object("IfcSurfaceOfLinearExtrusion") {}
+ Lazy< IfcDirection > ExtrudedDirection;
+ IfcLengthMeasure::Out Depth;
};
- // C++ wrapper for IfcSlab
- struct IfcSlab : IfcBuildingElement, ObjectHelper<IfcSlab,1> { IfcSlab() : Object("IfcSlab") {}
- Maybe< IfcSlabTypeEnum::Out > PredefinedType;
+ // C++ wrapper for IfcSurfaceOfRevolution
+ struct IfcSurfaceOfRevolution : IfcSweptSurface, ObjectHelper<IfcSurfaceOfRevolution,1> { IfcSurfaceOfRevolution() : Object("IfcSurfaceOfRevolution") {}
+ Lazy< IfcAxis1Placement > AxisPosition;
};
- // C++ wrapper for IfcVertex
- struct IfcVertex : IfcTopologicalRepresentationItem, ObjectHelper<IfcVertex,0> { IfcVertex() : Object("IfcVertex") {}
+ // C++ wrapper for IfcSurfaceStyle
+ struct IfcSurfaceStyle : IfcPresentationStyle, ObjectHelper<IfcSurfaceStyle,2> { IfcSurfaceStyle() : Object("IfcSurfaceStyle") {}
+ IfcSurfaceSide::Out Side;
+ ListOf< IfcSurfaceStyleElementSelect, 1, 5 >::Out Styles;
+ };
+ // C++ wrapper for IfcSurfaceStyleShading
+ struct IfcSurfaceStyleShading : ObjectHelper<IfcSurfaceStyleShading,1> { IfcSurfaceStyleShading() : Object("IfcSurfaceStyleShading") {}
+ Lazy< IfcColourRgb > SurfaceColour;
};
- // C++ wrapper for IfcVertexPoint
- struct IfcVertexPoint : IfcVertex, ObjectHelper<IfcVertexPoint,1> { IfcVertexPoint() : Object("IfcVertexPoint") {}
- Lazy< IfcPoint > VertexGeometry;
+ // C++ wrapper for IfcSurfaceStyleRendering
+ struct IfcSurfaceStyleRendering : IfcSurfaceStyleShading, ObjectHelper<IfcSurfaceStyleRendering,8> { IfcSurfaceStyleRendering() : Object("IfcSurfaceStyleRendering") {}
+ Maybe< IfcNormalisedRatioMeasure::Out > Transparency;
+ Maybe< IfcColourOrFactor::Out > DiffuseColour;
+ Maybe< IfcColourOrFactor::Out > TransmissionColour;
+ Maybe< IfcColourOrFactor::Out > DiffuseTransmissionColour;
+ Maybe< IfcColourOrFactor::Out > ReflectionColour;
+ Maybe< IfcColourOrFactor::Out > SpecularColour;
+ Maybe< IfcSpecularHighlightSelect::Out > SpecularHighlight;
+ IfcReflectanceMethodEnum::Out ReflectanceMethod;
};
- // C++ wrapper for IfcStructuralLinearAction
- struct IfcStructuralLinearAction : IfcStructuralAction, ObjectHelper<IfcStructuralLinearAction,1> { IfcStructuralLinearAction() : Object("IfcStructuralLinearAction") {}
- IfcProjectedOrTrueLengthEnum::Out ProjectedOrTrue;
+ // C++ wrapper for IfcSurfaceStyleWithTextures
+ struct IfcSurfaceStyleWithTextures : ObjectHelper<IfcSurfaceStyleWithTextures,1> { IfcSurfaceStyleWithTextures() : Object("IfcSurfaceStyleWithTextures") {}
+ ListOf< Lazy< NotImplemented >, 1, 0 > Textures;
};
- // C++ wrapper for IfcStructuralLinearActionVarying
- struct IfcStructuralLinearActionVarying : IfcStructuralLinearAction, ObjectHelper<IfcStructuralLinearActionVarying,2> { IfcStructuralLinearActionVarying() : Object("IfcStructuralLinearActionVarying") {}
- Lazy< NotImplemented > VaryingAppliedLoadLocation;
- ListOf< Lazy< NotImplemented >, 1, 0 > SubsequentAppliedLoads;
+ // C++ wrapper for IfcSweptDiskSolid
+ struct IfcSweptDiskSolid : IfcSolidModel, ObjectHelper<IfcSweptDiskSolid,5> { IfcSweptDiskSolid() : Object("IfcSweptDiskSolid") {}
+ Lazy< IfcCurve > Directrix;
+ IfcPositiveLengthMeasure::Out Radius;
+ Maybe< IfcPositiveLengthMeasure::Out > InnerRadius;
+ IfcParameterValue::Out StartParam;
+ IfcParameterValue::Out EndParam;
};
- // C++ wrapper for IfcBuildingElementProxyType
- struct IfcBuildingElementProxyType : IfcBuildingElementType, ObjectHelper<IfcBuildingElementProxyType,1> { IfcBuildingElementProxyType() : Object("IfcBuildingElementProxyType") {}
- IfcBuildingElementProxyTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcSwitchingDeviceType
+ struct IfcSwitchingDeviceType : IfcFlowControllerType, ObjectHelper<IfcSwitchingDeviceType,1> { IfcSwitchingDeviceType() : Object("IfcSwitchingDeviceType") {}
+ IfcSwitchingDeviceTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcProjectionElement
- struct IfcProjectionElement : IfcFeatureElementAddition, ObjectHelper<IfcProjectionElement,0> { IfcProjectionElement() : Object("IfcProjectionElement") {}
+ // C++ wrapper for IfcSystemFurnitureElementType
+ struct IfcSystemFurnitureElementType : IfcFurnishingElementType, ObjectHelper<IfcSystemFurnitureElementType,0> { IfcSystemFurnitureElementType() : Object("IfcSystemFurnitureElementType") {}
};
- // C++ wrapper for IfcConversionBasedUnit
- struct IfcConversionBasedUnit : IfcNamedUnit, ObjectHelper<IfcConversionBasedUnit,2> { IfcConversionBasedUnit() : Object("IfcConversionBasedUnit") {}
- IfcLabel::Out Name;
- Lazy< IfcMeasureWithUnit > ConversionFactor;
+ // C++ wrapper for IfcTShapeProfileDef
+ struct IfcTShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcTShapeProfileDef,10> { IfcTShapeProfileDef() : Object("IfcTShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out Depth;
+ IfcPositiveLengthMeasure::Out FlangeWidth;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out FlangeThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > FlangeEdgeRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > WebEdgeRadius;
+ Maybe< IfcPlaneAngleMeasure::Out > WebSlope;
+ Maybe< IfcPlaneAngleMeasure::Out > FlangeSlope;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInY;
};
- // C++ wrapper for IfcGeometricRepresentationSubContext
- struct IfcGeometricRepresentationSubContext : IfcGeometricRepresentationContext, ObjectHelper<IfcGeometricRepresentationSubContext,4> { IfcGeometricRepresentationSubContext() : Object("IfcGeometricRepresentationSubContext") {}
- Lazy< IfcGeometricRepresentationContext > ParentContext;
- Maybe< IfcPositiveRatioMeasure::Out > TargetScale;
- IfcGeometricProjectionEnum::Out TargetView;
- Maybe< IfcLabel::Out > UserDefinedTargetView;
+ // C++ wrapper for IfcTankType
+ struct IfcTankType : IfcFlowStorageDeviceType, ObjectHelper<IfcTankType,1> { IfcTankType() : Object("IfcTankType") {}
+ IfcTankTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcAnnotationSurfaceOccurrence
- struct IfcAnnotationSurfaceOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationSurfaceOccurrence,0> { IfcAnnotationSurfaceOccurrence() : Object("IfcAnnotationSurfaceOccurrence") {}
+ // C++ wrapper for IfcTendon
+ struct IfcTendon : IfcReinforcingElement, ObjectHelper<IfcTendon,8> { IfcTendon() : Object("IfcTendon") {}
+ IfcTendonTypeEnum::Out PredefinedType;
+ IfcPositiveLengthMeasure::Out NominalDiameter;
+ IfcAreaMeasure::Out CrossSectionArea;
+ Maybe< IfcForceMeasure::Out > TensionForce;
+ Maybe< IfcPressureMeasure::Out > PreStress;
+ Maybe< IfcNormalisedRatioMeasure::Out > FrictionCoefficient;
+ Maybe< IfcPositiveLengthMeasure::Out > AnchorageSlip;
+ Maybe< IfcPositiveLengthMeasure::Out > MinCurvatureRadius;
+ };
+
+ // C++ wrapper for IfcTendonAnchor
+ struct IfcTendonAnchor : IfcReinforcingElement, ObjectHelper<IfcTendonAnchor,0> { IfcTendonAnchor() : Object("IfcTendonAnchor") {}
};
- // C++ wrapper for IfcRoundedEdgeFeature
- struct IfcRoundedEdgeFeature : IfcEdgeFeature, ObjectHelper<IfcRoundedEdgeFeature,1> { IfcRoundedEdgeFeature() : Object("IfcRoundedEdgeFeature") {}
- Maybe< IfcPositiveLengthMeasure::Out > Radius;
+ // C++ wrapper for IfcTextLiteral
+ struct IfcTextLiteral : IfcGeometricRepresentationItem, ObjectHelper<IfcTextLiteral,3> { IfcTextLiteral() : Object("IfcTextLiteral") {}
+ IfcPresentableText::Out Literal;
+ IfcAxis2Placement::Out Placement;
+ IfcTextPath::Out Path;
};
- // C++ wrapper for IfcElectricDistributionPoint
- struct IfcElectricDistributionPoint : IfcFlowController, ObjectHelper<IfcElectricDistributionPoint,2> { IfcElectricDistributionPoint() : Object("IfcElectricDistributionPoint") {}
- IfcElectricDistributionPointFunctionEnum::Out DistributionPointFunction;
- Maybe< IfcLabel::Out > UserDefinedFunction;
+ // C++ wrapper for IfcTextLiteralWithExtent
+ struct IfcTextLiteralWithExtent : IfcTextLiteral, ObjectHelper<IfcTextLiteralWithExtent,2> { IfcTextLiteralWithExtent() : Object("IfcTextLiteralWithExtent") {}
+ Lazy< IfcPlanarExtent > Extent;
+ IfcBoxAlignment::Out BoxAlignment;
};
- // C++ wrapper for IfcCableCarrierSegmentType
- struct IfcCableCarrierSegmentType : IfcFlowSegmentType, ObjectHelper<IfcCableCarrierSegmentType,1> { IfcCableCarrierSegmentType() : Object("IfcCableCarrierSegmentType") {}
- IfcCableCarrierSegmentTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcTimeSeriesSchedule
+ struct IfcTimeSeriesSchedule : IfcControl, ObjectHelper<IfcTimeSeriesSchedule,3> { IfcTimeSeriesSchedule() : Object("IfcTimeSeriesSchedule") {}
+ Maybe< ListOf< IfcDateTimeSelect, 1, 0 >::Out > ApplicableDates;
+ IfcTimeSeriesScheduleTypeEnum::Out TimeSeriesScheduleType;
+ Lazy< NotImplemented > TimeSeries;
};
- // C++ wrapper for IfcWallStandardCase
- struct IfcWallStandardCase : IfcWall, ObjectHelper<IfcWallStandardCase,0> { IfcWallStandardCase() : Object("IfcWallStandardCase") {}
+ // C++ wrapper for IfcTopologyRepresentation
+ struct IfcTopologyRepresentation : IfcShapeModel, ObjectHelper<IfcTopologyRepresentation,0> { IfcTopologyRepresentation() : Object("IfcTopologyRepresentation") {}
};
- // C++ wrapper for IfcCsgSolid
- struct IfcCsgSolid : IfcSolidModel, ObjectHelper<IfcCsgSolid,1> { IfcCsgSolid() : Object("IfcCsgSolid") {}
- IfcCsgSelect::Out TreeRootExpression;
+ // C++ wrapper for IfcTransformerType
+ struct IfcTransformerType : IfcEnergyConversionDeviceType, ObjectHelper<IfcTransformerType,1> { IfcTransformerType() : Object("IfcTransformerType") {}
+ IfcTransformerTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcBeamType
- struct IfcBeamType : IfcBuildingElementType, ObjectHelper<IfcBeamType,1> { IfcBeamType() : Object("IfcBeamType") {}
- IfcBeamTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcTransportElement
+ struct IfcTransportElement : IfcElement, ObjectHelper<IfcTransportElement,3> { IfcTransportElement() : Object("IfcTransportElement") {}
+ Maybe< IfcTransportElementTypeEnum::Out > OperationType;
+ Maybe< IfcMassMeasure::Out > CapacityByWeight;
+ Maybe< IfcCountMeasure::Out > CapacityByNumber;
};
- // C++ wrapper for IfcAnnotationFillArea
- struct IfcAnnotationFillArea : IfcGeometricRepresentationItem, ObjectHelper<IfcAnnotationFillArea,2> { IfcAnnotationFillArea() : Object("IfcAnnotationFillArea") {}
- Lazy< IfcCurve > OuterBoundary;
- Maybe< ListOf< Lazy< IfcCurve >, 1, 0 > > InnerBoundaries;
+ // C++ wrapper for IfcTransportElementType
+ struct IfcTransportElementType : IfcElementType, ObjectHelper<IfcTransportElementType,1> { IfcTransportElementType() : Object("IfcTransportElementType") {}
+ IfcTransportElementTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralCurveMemberVarying
- struct IfcStructuralCurveMemberVarying : IfcStructuralCurveMember, ObjectHelper<IfcStructuralCurveMemberVarying,0> { IfcStructuralCurveMemberVarying() : Object("IfcStructuralCurveMemberVarying") {}
-
+ // C++ wrapper for IfcTrapeziumProfileDef
+ struct IfcTrapeziumProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcTrapeziumProfileDef,4> { IfcTrapeziumProfileDef() : Object("IfcTrapeziumProfileDef") {}
+ IfcPositiveLengthMeasure::Out BottomXDim;
+ IfcPositiveLengthMeasure::Out TopXDim;
+ IfcPositiveLengthMeasure::Out YDim;
+ IfcLengthMeasure::Out TopXOffset;
};
- // C++ wrapper for IfcPointOnSurface
- struct IfcPointOnSurface : IfcPoint, ObjectHelper<IfcPointOnSurface,3> { IfcPointOnSurface() : Object("IfcPointOnSurface") {}
- Lazy< IfcSurface > BasisSurface;
- IfcParameterValue::Out PointParameterU;
- IfcParameterValue::Out PointParameterV;
+ // C++ wrapper for IfcTrimmedCurve
+ struct IfcTrimmedCurve : IfcBoundedCurve, ObjectHelper<IfcTrimmedCurve,5> { IfcTrimmedCurve() : Object("IfcTrimmedCurve") {}
+ Lazy< IfcCurve > BasisCurve;
+ ListOf< IfcTrimmingSelect, 1, 2 >::Out Trim1;
+ ListOf< IfcTrimmingSelect, 1, 2 >::Out Trim2;
+ BOOLEAN::Out SenseAgreement;
+ IfcTrimmingPreference::Out MasterRepresentation;
};
- // C++ wrapper for IfcOrderAction
- struct IfcOrderAction : IfcTask, ObjectHelper<IfcOrderAction,1> { IfcOrderAction() : Object("IfcOrderAction") {}
- IfcIdentifier::Out ActionID;
+ // C++ wrapper for IfcTubeBundleType
+ struct IfcTubeBundleType : IfcEnergyConversionDeviceType, ObjectHelper<IfcTubeBundleType,1> { IfcTubeBundleType() : Object("IfcTubeBundleType") {}
+ IfcTubeBundleTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcEdgeLoop
- struct IfcEdgeLoop : IfcLoop, ObjectHelper<IfcEdgeLoop,1> { IfcEdgeLoop() : Object("IfcEdgeLoop") {}
- ListOf< Lazy< IfcOrientedEdge >, 1, 0 > EdgeList;
+ // C++ wrapper for IfcTwoDirectionRepeatFactor
+ struct IfcTwoDirectionRepeatFactor : IfcOneDirectionRepeatFactor, ObjectHelper<IfcTwoDirectionRepeatFactor,1> { IfcTwoDirectionRepeatFactor() : Object("IfcTwoDirectionRepeatFactor") {}
+ Lazy< IfcVector > SecondRepeatFactor;
};
- // C++ wrapper for IfcAnnotationFillAreaOccurrence
- struct IfcAnnotationFillAreaOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationFillAreaOccurrence,2> { IfcAnnotationFillAreaOccurrence() : Object("IfcAnnotationFillAreaOccurrence") {}
- Maybe< Lazy< IfcPoint > > FillStyleTarget;
- Maybe< IfcGlobalOrLocalEnum::Out > GlobalOrLocal;
+ // C++ wrapper for IfcUShapeProfileDef
+ struct IfcUShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcUShapeProfileDef,8> { IfcUShapeProfileDef() : Object("IfcUShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out Depth;
+ IfcPositiveLengthMeasure::Out FlangeWidth;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out FlangeThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
+ Maybe< IfcPlaneAngleMeasure::Out > FlangeSlope;
+ Maybe< IfcPositiveLengthMeasure::Out > CentreOfGravityInX;
};
- // C++ wrapper for IfcWorkPlan
- struct IfcWorkPlan : IfcWorkControl, ObjectHelper<IfcWorkPlan,0> { IfcWorkPlan() : Object("IfcWorkPlan") {}
-
+ // C++ wrapper for IfcUnitAssignment
+ struct IfcUnitAssignment : ObjectHelper<IfcUnitAssignment,1> { IfcUnitAssignment() : Object("IfcUnitAssignment") {}
+ ListOf< IfcUnit, 1, 0 >::Out Units;
};
- // C++ wrapper for IfcEllipse
- struct IfcEllipse : IfcConic, ObjectHelper<IfcEllipse,2> { IfcEllipse() : Object("IfcEllipse") {}
- IfcPositiveLengthMeasure::Out SemiAxis1;
- IfcPositiveLengthMeasure::Out SemiAxis2;
+ // C++ wrapper for IfcUnitaryEquipmentType
+ struct IfcUnitaryEquipmentType : IfcEnergyConversionDeviceType, ObjectHelper<IfcUnitaryEquipmentType,1> { IfcUnitaryEquipmentType() : Object("IfcUnitaryEquipmentType") {}
+ IfcUnitaryEquipmentTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcProductDefinitionShape
- struct IfcProductDefinitionShape : IfcProductRepresentation, ObjectHelper<IfcProductDefinitionShape,0> { IfcProductDefinitionShape() : Object("IfcProductDefinitionShape") {}
+ // C++ wrapper for IfcValveType
+ struct IfcValveType : IfcFlowControllerType, ObjectHelper<IfcValveType,1> { IfcValveType() : Object("IfcValveType") {}
+ IfcValveTypeEnum::Out PredefinedType;
+ };
+ // C++ wrapper for IfcVector
+ struct IfcVector : IfcGeometricRepresentationItem, ObjectHelper<IfcVector,2> { IfcVector() : Object("IfcVector") {}
+ Lazy< IfcDirection > Orientation;
+ IfcLengthMeasure::Out Magnitude;
};
- // C++ wrapper for IfcProjectionCurve
- struct IfcProjectionCurve : IfcAnnotationCurveOccurrence, ObjectHelper<IfcProjectionCurve,0> { IfcProjectionCurve() : Object("IfcProjectionCurve") {}
+ // C++ wrapper for IfcVertex
+ struct IfcVertex : IfcTopologicalRepresentationItem, ObjectHelper<IfcVertex,0> { IfcVertex() : Object("IfcVertex") {}
};
- // C++ wrapper for IfcElectricalCircuit
- struct IfcElectricalCircuit : IfcSystem, ObjectHelper<IfcElectricalCircuit,0> { IfcElectricalCircuit() : Object("IfcElectricalCircuit") {}
+ // C++ wrapper for IfcVertexLoop
+ struct IfcVertexLoop : IfcLoop, ObjectHelper<IfcVertexLoop,1> { IfcVertexLoop() : Object("IfcVertexLoop") {}
+ Lazy< IfcVertex > LoopVertex;
+ };
+ // C++ wrapper for IfcVertexPoint
+ struct IfcVertexPoint : IfcVertex, ObjectHelper<IfcVertexPoint,1> { IfcVertexPoint() : Object("IfcVertexPoint") {}
+ Lazy< IfcPoint > VertexGeometry;
};
- // C++ wrapper for IfcRationalBezierCurve
- struct IfcRationalBezierCurve : IfcBezierCurve, ObjectHelper<IfcRationalBezierCurve,1> { IfcRationalBezierCurve() : Object("IfcRationalBezierCurve") {}
- ListOf< REAL, 2, 0 >::Out WeightsData;
+ // C++ wrapper for IfcVibrationIsolatorType
+ struct IfcVibrationIsolatorType : IfcDiscreteAccessoryType, ObjectHelper<IfcVibrationIsolatorType,1> { IfcVibrationIsolatorType() : Object("IfcVibrationIsolatorType") {}
+ IfcVibrationIsolatorTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcStructuralPointAction
- struct IfcStructuralPointAction : IfcStructuralAction, ObjectHelper<IfcStructuralPointAction,0> { IfcStructuralPointAction() : Object("IfcStructuralPointAction") {}
+ // C++ wrapper for IfcVirtualElement
+ struct IfcVirtualElement : IfcElement, ObjectHelper<IfcVirtualElement,0> { IfcVirtualElement() : Object("IfcVirtualElement") {}
};
- // C++ wrapper for IfcPipeSegmentType
- struct IfcPipeSegmentType : IfcFlowSegmentType, ObjectHelper<IfcPipeSegmentType,1> { IfcPipeSegmentType() : Object("IfcPipeSegmentType") {}
- IfcPipeSegmentTypeEnum::Out PredefinedType;
- };
+ // C++ wrapper for IfcWall
+ struct IfcWall : IfcBuildingElement, ObjectHelper<IfcWall,0> { IfcWall() : Object("IfcWall") {}
- // C++ wrapper for IfcTwoDirectionRepeatFactor
- struct IfcTwoDirectionRepeatFactor : IfcOneDirectionRepeatFactor, ObjectHelper<IfcTwoDirectionRepeatFactor,1> { IfcTwoDirectionRepeatFactor() : Object("IfcTwoDirectionRepeatFactor") {}
- Lazy< IfcVector > SecondRepeatFactor;
};
- // C++ wrapper for IfcShapeRepresentation
- struct IfcShapeRepresentation : IfcShapeModel, ObjectHelper<IfcShapeRepresentation,0> { IfcShapeRepresentation() : Object("IfcShapeRepresentation") {}
+ // C++ wrapper for IfcWallStandardCase
+ struct IfcWallStandardCase : IfcWall, ObjectHelper<IfcWallStandardCase,0> { IfcWallStandardCase() : Object("IfcWallStandardCase") {}
};
- // C++ wrapper for IfcPropertySet
- struct IfcPropertySet : IfcPropertySetDefinition, ObjectHelper<IfcPropertySet,1> { IfcPropertySet() : Object("IfcPropertySet") {}
- ListOf< Lazy< IfcProperty >, 1, 0 > HasProperties;
+ // C++ wrapper for IfcWallType
+ struct IfcWallType : IfcBuildingElementType, ObjectHelper<IfcWallType,1> { IfcWallType() : Object("IfcWallType") {}
+ IfcWallTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcSurfaceStyleRendering
- struct IfcSurfaceStyleRendering : IfcSurfaceStyleShading, ObjectHelper<IfcSurfaceStyleRendering,8> { IfcSurfaceStyleRendering() : Object("IfcSurfaceStyleRendering") {}
- Maybe< IfcNormalisedRatioMeasure::Out > Transparency;
- Maybe< IfcColourOrFactor::Out > DiffuseColour;
- Maybe< IfcColourOrFactor::Out > TransmissionColour;
- Maybe< IfcColourOrFactor::Out > DiffuseTransmissionColour;
- Maybe< IfcColourOrFactor::Out > ReflectionColour;
- Maybe< IfcColourOrFactor::Out > SpecularColour;
- Maybe< IfcSpecularHighlightSelect::Out > SpecularHighlight;
- IfcReflectanceMethodEnum::Out ReflectanceMethod;
+ // C++ wrapper for IfcWasteTerminalType
+ struct IfcWasteTerminalType : IfcFlowTerminalType, ObjectHelper<IfcWasteTerminalType,1> { IfcWasteTerminalType() : Object("IfcWasteTerminalType") {}
+ IfcWasteTerminalTypeEnum::Out PredefinedType;
};
- // C++ wrapper for IfcDistributionPort
- struct IfcDistributionPort : IfcPort, ObjectHelper<IfcDistributionPort,1> { IfcDistributionPort() : Object("IfcDistributionPort") {}
- Maybe< IfcFlowDirectionEnum::Out > FlowDirection;
+ // C++ wrapper for IfcWindow
+ struct IfcWindow : IfcBuildingElement, ObjectHelper<IfcWindow,2> { IfcWindow() : Object("IfcWindow") {}
+ Maybe< IfcPositiveLengthMeasure::Out > OverallHeight;
+ Maybe< IfcPositiveLengthMeasure::Out > OverallWidth;
};
- // C++ wrapper for IfcPipeFittingType
- struct IfcPipeFittingType : IfcFlowFittingType, ObjectHelper<IfcPipeFittingType,1> { IfcPipeFittingType() : Object("IfcPipeFittingType") {}
- IfcPipeFittingTypeEnum::Out PredefinedType;
+ // C++ wrapper for IfcWindowStyle
+ struct IfcWindowStyle : IfcTypeProduct, ObjectHelper<IfcWindowStyle,4> { IfcWindowStyle() : Object("IfcWindowStyle") {}
+ IfcWindowStyleConstructionEnum::Out ConstructionType;
+ IfcWindowStyleOperationEnum::Out OperationType;
+ BOOLEAN::Out ParameterTakesPrecedence;
+ BOOLEAN::Out Sizeable;
};
- // C++ wrapper for IfcTransportElement
- struct IfcTransportElement : IfcElement, ObjectHelper<IfcTransportElement,3> { IfcTransportElement() : Object("IfcTransportElement") {}
- Maybe< IfcTransportElementTypeEnum::Out > OperationType;
- Maybe< IfcMassMeasure::Out > CapacityByWeight;
- Maybe< IfcCountMeasure::Out > CapacityByNumber;
+ // C++ wrapper for IfcWorkControl
+ struct IfcWorkControl : IfcControl, ObjectHelper<IfcWorkControl,10> { IfcWorkControl() : Object("IfcWorkControl") {}
+ IfcIdentifier::Out Identifier;
+ IfcDateTimeSelect::Out CreationDate;
+ Maybe< ListOf< Lazy< NotImplemented >, 1, 0 > > Creators;
+ Maybe< IfcLabel::Out > Purpose;
+ Maybe< IfcTimeMeasure::Out > Duration;
+ Maybe< IfcTimeMeasure::Out > TotalFloat;
+ IfcDateTimeSelect::Out StartTime;
+ Maybe< IfcDateTimeSelect::Out > FinishTime;
+ Maybe< IfcWorkControlTypeEnum::Out > WorkControlType;
+ Maybe< IfcLabel::Out > UserDefinedControlType;
};
- // C++ wrapper for IfcAnnotationTextOccurrence
- struct IfcAnnotationTextOccurrence : IfcAnnotationOccurrence, ObjectHelper<IfcAnnotationTextOccurrence,0> { IfcAnnotationTextOccurrence() : Object("IfcAnnotationTextOccurrence") {}
+ // C++ wrapper for IfcWorkPlan
+ struct IfcWorkPlan : IfcWorkControl, ObjectHelper<IfcWorkPlan,0> { IfcWorkPlan() : Object("IfcWorkPlan") {}
};
- // C++ wrapper for IfcStructuralAnalysisModel
- struct IfcStructuralAnalysisModel : IfcSystem, ObjectHelper<IfcStructuralAnalysisModel,4> { IfcStructuralAnalysisModel() : Object("IfcStructuralAnalysisModel") {}
- IfcAnalysisModelTypeEnum::Out PredefinedType;
- Maybe< Lazy< IfcAxis2Placement3D > > OrientationOf2DPlane;
- Maybe< ListOf< Lazy< IfcStructuralLoadGroup >, 1, 0 > > LoadedBy;
- Maybe< ListOf< Lazy< IfcStructuralResultGroup >, 1, 0 > > HasResults;
+ // C++ wrapper for IfcWorkSchedule
+ struct IfcWorkSchedule : IfcWorkControl, ObjectHelper<IfcWorkSchedule,0> { IfcWorkSchedule() : Object("IfcWorkSchedule") {}
+
};
- // C++ wrapper for IfcConditionCriterion
- struct IfcConditionCriterion : IfcControl, ObjectHelper<IfcConditionCriterion,2> { IfcConditionCriterion() : Object("IfcConditionCriterion") {}
- IfcConditionCriterionSelect::Out Criterion;
- IfcDateTimeSelect::Out CriterionDateTime;
+ // C++ wrapper for IfcZShapeProfileDef
+ struct IfcZShapeProfileDef : IfcParameterizedProfileDef, ObjectHelper<IfcZShapeProfileDef,6> { IfcZShapeProfileDef() : Object("IfcZShapeProfileDef") {}
+ IfcPositiveLengthMeasure::Out Depth;
+ IfcPositiveLengthMeasure::Out FlangeWidth;
+ IfcPositiveLengthMeasure::Out WebThickness;
+ IfcPositiveLengthMeasure::Out FlangeThickness;
+ Maybe< IfcPositiveLengthMeasure::Out > FilletRadius;
+ Maybe< IfcPositiveLengthMeasure::Out > EdgeRadius;
};
- void GetSchema(EXPRESS::ConversionSchema& out);
+ // C++ wrapper for IfcZone
+ struct IfcZone : IfcGroup, ObjectHelper<IfcZone,0> { IfcZone() : Object("IfcZone") {}
+
+ };
+
+ void GetSchema(EXPRESS::ConversionSchema& out);
} //! IFC
namespace STEP {
- // ******************************************************************************
- // Converter stubs
- // ******************************************************************************
-
+ // ******************************************************************************
+ // Converter stubs
+ // ******************************************************************************
+
#define DECL_CONV_STUB(type) template <> size_t GenericFill<IFC::type>(const STEP::DB& db, const EXPRESS::LIST& params, IFC::type* in)
-
- DECL_CONV_STUB(IfcRoot);
- DECL_CONV_STUB(IfcObjectDefinition);
- DECL_CONV_STUB(IfcTypeObject);
- DECL_CONV_STUB(IfcTypeProduct);
- DECL_CONV_STUB(IfcElementType);
- DECL_CONV_STUB(IfcDistributionElementType);
- DECL_CONV_STUB(IfcDistributionFlowElementType);
- DECL_CONV_STUB(IfcFlowControllerType);
- DECL_CONV_STUB(IfcElectricTimeControlType);
- DECL_CONV_STUB(IfcRepresentation);
- DECL_CONV_STUB(IfcShapeModel);
- DECL_CONV_STUB(IfcTopologyRepresentation);
- DECL_CONV_STUB(IfcRelationship);
- DECL_CONV_STUB(IfcRelConnects);
- DECL_CONV_STUB(IfcFlowFittingType);
- DECL_CONV_STUB(IfcCableCarrierFittingType);
- DECL_CONV_STUB(IfcEnergyConversionDeviceType);
- DECL_CONV_STUB(IfcCoilType);
- DECL_CONV_STUB(IfcObject);
- DECL_CONV_STUB(IfcControl);
- DECL_CONV_STUB(IfcPerformanceHistory);
- DECL_CONV_STUB(IfcRepresentationItem);
- DECL_CONV_STUB(IfcGeometricRepresentationItem);
- DECL_CONV_STUB(IfcTextLiteral);
- DECL_CONV_STUB(IfcTextLiteralWithExtent);
- DECL_CONV_STUB(IfcProductRepresentation);
- DECL_CONV_STUB(IfcProduct);
- DECL_CONV_STUB(IfcElement);
- DECL_CONV_STUB(IfcDistributionElement);
- DECL_CONV_STUB(IfcDistributionFlowElement);
- DECL_CONV_STUB(IfcCurve);
- DECL_CONV_STUB(IfcBoundedCurve);
- DECL_CONV_STUB(IfcCompositeCurve);
- DECL_CONV_STUB(Ifc2DCompositeCurve);
- DECL_CONV_STUB(IfcCartesianTransformationOperator);
- DECL_CONV_STUB(IfcCartesianTransformationOperator3D);
- DECL_CONV_STUB(IfcProperty);
- DECL_CONV_STUB(IfcSimpleProperty);
- DECL_CONV_STUB(IfcPropertyEnumeratedValue);
- DECL_CONV_STUB(IfcBuildingElementType);
- DECL_CONV_STUB(IfcStairFlightType);
- DECL_CONV_STUB(IfcSurface);
- DECL_CONV_STUB(IfcElementarySurface);
- DECL_CONV_STUB(IfcPlane);
- DECL_CONV_STUB(IfcBooleanResult);
- DECL_CONV_STUB(IfcBooleanClippingResult);
- DECL_CONV_STUB(IfcSolidModel);
- DECL_CONV_STUB(IfcManifoldSolidBrep);
- DECL_CONV_STUB(IfcFlowTerminalType);
- DECL_CONV_STUB(IfcStackTerminalType);
- DECL_CONV_STUB(IfcStructuralItem);
- DECL_CONV_STUB(IfcStructuralConnection);
- DECL_CONV_STUB(IfcStructuralCurveConnection);
- DECL_CONV_STUB(IfcJunctionBoxType);
- DECL_CONV_STUB(IfcPropertyDefinition);
- DECL_CONV_STUB(IfcPropertySetDefinition);
- DECL_CONV_STUB(IfcProcess);
- DECL_CONV_STUB(IfcTask);
- DECL_CONV_STUB(IfcRelFillsElement);
- DECL_CONV_STUB(IfcProcedure);
- DECL_CONV_STUB(IfcProxy);
- DECL_CONV_STUB(IfcResource);
- DECL_CONV_STUB(IfcConstructionResource);
- DECL_CONV_STUB(IfcSubContractResource);
- DECL_CONV_STUB(IfcRelContainedInSpatialStructure);
- DECL_CONV_STUB(IfcTopologicalRepresentationItem);
- DECL_CONV_STUB(IfcEdge);
- DECL_CONV_STUB(IfcEdgeCurve);
- DECL_CONV_STUB(IfcPlateType);
- DECL_CONV_STUB(IfcObjectPlacement);
- DECL_CONV_STUB(IfcGridPlacement);
- DECL_CONV_STUB(IfcFireSuppressionTerminalType);
- DECL_CONV_STUB(IfcFlowStorageDevice);
- DECL_CONV_STUB(IfcSweptSurface);
- DECL_CONV_STUB(IfcSurfaceOfRevolution);
- DECL_CONV_STUB(IfcOrientedEdge);
- DECL_CONV_STUB(IfcDirection);
- DECL_CONV_STUB(IfcProfileDef);
- DECL_CONV_STUB(IfcParameterizedProfileDef);
- DECL_CONV_STUB(IfcCShapeProfileDef);
- DECL_CONV_STUB(IfcFeatureElement);
- DECL_CONV_STUB(IfcFeatureElementSubtraction);
- DECL_CONV_STUB(IfcEdgeFeature);
- DECL_CONV_STUB(IfcChamferEdgeFeature);
- DECL_CONV_STUB(IfcBuildingElement);
- DECL_CONV_STUB(IfcColumn);
- DECL_CONV_STUB(IfcPropertyReferenceValue);
- DECL_CONV_STUB(IfcElectricMotorType);
- DECL_CONV_STUB(IfcSpatialStructureElementType);
- DECL_CONV_STUB(IfcSpaceType);
- DECL_CONV_STUB(IfcColumnType);
- DECL_CONV_STUB(IfcCraneRailAShapeProfileDef);
- DECL_CONV_STUB(IfcCondenserType);
- DECL_CONV_STUB(IfcCircleProfileDef);
- DECL_CONV_STUB(IfcCircleHollowProfileDef);
- DECL_CONV_STUB(IfcPlacement);
- DECL_CONV_STUB(IfcAxis2Placement3D);
- DECL_CONV_STUB(IfcPresentationStyle);
- DECL_CONV_STUB(IfcEquipmentElement);
- DECL_CONV_STUB(IfcCompositeCurveSegment);
- DECL_CONV_STUB(IfcRectangleProfileDef);
- DECL_CONV_STUB(IfcBuildingElementProxy);
- DECL_CONV_STUB(IfcDistributionControlElementType);
- DECL_CONV_STUB(IfcFlowInstrumentType);
- DECL_CONV_STUB(IfcDraughtingCallout);
- DECL_CONV_STUB(IfcDimensionCurveDirectedCallout);
- DECL_CONV_STUB(IfcLinearDimension);
- DECL_CONV_STUB(IfcElementAssembly);
- DECL_CONV_STUB(IfcCsgPrimitive3D);
- DECL_CONV_STUB(IfcRightCircularCone);
- DECL_CONV_STUB(IfcProjectOrder);
- DECL_CONV_STUB(IfcLShapeProfileDef);
- DECL_CONV_STUB(IfcAngularDimension);
- DECL_CONV_STUB(IfcLocalPlacement);
- DECL_CONV_STUB(IfcSweptAreaSolid);
- DECL_CONV_STUB(IfcRevolvedAreaSolid);
- DECL_CONV_STUB(IfcStructuralSurfaceConnection);
- DECL_CONV_STUB(IfcRadiusDimension);
- DECL_CONV_STUB(IfcSweptDiskSolid);
- DECL_CONV_STUB(IfcHalfSpaceSolid);
- DECL_CONV_STUB(IfcPolygonalBoundedHalfSpace);
- DECL_CONV_STUB(IfcTimeSeriesSchedule);
- DECL_CONV_STUB(IfcCooledBeamType);
- DECL_CONV_STUB(IfcProject);
- DECL_CONV_STUB(IfcEvaporatorType);
- DECL_CONV_STUB(IfcLaborResource);
- DECL_CONV_STUB(IfcPropertyBoundedValue);
- DECL_CONV_STUB(IfcRampFlightType);
- DECL_CONV_STUB(IfcMember);
- DECL_CONV_STUB(IfcTubeBundleType);
- DECL_CONV_STUB(IfcValveType);
- DECL_CONV_STUB(IfcTrimmedCurve);
- DECL_CONV_STUB(IfcRelDefines);
- DECL_CONV_STUB(IfcRelDefinesByProperties);
- DECL_CONV_STUB(IfcActor);
- DECL_CONV_STUB(IfcOccupant);
- DECL_CONV_STUB(IfcHumidifierType);
- DECL_CONV_STUB(IfcArbitraryOpenProfileDef);
- DECL_CONV_STUB(IfcPermit);
- DECL_CONV_STUB(IfcOffsetCurve3D);
- DECL_CONV_STUB(IfcLightSource);
- DECL_CONV_STUB(IfcLightSourcePositional);
- DECL_CONV_STUB(IfcCompositeProfileDef);
- DECL_CONV_STUB(IfcRamp);
- DECL_CONV_STUB(IfcFlowMovingDevice);
- DECL_CONV_STUB(IfcSpaceHeaterType);
- DECL_CONV_STUB(IfcLampType);
- DECL_CONV_STUB(IfcBuildingElementComponent);
- DECL_CONV_STUB(IfcReinforcingElement);
- DECL_CONV_STUB(IfcReinforcingBar);
- DECL_CONV_STUB(IfcElectricHeaterType);
- DECL_CONV_STUB(IfcTShapeProfileDef);
- DECL_CONV_STUB(IfcStructuralActivity);
- DECL_CONV_STUB(IfcStructuralAction);
- DECL_CONV_STUB(IfcDuctFittingType);
- DECL_CONV_STUB(IfcCartesianTransformationOperator2D);
- DECL_CONV_STUB(IfcCartesianTransformationOperator2DnonUniform);
- DECL_CONV_STUB(IfcVirtualElement);
- DECL_CONV_STUB(IfcRightCircularCylinder);
- DECL_CONV_STUB(IfcOutletType);
- DECL_CONV_STUB(IfcRelDecomposes);
- DECL_CONV_STUB(IfcCovering);
- DECL_CONV_STUB(IfcPolyline);
- DECL_CONV_STUB(IfcPath);
- DECL_CONV_STUB(IfcElementComponent);
- DECL_CONV_STUB(IfcFastener);
- DECL_CONV_STUB(IfcMappedItem);
- DECL_CONV_STUB(IfcRectangularPyramid);
- DECL_CONV_STUB(IfcCrewResource);
- DECL_CONV_STUB(IfcNamedUnit);
- DECL_CONV_STUB(IfcContextDependentUnit);
- DECL_CONV_STUB(IfcUnitaryEquipmentType);
- DECL_CONV_STUB(IfcRoof);
- DECL_CONV_STUB(IfcStructuralMember);
- DECL_CONV_STUB(IfcStyleModel);
- DECL_CONV_STUB(IfcStyledRepresentation);
- DECL_CONV_STUB(IfcSpatialStructureElement);
- DECL_CONV_STUB(IfcBuilding);
- DECL_CONV_STUB(IfcConnectedFaceSet);
- DECL_CONV_STUB(IfcOpenShell);
- DECL_CONV_STUB(IfcFacetedBrep);
- DECL_CONV_STUB(IfcConic);
- DECL_CONV_STUB(IfcCoveringType);
- DECL_CONV_STUB(IfcRoundedRectangleProfileDef);
- DECL_CONV_STUB(IfcAirTerminalType);
- DECL_CONV_STUB(IfcFlowMovingDeviceType);
- DECL_CONV_STUB(IfcCompressorType);
- DECL_CONV_STUB(IfcIShapeProfileDef);
- DECL_CONV_STUB(IfcAsymmetricIShapeProfileDef);
- DECL_CONV_STUB(IfcControllerType);
- DECL_CONV_STUB(IfcRailing);
- DECL_CONV_STUB(IfcGroup);
- DECL_CONV_STUB(IfcAsset);
- DECL_CONV_STUB(IfcMaterialDefinitionRepresentation);
- DECL_CONV_STUB(IfcRailingType);
- DECL_CONV_STUB(IfcWall);
- DECL_CONV_STUB(IfcStructuralPointConnection);
- DECL_CONV_STUB(IfcPropertyListValue);
- DECL_CONV_STUB(IfcFurnitureStandard);
- DECL_CONV_STUB(IfcElectricGeneratorType);
- DECL_CONV_STUB(IfcDoor);
- DECL_CONV_STUB(IfcStyledItem);
- DECL_CONV_STUB(IfcAnnotationOccurrence);
- DECL_CONV_STUB(IfcAnnotationSymbolOccurrence);
- DECL_CONV_STUB(IfcArbitraryClosedProfileDef);
- DECL_CONV_STUB(IfcArbitraryProfileDefWithVoids);
- DECL_CONV_STUB(IfcLine);
- DECL_CONV_STUB(IfcFlowSegmentType);
- DECL_CONV_STUB(IfcAirTerminalBoxType);
- DECL_CONV_STUB(IfcPropertySingleValue);
- DECL_CONV_STUB(IfcAlarmType);
- DECL_CONV_STUB(IfcEllipseProfileDef);
- DECL_CONV_STUB(IfcStair);
- DECL_CONV_STUB(IfcSurfaceStyleShading);
- DECL_CONV_STUB(IfcPumpType);
- DECL_CONV_STUB(IfcDefinedSymbol);
- DECL_CONV_STUB(IfcElementComponentType);
- DECL_CONV_STUB(IfcFastenerType);
- DECL_CONV_STUB(IfcMechanicalFastenerType);
- DECL_CONV_STUB(IfcFlowFitting);
- DECL_CONV_STUB(IfcLightSourceDirectional);
- DECL_CONV_STUB(IfcSurfaceStyle);
- DECL_CONV_STUB(IfcAnnotationSurface);
- DECL_CONV_STUB(IfcFlowController);
- DECL_CONV_STUB(IfcBuildingStorey);
- DECL_CONV_STUB(IfcWorkControl);
- DECL_CONV_STUB(IfcWorkSchedule);
- DECL_CONV_STUB(IfcDuctSegmentType);
- DECL_CONV_STUB(IfcFace);
- DECL_CONV_STUB(IfcStructuralSurfaceMember);
- DECL_CONV_STUB(IfcStructuralSurfaceMemberVarying);
- DECL_CONV_STUB(IfcFaceSurface);
- DECL_CONV_STUB(IfcCostSchedule);
- DECL_CONV_STUB(IfcPlanarExtent);
- DECL_CONV_STUB(IfcPlanarBox);
- DECL_CONV_STUB(IfcColourSpecification);
- DECL_CONV_STUB(IfcVector);
- DECL_CONV_STUB(IfcBeam);
- DECL_CONV_STUB(IfcColourRgb);
- DECL_CONV_STUB(IfcStructuralPlanarAction);
- DECL_CONV_STUB(IfcStructuralPlanarActionVarying);
- DECL_CONV_STUB(IfcSite);
- DECL_CONV_STUB(IfcDiscreteAccessoryType);
- DECL_CONV_STUB(IfcVibrationIsolatorType);
- DECL_CONV_STUB(IfcEvaporativeCoolerType);
- DECL_CONV_STUB(IfcDistributionChamberElementType);
- DECL_CONV_STUB(IfcFeatureElementAddition);
- DECL_CONV_STUB(IfcStructuredDimensionCallout);
- DECL_CONV_STUB(IfcCoolingTowerType);
- DECL_CONV_STUB(IfcCenterLineProfileDef);
- DECL_CONV_STUB(IfcWindowStyle);
- DECL_CONV_STUB(IfcLightSourceGoniometric);
- DECL_CONV_STUB(IfcTransformerType);
- DECL_CONV_STUB(IfcMemberType);
- DECL_CONV_STUB(IfcSurfaceOfLinearExtrusion);
- DECL_CONV_STUB(IfcMotorConnectionType);
- DECL_CONV_STUB(IfcFlowTreatmentDeviceType);
- DECL_CONV_STUB(IfcDuctSilencerType);
- DECL_CONV_STUB(IfcFurnishingElementType);
- DECL_CONV_STUB(IfcSystemFurnitureElementType);
- DECL_CONV_STUB(IfcWasteTerminalType);
- DECL_CONV_STUB(IfcBSplineCurve);
- DECL_CONV_STUB(IfcBezierCurve);
- DECL_CONV_STUB(IfcActuatorType);
- DECL_CONV_STUB(IfcDistributionControlElement);
- DECL_CONV_STUB(IfcAnnotation);
- DECL_CONV_STUB(IfcShellBasedSurfaceModel);
- DECL_CONV_STUB(IfcActionRequest);
- DECL_CONV_STUB(IfcExtrudedAreaSolid);
- DECL_CONV_STUB(IfcSystem);
- DECL_CONV_STUB(IfcFillAreaStyleHatching);
- DECL_CONV_STUB(IfcRelVoidsElement);
- DECL_CONV_STUB(IfcSurfaceCurveSweptAreaSolid);
- DECL_CONV_STUB(IfcCartesianTransformationOperator3DnonUniform);
- DECL_CONV_STUB(IfcCurtainWallType);
- DECL_CONV_STUB(IfcEquipmentStandard);
- DECL_CONV_STUB(IfcFlowStorageDeviceType);
- DECL_CONV_STUB(IfcDiameterDimension);
- DECL_CONV_STUB(IfcSwitchingDeviceType);
- DECL_CONV_STUB(IfcWindow);
- DECL_CONV_STUB(IfcFlowTreatmentDevice);
- DECL_CONV_STUB(IfcChillerType);
- DECL_CONV_STUB(IfcRectangleHollowProfileDef);
- DECL_CONV_STUB(IfcBoxedHalfSpace);
- DECL_CONV_STUB(IfcAxis2Placement2D);
- DECL_CONV_STUB(IfcSpaceProgram);
- DECL_CONV_STUB(IfcPoint);
- DECL_CONV_STUB(IfcCartesianPoint);
- DECL_CONV_STUB(IfcBoundedSurface);
- DECL_CONV_STUB(IfcLoop);
- DECL_CONV_STUB(IfcPolyLoop);
- DECL_CONV_STUB(IfcTerminatorSymbol);
- DECL_CONV_STUB(IfcDimensionCurveTerminator);
- DECL_CONV_STUB(IfcTrapeziumProfileDef);
- DECL_CONV_STUB(IfcRepresentationContext);
- DECL_CONV_STUB(IfcGeometricRepresentationContext);
- DECL_CONV_STUB(IfcCurveBoundedPlane);
- DECL_CONV_STUB(IfcSIUnit);
- DECL_CONV_STUB(IfcStructuralReaction);
- DECL_CONV_STUB(IfcStructuralPointReaction);
- DECL_CONV_STUB(IfcAxis1Placement);
- DECL_CONV_STUB(IfcElectricApplianceType);
- DECL_CONV_STUB(IfcSensorType);
- DECL_CONV_STUB(IfcFurnishingElement);
- DECL_CONV_STUB(IfcProtectiveDeviceType);
- DECL_CONV_STUB(IfcZShapeProfileDef);
- DECL_CONV_STUB(IfcScheduleTimeControl);
- DECL_CONV_STUB(IfcRepresentationMap);
- DECL_CONV_STUB(IfcClosedShell);
- DECL_CONV_STUB(IfcBuildingElementPart);
- DECL_CONV_STUB(IfcBlock);
- DECL_CONV_STUB(IfcLightFixtureType);
- DECL_CONV_STUB(IfcOpeningElement);
- DECL_CONV_STUB(IfcLightSourceSpot);
- DECL_CONV_STUB(IfcTendonAnchor);
- DECL_CONV_STUB(IfcElectricFlowStorageDeviceType);
- DECL_CONV_STUB(IfcSphere);
- DECL_CONV_STUB(IfcDamperType);
- DECL_CONV_STUB(IfcProjectOrderRecord);
- DECL_CONV_STUB(IfcDistributionChamberElement);
- DECL_CONV_STUB(IfcMechanicalFastener);
- DECL_CONV_STUB(IfcRectangularTrimmedSurface);
- DECL_CONV_STUB(IfcZone);
- DECL_CONV_STUB(IfcFanType);
- DECL_CONV_STUB(IfcGeometricSet);
- DECL_CONV_STUB(IfcFillAreaStyleTiles);
- DECL_CONV_STUB(IfcCableSegmentType);
- DECL_CONV_STUB(IfcRelOverridesProperties);
- DECL_CONV_STUB(IfcMeasureWithUnit);
- DECL_CONV_STUB(IfcSlabType);
- DECL_CONV_STUB(IfcServiceLife);
- DECL_CONV_STUB(IfcFurnitureType);
- DECL_CONV_STUB(IfcCostItem);
- DECL_CONV_STUB(IfcReinforcingMesh);
- DECL_CONV_STUB(IfcFacetedBrepWithVoids);
- DECL_CONV_STUB(IfcGasTerminalType);
- DECL_CONV_STUB(IfcPile);
- DECL_CONV_STUB(IfcFillAreaStyleTileSymbolWithStyle);
- DECL_CONV_STUB(IfcConstructionMaterialResource);
- DECL_CONV_STUB(IfcAnnotationCurveOccurrence);
- DECL_CONV_STUB(IfcDimensionCurve);
- DECL_CONV_STUB(IfcGeometricCurveSet);
- DECL_CONV_STUB(IfcRelAggregates);
- DECL_CONV_STUB(IfcFaceBasedSurfaceModel);
- DECL_CONV_STUB(IfcEnergyConversionDevice);
- DECL_CONV_STUB(IfcRampFlight);
- DECL_CONV_STUB(IfcVertexLoop);
- DECL_CONV_STUB(IfcPlate);
- DECL_CONV_STUB(IfcUShapeProfileDef);
- DECL_CONV_STUB(IfcFaceBound);
- DECL_CONV_STUB(IfcFaceOuterBound);
- DECL_CONV_STUB(IfcOneDirectionRepeatFactor);
- DECL_CONV_STUB(IfcBoilerType);
- DECL_CONV_STUB(IfcConstructionEquipmentResource);
- DECL_CONV_STUB(IfcComplexProperty);
- DECL_CONV_STUB(IfcFooting);
- DECL_CONV_STUB(IfcConstructionProductResource);
- DECL_CONV_STUB(IfcDerivedProfileDef);
- DECL_CONV_STUB(IfcPropertyTableValue);
- DECL_CONV_STUB(IfcFlowMeterType);
- DECL_CONV_STUB(IfcDoorStyle);
- DECL_CONV_STUB(IfcUnitAssignment);
- DECL_CONV_STUB(IfcFlowTerminal);
- DECL_CONV_STUB(IfcCraneRailFShapeProfileDef);
- DECL_CONV_STUB(IfcFlowSegment);
- DECL_CONV_STUB(IfcElementQuantity);
- DECL_CONV_STUB(IfcCurtainWall);
- DECL_CONV_STUB(IfcDiscreteAccessory);
- DECL_CONV_STUB(IfcGrid);
- DECL_CONV_STUB(IfcSanitaryTerminalType);
- DECL_CONV_STUB(IfcSubedge);
- DECL_CONV_STUB(IfcFilterType);
- DECL_CONV_STUB(IfcTendon);
- DECL_CONV_STUB(IfcStructuralLoadGroup);
- DECL_CONV_STUB(IfcPresentationStyleAssignment);
- DECL_CONV_STUB(IfcStructuralCurveMember);
- DECL_CONV_STUB(IfcLightSourceAmbient);
- DECL_CONV_STUB(IfcCondition);
- DECL_CONV_STUB(IfcPort);
- DECL_CONV_STUB(IfcSpace);
- DECL_CONV_STUB(IfcHeatExchangerType);
- DECL_CONV_STUB(IfcTankType);
- DECL_CONV_STUB(IfcInventory);
- DECL_CONV_STUB(IfcTransportElementType);
- DECL_CONV_STUB(IfcAirToAirHeatRecoveryType);
- DECL_CONV_STUB(IfcStairFlight);
- DECL_CONV_STUB(IfcElectricalElement);
- DECL_CONV_STUB(IfcSurfaceStyleWithTextures);
- DECL_CONV_STUB(IfcBoundingBox);
- DECL_CONV_STUB(IfcWallType);
- DECL_CONV_STUB(IfcMove);
- DECL_CONV_STUB(IfcCircle);
- DECL_CONV_STUB(IfcOffsetCurve2D);
- DECL_CONV_STUB(IfcPointOnCurve);
- DECL_CONV_STUB(IfcStructuralResultGroup);
- DECL_CONV_STUB(IfcSectionedSpine);
- DECL_CONV_STUB(IfcSlab);
- DECL_CONV_STUB(IfcVertex);
- DECL_CONV_STUB(IfcVertexPoint);
- DECL_CONV_STUB(IfcStructuralLinearAction);
- DECL_CONV_STUB(IfcStructuralLinearActionVarying);
- DECL_CONV_STUB(IfcBuildingElementProxyType);
- DECL_CONV_STUB(IfcProjectionElement);
- DECL_CONV_STUB(IfcConversionBasedUnit);
- DECL_CONV_STUB(IfcGeometricRepresentationSubContext);
- DECL_CONV_STUB(IfcAnnotationSurfaceOccurrence);
- DECL_CONV_STUB(IfcRoundedEdgeFeature);
- DECL_CONV_STUB(IfcElectricDistributionPoint);
- DECL_CONV_STUB(IfcCableCarrierSegmentType);
- DECL_CONV_STUB(IfcWallStandardCase);
- DECL_CONV_STUB(IfcCsgSolid);
- DECL_CONV_STUB(IfcBeamType);
- DECL_CONV_STUB(IfcAnnotationFillArea);
- DECL_CONV_STUB(IfcStructuralCurveMemberVarying);
- DECL_CONV_STUB(IfcPointOnSurface);
- DECL_CONV_STUB(IfcOrderAction);
- DECL_CONV_STUB(IfcEdgeLoop);
- DECL_CONV_STUB(IfcAnnotationFillAreaOccurrence);
- DECL_CONV_STUB(IfcWorkPlan);
- DECL_CONV_STUB(IfcEllipse);
- DECL_CONV_STUB(IfcProductDefinitionShape);
- DECL_CONV_STUB(IfcProjectionCurve);
- DECL_CONV_STUB(IfcElectricalCircuit);
- DECL_CONV_STUB(IfcRationalBezierCurve);
- DECL_CONV_STUB(IfcStructuralPointAction);
- DECL_CONV_STUB(IfcPipeSegmentType);
- DECL_CONV_STUB(IfcTwoDirectionRepeatFactor);
- DECL_CONV_STUB(IfcShapeRepresentation);
- DECL_CONV_STUB(IfcPropertySet);
- DECL_CONV_STUB(IfcSurfaceStyleRendering);
- DECL_CONV_STUB(IfcDistributionPort);
- DECL_CONV_STUB(IfcPipeFittingType);
- DECL_CONV_STUB(IfcTransportElement);
- DECL_CONV_STUB(IfcAnnotationTextOccurrence);
- DECL_CONV_STUB(IfcStructuralAnalysisModel);
- DECL_CONV_STUB(IfcConditionCriterion);
+
+ DECL_CONV_STUB(IfcRepresentationItem);
+ DECL_CONV_STUB(IfcGeometricRepresentationItem);
+ DECL_CONV_STUB(IfcCurve);
+ DECL_CONV_STUB(IfcBoundedCurve);
+ DECL_CONV_STUB(IfcCompositeCurve);
+ DECL_CONV_STUB(Ifc2DCompositeCurve);
+ DECL_CONV_STUB(IfcRoot);
+ DECL_CONV_STUB(IfcObjectDefinition);
+ DECL_CONV_STUB(IfcObject);
+ DECL_CONV_STUB(IfcControl);
+ DECL_CONV_STUB(IfcActionRequest);
+ DECL_CONV_STUB(IfcActor);
+ DECL_CONV_STUB(IfcTypeObject);
+ DECL_CONV_STUB(IfcTypeProduct);
+ DECL_CONV_STUB(IfcElementType);
+ DECL_CONV_STUB(IfcDistributionElementType);
+ DECL_CONV_STUB(IfcDistributionControlElementType);
+ DECL_CONV_STUB(IfcActuatorType);
+ DECL_CONV_STUB(IfcDistributionFlowElementType);
+ DECL_CONV_STUB(IfcFlowControllerType);
+ DECL_CONV_STUB(IfcAirTerminalBoxType);
+ DECL_CONV_STUB(IfcFlowTerminalType);
+ DECL_CONV_STUB(IfcAirTerminalType);
+ DECL_CONV_STUB(IfcEnergyConversionDeviceType);
+ DECL_CONV_STUB(IfcAirToAirHeatRecoveryType);
+ DECL_CONV_STUB(IfcAlarmType);
+ DECL_CONV_STUB(IfcDraughtingCallout);
+ DECL_CONV_STUB(IfcDimensionCurveDirectedCallout);
+ DECL_CONV_STUB(IfcAngularDimension);
+ DECL_CONV_STUB(IfcProduct);
+ DECL_CONV_STUB(IfcAnnotation);
+ DECL_CONV_STUB(IfcStyledItem);
+ DECL_CONV_STUB(IfcAnnotationOccurrence);
+ DECL_CONV_STUB(IfcAnnotationCurveOccurrence);
+ DECL_CONV_STUB(IfcAnnotationFillArea);
+ DECL_CONV_STUB(IfcAnnotationFillAreaOccurrence);
+ DECL_CONV_STUB(IfcAnnotationSurface);
+ DECL_CONV_STUB(IfcAnnotationSurfaceOccurrence);
+ DECL_CONV_STUB(IfcAnnotationSymbolOccurrence);
+ DECL_CONV_STUB(IfcAnnotationTextOccurrence);
+ DECL_CONV_STUB(IfcProfileDef);
+ DECL_CONV_STUB(IfcArbitraryClosedProfileDef);
+ DECL_CONV_STUB(IfcArbitraryOpenProfileDef);
+ DECL_CONV_STUB(IfcArbitraryProfileDefWithVoids);
+ DECL_CONV_STUB(IfcGroup);
+ DECL_CONV_STUB(IfcAsset);
+ DECL_CONV_STUB(IfcParameterizedProfileDef);
+ DECL_CONV_STUB(IfcIShapeProfileDef);
+ DECL_CONV_STUB(IfcAsymmetricIShapeProfileDef);
+ DECL_CONV_STUB(IfcPlacement);
+ DECL_CONV_STUB(IfcAxis1Placement);
+ DECL_CONV_STUB(IfcAxis2Placement2D);
+ DECL_CONV_STUB(IfcAxis2Placement3D);
+ DECL_CONV_STUB(IfcBSplineCurve);
+ DECL_CONV_STUB(IfcElement);
+ DECL_CONV_STUB(IfcBuildingElement);
+ DECL_CONV_STUB(IfcBeam);
+ DECL_CONV_STUB(IfcBuildingElementType);
+ DECL_CONV_STUB(IfcBeamType);
+ DECL_CONV_STUB(IfcBezierCurve);
+ DECL_CONV_STUB(IfcCsgPrimitive3D);
+ DECL_CONV_STUB(IfcBlock);
+ DECL_CONV_STUB(IfcBoilerType);
+ DECL_CONV_STUB(IfcBooleanResult);
+ DECL_CONV_STUB(IfcBooleanClippingResult);
+ DECL_CONV_STUB(IfcSurface);
+ DECL_CONV_STUB(IfcBoundedSurface);
+ DECL_CONV_STUB(IfcBoundingBox);
+ DECL_CONV_STUB(IfcHalfSpaceSolid);
+ DECL_CONV_STUB(IfcBoxedHalfSpace);
+ DECL_CONV_STUB(IfcSpatialStructureElement);
+ DECL_CONV_STUB(IfcBuilding);
+ DECL_CONV_STUB(IfcBuildingElementComponent);
+ DECL_CONV_STUB(IfcBuildingElementPart);
+ DECL_CONV_STUB(IfcBuildingElementProxy);
+ DECL_CONV_STUB(IfcBuildingElementProxyType);
+ DECL_CONV_STUB(IfcBuildingStorey);
+ DECL_CONV_STUB(IfcCShapeProfileDef);
+ DECL_CONV_STUB(IfcFlowFittingType);
+ DECL_CONV_STUB(IfcCableCarrierFittingType);
+ DECL_CONV_STUB(IfcFlowSegmentType);
+ DECL_CONV_STUB(IfcCableCarrierSegmentType);
+ DECL_CONV_STUB(IfcCableSegmentType);
+ DECL_CONV_STUB(IfcPoint);
+ DECL_CONV_STUB(IfcCartesianPoint);
+ DECL_CONV_STUB(IfcCartesianTransformationOperator);
+ DECL_CONV_STUB(IfcCartesianTransformationOperator2D);
+ DECL_CONV_STUB(IfcCartesianTransformationOperator2DnonUniform);
+ DECL_CONV_STUB(IfcCartesianTransformationOperator3D);
+ DECL_CONV_STUB(IfcCartesianTransformationOperator3DnonUniform);
+ DECL_CONV_STUB(IfcCenterLineProfileDef);
+ DECL_CONV_STUB(IfcFeatureElement);
+ DECL_CONV_STUB(IfcFeatureElementSubtraction);
+ DECL_CONV_STUB(IfcEdgeFeature);
+ DECL_CONV_STUB(IfcChamferEdgeFeature);
+ DECL_CONV_STUB(IfcChillerType);
+ DECL_CONV_STUB(IfcConic);
+ DECL_CONV_STUB(IfcCircle);
+ DECL_CONV_STUB(IfcCircleProfileDef);
+ DECL_CONV_STUB(IfcCircleHollowProfileDef);
+ DECL_CONV_STUB(IfcTopologicalRepresentationItem);
+ DECL_CONV_STUB(IfcConnectedFaceSet);
+ DECL_CONV_STUB(IfcClosedShell);
+ DECL_CONV_STUB(IfcCoilType);
+ DECL_CONV_STUB(IfcColourSpecification);
+ DECL_CONV_STUB(IfcColourRgb);
+ DECL_CONV_STUB(IfcColumn);
+ DECL_CONV_STUB(IfcColumnType);
+ DECL_CONV_STUB(IfcProperty);
+ DECL_CONV_STUB(IfcComplexProperty);
+ DECL_CONV_STUB(IfcCompositeCurveSegment);
+ DECL_CONV_STUB(IfcCompositeProfileDef);
+ DECL_CONV_STUB(IfcFlowMovingDeviceType);
+ DECL_CONV_STUB(IfcCompressorType);
+ DECL_CONV_STUB(IfcCondenserType);
+ DECL_CONV_STUB(IfcCondition);
+ DECL_CONV_STUB(IfcConditionCriterion);
+ DECL_CONV_STUB(IfcResource);
+ DECL_CONV_STUB(IfcConstructionResource);
+ DECL_CONV_STUB(IfcConstructionEquipmentResource);
+ DECL_CONV_STUB(IfcConstructionMaterialResource);
+ DECL_CONV_STUB(IfcConstructionProductResource);
+ DECL_CONV_STUB(IfcNamedUnit);
+ DECL_CONV_STUB(IfcContextDependentUnit);
+ DECL_CONV_STUB(IfcControllerType);
+ DECL_CONV_STUB(IfcConversionBasedUnit);
+ DECL_CONV_STUB(IfcCooledBeamType);
+ DECL_CONV_STUB(IfcCoolingTowerType);
+ DECL_CONV_STUB(IfcCostItem);
+ DECL_CONV_STUB(IfcCostSchedule);
+ DECL_CONV_STUB(IfcCovering);
+ DECL_CONV_STUB(IfcCoveringType);
+ DECL_CONV_STUB(IfcCraneRailAShapeProfileDef);
+ DECL_CONV_STUB(IfcCraneRailFShapeProfileDef);
+ DECL_CONV_STUB(IfcCrewResource);
+ DECL_CONV_STUB(IfcSolidModel);
+ DECL_CONV_STUB(IfcCsgSolid);
+ DECL_CONV_STUB(IfcCurtainWall);
+ DECL_CONV_STUB(IfcCurtainWallType);
+ DECL_CONV_STUB(IfcCurveBoundedPlane);
+ DECL_CONV_STUB(IfcPresentationStyle);
+ DECL_CONV_STUB(IfcDamperType);
+ DECL_CONV_STUB(IfcDefinedSymbol);
+ DECL_CONV_STUB(IfcDerivedProfileDef);
+ DECL_CONV_STUB(IfcDiameterDimension);
+ DECL_CONV_STUB(IfcDimensionCurve);
+ DECL_CONV_STUB(IfcTerminatorSymbol);
+ DECL_CONV_STUB(IfcDimensionCurveTerminator);
+ DECL_CONV_STUB(IfcDirection);
+ DECL_CONV_STUB(IfcElementComponent);
+ DECL_CONV_STUB(IfcDiscreteAccessory);
+ DECL_CONV_STUB(IfcElementComponentType);
+ DECL_CONV_STUB(IfcDiscreteAccessoryType);
+ DECL_CONV_STUB(IfcDistributionElement);
+ DECL_CONV_STUB(IfcDistributionFlowElement);
+ DECL_CONV_STUB(IfcDistributionChamberElement);
+ DECL_CONV_STUB(IfcDistributionChamberElementType);
+ DECL_CONV_STUB(IfcDistributionControlElement);
+ DECL_CONV_STUB(IfcPort);
+ DECL_CONV_STUB(IfcDistributionPort);
+ DECL_CONV_STUB(IfcDoor);
+ DECL_CONV_STUB(IfcPropertyDefinition);
+ DECL_CONV_STUB(IfcPropertySetDefinition);
+ DECL_CONV_STUB(IfcDoorStyle);
+ DECL_CONV_STUB(IfcDuctFittingType);
+ DECL_CONV_STUB(IfcDuctSegmentType);
+ DECL_CONV_STUB(IfcFlowTreatmentDeviceType);
+ DECL_CONV_STUB(IfcDuctSilencerType);
+ DECL_CONV_STUB(IfcEdge);
+ DECL_CONV_STUB(IfcEdgeCurve);
+ DECL_CONV_STUB(IfcLoop);
+ DECL_CONV_STUB(IfcEdgeLoop);
+ DECL_CONV_STUB(IfcElectricApplianceType);
+ DECL_CONV_STUB(IfcFlowController);
+ DECL_CONV_STUB(IfcElectricDistributionPoint);
+ DECL_CONV_STUB(IfcFlowStorageDeviceType);
+ DECL_CONV_STUB(IfcElectricFlowStorageDeviceType);
+ DECL_CONV_STUB(IfcElectricGeneratorType);
+ DECL_CONV_STUB(IfcElectricHeaterType);
+ DECL_CONV_STUB(IfcElectricMotorType);
+ DECL_CONV_STUB(IfcElectricTimeControlType);
+ DECL_CONV_STUB(IfcSystem);
+ DECL_CONV_STUB(IfcElectricalCircuit);
+ DECL_CONV_STUB(IfcElectricalElement);
+ DECL_CONV_STUB(IfcElementAssembly);
+ DECL_CONV_STUB(IfcElementQuantity);
+ DECL_CONV_STUB(IfcElementarySurface);
+ DECL_CONV_STUB(IfcEllipse);
+ DECL_CONV_STUB(IfcEllipseProfileDef);
+ DECL_CONV_STUB(IfcEnergyConversionDevice);
+ DECL_CONV_STUB(IfcEquipmentElement);
+ DECL_CONV_STUB(IfcEquipmentStandard);
+ DECL_CONV_STUB(IfcEvaporativeCoolerType);
+ DECL_CONV_STUB(IfcEvaporatorType);
+ DECL_CONV_STUB(IfcSweptAreaSolid);
+ DECL_CONV_STUB(IfcExtrudedAreaSolid);
+ DECL_CONV_STUB(IfcFace);
+ DECL_CONV_STUB(IfcFaceBasedSurfaceModel);
+ DECL_CONV_STUB(IfcFaceBound);
+ DECL_CONV_STUB(IfcFaceOuterBound);
+ DECL_CONV_STUB(IfcFaceSurface);
+ DECL_CONV_STUB(IfcManifoldSolidBrep);
+ DECL_CONV_STUB(IfcFacetedBrep);
+ DECL_CONV_STUB(IfcFacetedBrepWithVoids);
+ DECL_CONV_STUB(IfcFanType);
+ DECL_CONV_STUB(IfcFastener);
+ DECL_CONV_STUB(IfcFastenerType);
+ DECL_CONV_STUB(IfcFeatureElementAddition);
+ DECL_CONV_STUB(IfcFillAreaStyleHatching);
+ DECL_CONV_STUB(IfcFillAreaStyleTileSymbolWithStyle);
+ DECL_CONV_STUB(IfcFillAreaStyleTiles);
+ DECL_CONV_STUB(IfcFilterType);
+ DECL_CONV_STUB(IfcFireSuppressionTerminalType);
+ DECL_CONV_STUB(IfcFlowFitting);
+ DECL_CONV_STUB(IfcFlowInstrumentType);
+ DECL_CONV_STUB(IfcFlowMeterType);
+ DECL_CONV_STUB(IfcFlowMovingDevice);
+ DECL_CONV_STUB(IfcFlowSegment);
+ DECL_CONV_STUB(IfcFlowStorageDevice);
+ DECL_CONV_STUB(IfcFlowTerminal);
+ DECL_CONV_STUB(IfcFlowTreatmentDevice);
+ DECL_CONV_STUB(IfcFooting);
+ DECL_CONV_STUB(IfcFurnishingElement);
+ DECL_CONV_STUB(IfcFurnishingElementType);
+ DECL_CONV_STUB(IfcFurnitureStandard);
+ DECL_CONV_STUB(IfcFurnitureType);
+ DECL_CONV_STUB(IfcGasTerminalType);
+ DECL_CONV_STUB(IfcGeometricSet);
+ DECL_CONV_STUB(IfcGeometricCurveSet);
+ DECL_CONV_STUB(IfcRepresentationContext);
+ DECL_CONV_STUB(IfcGeometricRepresentationContext);
+ DECL_CONV_STUB(IfcGeometricRepresentationSubContext);
+ DECL_CONV_STUB(IfcGrid);
+ DECL_CONV_STUB(IfcObjectPlacement);
+ DECL_CONV_STUB(IfcGridPlacement);
+ DECL_CONV_STUB(IfcHeatExchangerType);
+ DECL_CONV_STUB(IfcHumidifierType);
+ DECL_CONV_STUB(IfcInventory);
+ DECL_CONV_STUB(IfcJunctionBoxType);
+ DECL_CONV_STUB(IfcLShapeProfileDef);
+ DECL_CONV_STUB(IfcLaborResource);
+ DECL_CONV_STUB(IfcLampType);
+ DECL_CONV_STUB(IfcLightFixtureType);
+ DECL_CONV_STUB(IfcLightSource);
+ DECL_CONV_STUB(IfcLightSourceAmbient);
+ DECL_CONV_STUB(IfcLightSourceDirectional);
+ DECL_CONV_STUB(IfcLightSourceGoniometric);
+ DECL_CONV_STUB(IfcLightSourcePositional);
+ DECL_CONV_STUB(IfcLightSourceSpot);
+ DECL_CONV_STUB(IfcLine);
+ DECL_CONV_STUB(IfcLinearDimension);
+ DECL_CONV_STUB(IfcLocalPlacement);
+ DECL_CONV_STUB(IfcMappedItem);
+ DECL_CONV_STUB(IfcProductRepresentation);
+ DECL_CONV_STUB(IfcMaterialDefinitionRepresentation);
+ DECL_CONV_STUB(IfcMeasureWithUnit);
+ DECL_CONV_STUB(IfcMechanicalFastener);
+ DECL_CONV_STUB(IfcMechanicalFastenerType);
+ DECL_CONV_STUB(IfcMember);
+ DECL_CONV_STUB(IfcMemberType);
+ DECL_CONV_STUB(IfcMotorConnectionType);
+ DECL_CONV_STUB(IfcProcess);
+ DECL_CONV_STUB(IfcTask);
+ DECL_CONV_STUB(IfcMove);
+ DECL_CONV_STUB(IfcOccupant);
+ DECL_CONV_STUB(IfcOffsetCurve2D);
+ DECL_CONV_STUB(IfcOffsetCurve3D);
+ DECL_CONV_STUB(IfcOneDirectionRepeatFactor);
+ DECL_CONV_STUB(IfcOpenShell);
+ DECL_CONV_STUB(IfcOpeningElement);
+ DECL_CONV_STUB(IfcOrderAction);
+ DECL_CONV_STUB(IfcOrientedEdge);
+ DECL_CONV_STUB(IfcOutletType);
+ DECL_CONV_STUB(IfcPath);
+ DECL_CONV_STUB(IfcPerformanceHistory);
+ DECL_CONV_STUB(IfcPermit);
+ DECL_CONV_STUB(IfcPile);
+ DECL_CONV_STUB(IfcPipeFittingType);
+ DECL_CONV_STUB(IfcPipeSegmentType);
+ DECL_CONV_STUB(IfcPlanarExtent);
+ DECL_CONV_STUB(IfcPlanarBox);
+ DECL_CONV_STUB(IfcPlane);
+ DECL_CONV_STUB(IfcPlate);
+ DECL_CONV_STUB(IfcPlateType);
+ DECL_CONV_STUB(IfcPointOnCurve);
+ DECL_CONV_STUB(IfcPointOnSurface);
+ DECL_CONV_STUB(IfcPolyLoop);
+ DECL_CONV_STUB(IfcPolygonalBoundedHalfSpace);
+ DECL_CONV_STUB(IfcPolyline);
+ DECL_CONV_STUB(IfcPresentationStyleAssignment);
+ DECL_CONV_STUB(IfcProcedure);
+ DECL_CONV_STUB(IfcProductDefinitionShape);
+ DECL_CONV_STUB(IfcProject);
+ DECL_CONV_STUB(IfcProjectOrder);
+ DECL_CONV_STUB(IfcProjectOrderRecord);
+ DECL_CONV_STUB(IfcProjectionCurve);
+ DECL_CONV_STUB(IfcProjectionElement);
+ DECL_CONV_STUB(IfcSimpleProperty);
+ DECL_CONV_STUB(IfcPropertyBoundedValue);
+ DECL_CONV_STUB(IfcPropertyEnumeratedValue);
+ DECL_CONV_STUB(IfcPropertyListValue);
+ DECL_CONV_STUB(IfcPropertyReferenceValue);
+ DECL_CONV_STUB(IfcPropertySet);
+ DECL_CONV_STUB(IfcPropertySingleValue);
+ DECL_CONV_STUB(IfcPropertyTableValue);
+ DECL_CONV_STUB(IfcProtectiveDeviceType);
+ DECL_CONV_STUB(IfcProxy);
+ DECL_CONV_STUB(IfcPumpType);
+ DECL_CONV_STUB(IfcRadiusDimension);
+ DECL_CONV_STUB(IfcRailing);
+ DECL_CONV_STUB(IfcRailingType);
+ DECL_CONV_STUB(IfcRamp);
+ DECL_CONV_STUB(IfcRampFlight);
+ DECL_CONV_STUB(IfcRampFlightType);
+ DECL_CONV_STUB(IfcRationalBezierCurve);
+ DECL_CONV_STUB(IfcRectangleProfileDef);
+ DECL_CONV_STUB(IfcRectangleHollowProfileDef);
+ DECL_CONV_STUB(IfcRectangularPyramid);
+ DECL_CONV_STUB(IfcRectangularTrimmedSurface);
+ DECL_CONV_STUB(IfcReinforcingElement);
+ DECL_CONV_STUB(IfcReinforcingBar);
+ DECL_CONV_STUB(IfcReinforcingMesh);
+ DECL_CONV_STUB(IfcRelationship);
+ DECL_CONV_STUB(IfcRelDecomposes);
+ DECL_CONV_STUB(IfcRelAggregates);
+ DECL_CONV_STUB(IfcRelConnects);
+ DECL_CONV_STUB(IfcRelContainedInSpatialStructure);
+ DECL_CONV_STUB(IfcRelDefines);
+ DECL_CONV_STUB(IfcRelDefinesByProperties);
+ DECL_CONV_STUB(IfcRelFillsElement);
+ DECL_CONV_STUB(IfcRelOverridesProperties);
+ DECL_CONV_STUB(IfcRelVoidsElement);
+ DECL_CONV_STUB(IfcRepresentation);
+ DECL_CONV_STUB(IfcRepresentationMap);
+ DECL_CONV_STUB(IfcRevolvedAreaSolid);
+ DECL_CONV_STUB(IfcRightCircularCone);
+ DECL_CONV_STUB(IfcRightCircularCylinder);
+ DECL_CONV_STUB(IfcRoof);
+ DECL_CONV_STUB(IfcRoundedEdgeFeature);
+ DECL_CONV_STUB(IfcRoundedRectangleProfileDef);
+ DECL_CONV_STUB(IfcSIUnit);
+ DECL_CONV_STUB(IfcSanitaryTerminalType);
+ DECL_CONV_STUB(IfcScheduleTimeControl);
+ DECL_CONV_STUB(IfcSectionedSpine);
+ DECL_CONV_STUB(IfcSensorType);
+ DECL_CONV_STUB(IfcServiceLife);
+ DECL_CONV_STUB(IfcShapeModel);
+ DECL_CONV_STUB(IfcShapeRepresentation);
+ DECL_CONV_STUB(IfcShellBasedSurfaceModel);
+ DECL_CONV_STUB(IfcSite);
+ DECL_CONV_STUB(IfcSlab);
+ DECL_CONV_STUB(IfcSlabType);
+ DECL_CONV_STUB(IfcSpace);
+ DECL_CONV_STUB(IfcSpaceHeaterType);
+ DECL_CONV_STUB(IfcSpaceProgram);
+ DECL_CONV_STUB(IfcSpatialStructureElementType);
+ DECL_CONV_STUB(IfcSpaceType);
+ DECL_CONV_STUB(IfcSphere);
+ DECL_CONV_STUB(IfcStackTerminalType);
+ DECL_CONV_STUB(IfcStair);
+ DECL_CONV_STUB(IfcStairFlight);
+ DECL_CONV_STUB(IfcStairFlightType);
+ DECL_CONV_STUB(IfcStructuralActivity);
+ DECL_CONV_STUB(IfcStructuralAction);
+ DECL_CONV_STUB(IfcStructuralAnalysisModel);
+ DECL_CONV_STUB(IfcStructuralItem);
+ DECL_CONV_STUB(IfcStructuralConnection);
+ DECL_CONV_STUB(IfcStructuralCurveConnection);
+ DECL_CONV_STUB(IfcStructuralMember);
+ DECL_CONV_STUB(IfcStructuralCurveMember);
+ DECL_CONV_STUB(IfcStructuralCurveMemberVarying);
+ DECL_CONV_STUB(IfcStructuralLinearAction);
+ DECL_CONV_STUB(IfcStructuralLinearActionVarying);
+ DECL_CONV_STUB(IfcStructuralLoadGroup);
+ DECL_CONV_STUB(IfcStructuralPlanarAction);
+ DECL_CONV_STUB(IfcStructuralPlanarActionVarying);
+ DECL_CONV_STUB(IfcStructuralPointAction);
+ DECL_CONV_STUB(IfcStructuralPointConnection);
+ DECL_CONV_STUB(IfcStructuralReaction);
+ DECL_CONV_STUB(IfcStructuralPointReaction);
+ DECL_CONV_STUB(IfcStructuralResultGroup);
+ DECL_CONV_STUB(IfcStructuralSurfaceConnection);
+ DECL_CONV_STUB(IfcStructuralSurfaceMember);
+ DECL_CONV_STUB(IfcStructuralSurfaceMemberVarying);
+ DECL_CONV_STUB(IfcStructuredDimensionCallout);
+ DECL_CONV_STUB(IfcStyleModel);
+ DECL_CONV_STUB(IfcStyledRepresentation);
+ DECL_CONV_STUB(IfcSubContractResource);
+ DECL_CONV_STUB(IfcSubedge);
+ DECL_CONV_STUB(IfcSurfaceCurveSweptAreaSolid);
+ DECL_CONV_STUB(IfcSweptSurface);
+ DECL_CONV_STUB(IfcSurfaceOfLinearExtrusion);
+ DECL_CONV_STUB(IfcSurfaceOfRevolution);
+ DECL_CONV_STUB(IfcSurfaceStyle);
+ DECL_CONV_STUB(IfcSurfaceStyleShading);
+ DECL_CONV_STUB(IfcSurfaceStyleRendering);
+ DECL_CONV_STUB(IfcSurfaceStyleWithTextures);
+ DECL_CONV_STUB(IfcSweptDiskSolid);
+ DECL_CONV_STUB(IfcSwitchingDeviceType);
+ DECL_CONV_STUB(IfcSystemFurnitureElementType);
+ DECL_CONV_STUB(IfcTShapeProfileDef);
+ DECL_CONV_STUB(IfcTankType);
+ DECL_CONV_STUB(IfcTendon);
+ DECL_CONV_STUB(IfcTendonAnchor);
+ DECL_CONV_STUB(IfcTextLiteral);
+ DECL_CONV_STUB(IfcTextLiteralWithExtent);
+ DECL_CONV_STUB(IfcTimeSeriesSchedule);
+ DECL_CONV_STUB(IfcTopologyRepresentation);
+ DECL_CONV_STUB(IfcTransformerType);
+ DECL_CONV_STUB(IfcTransportElement);
+ DECL_CONV_STUB(IfcTransportElementType);
+ DECL_CONV_STUB(IfcTrapeziumProfileDef);
+ DECL_CONV_STUB(IfcTrimmedCurve);
+ DECL_CONV_STUB(IfcTubeBundleType);
+ DECL_CONV_STUB(IfcTwoDirectionRepeatFactor);
+ DECL_CONV_STUB(IfcUShapeProfileDef);
+ DECL_CONV_STUB(IfcUnitAssignment);
+ DECL_CONV_STUB(IfcUnitaryEquipmentType);
+ DECL_CONV_STUB(IfcValveType);
+ DECL_CONV_STUB(IfcVector);
+ DECL_CONV_STUB(IfcVertex);
+ DECL_CONV_STUB(IfcVertexLoop);
+ DECL_CONV_STUB(IfcVertexPoint);
+ DECL_CONV_STUB(IfcVibrationIsolatorType);
+ DECL_CONV_STUB(IfcVirtualElement);
+ DECL_CONV_STUB(IfcWall);
+ DECL_CONV_STUB(IfcWallStandardCase);
+ DECL_CONV_STUB(IfcWallType);
+ DECL_CONV_STUB(IfcWasteTerminalType);
+ DECL_CONV_STUB(IfcWindow);
+ DECL_CONV_STUB(IfcWindowStyle);
+ DECL_CONV_STUB(IfcWorkControl);
+ DECL_CONV_STUB(IfcWorkPlan);
+ DECL_CONV_STUB(IfcWorkSchedule);
+ DECL_CONV_STUB(IfcZShapeProfileDef);
+ DECL_CONV_STUB(IfcZone);
#undef DECL_CONV_STUB
diff --git a/src/3rdparty/assimp/code/IFCReaderGen1.cpp b/src/3rdparty/assimp/code/IFCReaderGen1.cpp
index bbf25c232..0377be5d7 100644
--- a/src/3rdparty/assimp/code/IFCReaderGen1.cpp
+++ b/src/3rdparty/assimp/code/IFCReaderGen1.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCReaderGen.h"
@@ -50,996 +50,996 @@ using namespace IFC;
namespace {
- typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
- const SchemaEntry schema_raw[] = {
- SchemaEntry("ifcstairtypeenum",NULL )
-, SchemaEntry("ifcspacetypeenum",NULL )
-, SchemaEntry("ifcwalltypeenum",NULL )
-, SchemaEntry("ifcmonthinyearnumber",NULL )
-, SchemaEntry("ifcheatfluxdensitymeasure",NULL )
-, SchemaEntry("ifckinematicviscositymeasure",NULL )
-, SchemaEntry("ifcsequenceenum",NULL )
-, SchemaEntry("ifcairtoairheatrecoverytypeenum",NULL )
-, SchemaEntry("ifcactorselect",NULL )
-, SchemaEntry("ifctransformertypeenum",NULL )
-, SchemaEntry("ifcunitaryequipmenttypeenum",NULL )
-, SchemaEntry("ifcelectricflowstoragedevicetypeenum",NULL )
-, SchemaEntry("ifcenergysequenceenum",NULL )
-, SchemaEntry("ifcworkcontroltypeenum",NULL )
-, SchemaEntry("ifccurvaturemeasure",NULL )
-, SchemaEntry("ifcparametervalue",NULL )
-, SchemaEntry("ifcappliedvalueselect",NULL )
-, SchemaEntry("ifcwarpingconstantmeasure",NULL )
-, SchemaEntry("ifcarithmeticoperatorenum",NULL )
-, SchemaEntry("ifclinearforcemeasure",NULL )
-, SchemaEntry("ifcwindowpanelpositionenum",NULL )
-, SchemaEntry("ifcflowmetertypeenum",NULL )
-, SchemaEntry("ifcrampflighttypeenum",NULL )
-, SchemaEntry("ifcspecularhighlightselect",NULL )
-, SchemaEntry("ifcactiontypeenum",NULL )
-, SchemaEntry("ifcgeometricprojectionenum",NULL )
-, SchemaEntry("ifctimeseriesdatatypeenum",NULL )
-, SchemaEntry("ifcmagneticfluxmeasure",NULL )
-, SchemaEntry("ifcobjecttypeenum",NULL )
-, SchemaEntry("ifcdataoriginenum",NULL )
-, SchemaEntry("ifcmassdensitymeasure",NULL )
-, SchemaEntry("ifclightfixturetypeenum",NULL )
-, SchemaEntry("ifcservicelifetypeenum",NULL )
-, SchemaEntry("ifcelectricvoltagemeasure",NULL )
-, SchemaEntry("ifcheatingvaluemeasure",NULL )
-, SchemaEntry("ifcpresentabletext",NULL )
-, SchemaEntry("ifcaheadorbehind",NULL )
-, SchemaEntry("ifcsimplevalue",NULL )
-, SchemaEntry("ifcsensortypeenum",NULL )
-, SchemaEntry("ifcderivedunitenum",NULL )
-, SchemaEntry("ifcsizeselect",NULL )
-, SchemaEntry("ifctransportelementtypeenum",NULL )
-, SchemaEntry("ifcinventorytypeenum",NULL )
-, SchemaEntry("ifctextdecoration",NULL )
-, SchemaEntry("ifcdirectionsenseenum",NULL )
-, SchemaEntry("ifcductfittingtypeenum",NULL )
-, SchemaEntry("ifcdocumentstatusenum",NULL )
-, SchemaEntry("ifcslabtypeenum",NULL )
-, SchemaEntry("ifcdoorstyleconstructionenum",NULL )
-, SchemaEntry("ifcvolumemeasure",NULL )
-, SchemaEntry("ifcinductancemeasure",NULL )
-, SchemaEntry("ifccurtainwalltypeenum",NULL )
-, SchemaEntry("ifcsiunitname",NULL )
-, SchemaEntry("ifcspecularexponent",NULL )
-, SchemaEntry("ifcsoundpressuremeasure",NULL )
-, SchemaEntry("ifcanalysistheorytypeenum",NULL )
-, SchemaEntry("ifcgasterminaltypeenum",NULL )
-, SchemaEntry("ifcyearnumber",NULL )
-, SchemaEntry("ifcmodulusofelasticitymeasure",NULL )
-, SchemaEntry("ifcchangeactionenum",NULL )
-, SchemaEntry("ifcdampertypeenum",NULL )
-, SchemaEntry("ifcevaporatortypeenum",NULL )
-, SchemaEntry("ifcionconcentrationmeasure",NULL )
-, SchemaEntry("ifcductsegmenttypeenum",NULL )
-, SchemaEntry("ifcprotectivedevicetypeenum",NULL )
-, SchemaEntry("ifcabsorbeddosemeasure",NULL )
-, SchemaEntry("ifcmassperlengthmeasure",NULL )
-, SchemaEntry("ifctextfontname",NULL )
-, SchemaEntry("ifcorientationselect",NULL )
-, SchemaEntry("ifcilluminancemeasure",NULL )
-, SchemaEntry("ifcfiresuppressionterminaltypeenum",NULL )
-, SchemaEntry("ifcfontstyle",NULL )
-, SchemaEntry("ifcmomentofinertiameasure",NULL )
-, SchemaEntry("ifcmodulusofsubgradereactionmeasure",NULL )
-, SchemaEntry("ifccomplexnumber",NULL )
-, SchemaEntry("ifchumidifiertypeenum",NULL )
-, SchemaEntry("ifcpresentationstyleselect",NULL )
-, SchemaEntry("ifcthermaltransmittancemeasure",NULL )
-, SchemaEntry("ifcribplatedirectionenum",NULL )
-, SchemaEntry("ifcclassificationnotationselect",NULL )
-, SchemaEntry("ifcminuteinhour",NULL )
-, SchemaEntry("ifcinternalorexternalenum",NULL )
-, SchemaEntry("ifcrotationalfrequencymeasure",NULL )
-, SchemaEntry("ifcsanitaryterminaltypeenum",NULL )
-, SchemaEntry("ifcsymbolstyleselect",NULL )
-, SchemaEntry("ifcelementcompositionenum",NULL )
-, SchemaEntry("ifctextpath",NULL )
-, SchemaEntry("ifcpowermeasure",NULL )
-, SchemaEntry("ifcsurfacestyleelementselect",NULL )
-, SchemaEntry("ifcresourceconsumptionenum",NULL )
-, SchemaEntry("ifcelectriccapacitancemeasure",NULL )
-, SchemaEntry("ifclayersetdirectionenum",NULL )
-, SchemaEntry("ifcrailingtypeenum",NULL )
-, SchemaEntry("ifcobjectiveenum",NULL )
-, SchemaEntry("ifcdocumentselect",NULL )
-, SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",NULL )
-, SchemaEntry("ifcthermaladmittancemeasure",NULL )
-, SchemaEntry("ifctransitioncode",NULL )
-, SchemaEntry("ifcconnectiontypeenum",NULL )
-, SchemaEntry("ifcmonetarymeasure",NULL )
-, SchemaEntry("ifcstackterminaltypeenum",NULL )
-, SchemaEntry("ifccolour",NULL )
-, SchemaEntry("ifctext",NULL )
-, SchemaEntry("ifccontextdependentmeasure",NULL )
-, SchemaEntry("ifcthermalconductivitymeasure",NULL )
-, SchemaEntry("ifcprojectedortruelengthenum",NULL )
-, SchemaEntry("ifcpressuremeasure",NULL )
-, SchemaEntry("ifcmoisturediffusivitymeasure",NULL )
-, SchemaEntry("ifcbooleanoperator",NULL )
-, SchemaEntry("ifcpropertysourceenum",NULL )
-, SchemaEntry("ifctimestamp",NULL )
-, SchemaEntry("ifcmaterialselect",NULL )
-, SchemaEntry("ifcgloballyuniqueid",NULL )
-, SchemaEntry("ifcreflectancemethodenum",NULL )
-, SchemaEntry("ifcvaporpermeabilitymeasure",NULL )
-, SchemaEntry("ifctimeseriesscheduletypeenum",NULL )
-, SchemaEntry("ifclinearmomentmeasure",NULL )
-, SchemaEntry("ifcgeometricsetselect",NULL )
-, SchemaEntry("ifcsectionmodulusmeasure",NULL )
-, SchemaEntry("ifcbsplinecurveform",NULL )
-, SchemaEntry("ifcdimensionextentusage",NULL )
-, SchemaEntry("ifcthermalexpansioncoefficientmeasure",NULL )
-, SchemaEntry("ifchourinday",NULL )
-, SchemaEntry("ifclinearvelocitymeasure",NULL )
-, SchemaEntry("ifctorquemeasure",NULL )
-, SchemaEntry("ifctemperaturegradientmeasure",NULL )
-, SchemaEntry("ifcfillstyleselect",NULL )
-, SchemaEntry("ifcelectricchargemeasure",NULL )
-, SchemaEntry("ifcheatexchangertypeenum",NULL )
-, SchemaEntry("ifcelectriccurrentenum",NULL )
-, SchemaEntry("ifcdaylightsavinghour",NULL )
-, SchemaEntry("ifcshell",NULL )
-, SchemaEntry("ifcdoseequivalentmeasure",NULL )
-, SchemaEntry("ifcprojectordertypeenum",NULL )
-, SchemaEntry("ifcderivedmeasurevalue",NULL )
-, SchemaEntry("ifclightdistributioncurveenum",NULL )
-, SchemaEntry("ifcwarpingmomentmeasure",NULL )
-, SchemaEntry("ifcmembertypeenum",NULL )
-, SchemaEntry("ifcsoundpowermeasure",NULL )
-, SchemaEntry("ifctextalignment",NULL )
-, SchemaEntry("ifccurveoredgecurve",NULL )
-, SchemaEntry("ifcmassflowratemeasure",NULL )
-, SchemaEntry("ifcisothermalmoisturecapacitymeasure",NULL )
-, SchemaEntry("ifccsgselect",NULL )
-, SchemaEntry("ifccoolingtowertypeenum",NULL )
-, SchemaEntry("ifcmassmeasure",NULL )
-, SchemaEntry("ifcpileconstructionenum",NULL )
-, SchemaEntry("ifcdoorstyleoperationenum",NULL )
-, SchemaEntry("ifcflowdirectionenum",NULL )
-, SchemaEntry("ifcthermalloadsourceenum",NULL )
-, SchemaEntry("ifclengthmeasure",NULL )
-, SchemaEntry("ifcconstraintenum",NULL )
-, SchemaEntry("ifcaxis2placement",NULL )
-, SchemaEntry("ifcloadgrouptypeenum",NULL )
-, SchemaEntry("ifcvalue",NULL )
-, SchemaEntry("ifcreinforcingbarsurfaceenum",NULL )
-, SchemaEntry("ifcprojectorderrecordtypeenum",NULL )
-, SchemaEntry("ifcdatetimeselect",NULL )
-, SchemaEntry("ifcstructuralsurfacetypeenum",NULL )
-, SchemaEntry("ifcpermeablecoveringoperationenum",NULL )
-, SchemaEntry("ifcfontweight",NULL )
-, SchemaEntry("ifcphmeasure",NULL )
-, SchemaEntry("ifcdescriptivemeasure",NULL )
-, SchemaEntry("ifccurvestylefontselect",NULL )
-, SchemaEntry("ifcunit",NULL )
-, SchemaEntry("ifchatchlinedistanceselect",NULL )
-, SchemaEntry("ifctextstyleselect",NULL )
-, SchemaEntry("ifcmetricvalueselect",NULL )
-, SchemaEntry("ifcvectorordirection",NULL )
-, SchemaEntry("ifcassemblyplaceenum",NULL )
-, SchemaEntry("ifcairterminaltypeenum",NULL )
-, SchemaEntry("ifccoveringtypeenum",NULL )
-, SchemaEntry("ifcplanarforcemeasure",NULL )
-, SchemaEntry("ifcvalvetypeenum",NULL )
-, SchemaEntry("ifcalarmtypeenum",NULL )
-, SchemaEntry("ifcdynamicviscositymeasure",NULL )
-, SchemaEntry("ifccurrencyenum",NULL )
-, SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",NULL )
-, SchemaEntry("ifccablecarrierfittingtypeenum",NULL )
-, SchemaEntry("ifcboolean",NULL )
-, SchemaEntry("ifcactionsourcetypeenum",NULL )
-, SchemaEntry("ifcstructuralactivityassignmentselect",NULL )
-, SchemaEntry("ifcdistributionchamberelementtypeenum",NULL )
-, SchemaEntry("ifcevaporativecoolertypeenum",NULL )
-, SchemaEntry("ifcmagneticfluxdensitymeasure",NULL )
-, SchemaEntry("ifclightdistributiondatasourceselect",NULL )
-, SchemaEntry("ifctubebundletypeenum",NULL )
-, SchemaEntry("ifcaccelerationmeasure",NULL )
-, SchemaEntry("ifcboilertypeenum",NULL )
-, SchemaEntry("ifcramptypeenum",NULL )
-, SchemaEntry("ifcluminousintensitydistributionmeasure",NULL )
-, SchemaEntry("ifctrimmingpreference",NULL )
-, SchemaEntry("ifcspecificheatcapacitymeasure",NULL )
-, SchemaEntry("ifcamountofsubstancemeasure",NULL )
-, SchemaEntry("ifcroleenum",NULL )
-, SchemaEntry("ifcdocumentconfidentialityenum",NULL )
-, SchemaEntry("ifcfrequencymeasure",NULL )
-, SchemaEntry("ifcsectiontypeenum",NULL )
-, SchemaEntry("ifcelementassemblytypeenum",NULL )
-, SchemaEntry("ifcfootingtypeenum",NULL )
-, SchemaEntry("ifclayereditem",NULL )
-, SchemaEntry("ifccablesegmenttypeenum",NULL )
-, SchemaEntry("ifcdefinedsymbolselect",NULL )
-, SchemaEntry("ifcbuildingelementproxytypeenum",NULL )
-, SchemaEntry("ifcelectricgeneratortypeenum",NULL )
-, SchemaEntry("ifcrotationalstiffnessmeasure",NULL )
-, SchemaEntry("ifcspaceheatertypeenum",NULL )
-, SchemaEntry("ifcareameasure",NULL )
-, SchemaEntry("ifclabel",NULL )
-, SchemaEntry("ifccostscheduletypeenum",NULL )
-, SchemaEntry("ifcswitchingdevicetypeenum",NULL )
-, SchemaEntry("ifcelectrictimecontroltypeenum",NULL )
-, SchemaEntry("ifcfiltertypeenum",NULL )
-, SchemaEntry("ifcpositivelengthmeasure",NULL )
-, SchemaEntry("ifcnullstyle",NULL )
-, SchemaEntry("ifcconditioncriterionselect",NULL )
-, SchemaEntry("ifcshearmodulusmeasure",NULL )
-, SchemaEntry("ifcnormalisedratiomeasure",NULL )
-, SchemaEntry("ifcdoorpaneloperationenum",NULL )
-, SchemaEntry("ifcpointorvertexpoint",NULL )
-, SchemaEntry("ifcrooftypeenum",NULL )
-, SchemaEntry("ifccountmeasure",NULL )
-, SchemaEntry("ifcelectricconductancemeasure",NULL )
-, SchemaEntry("ifcproceduretypeenum",NULL )
-, SchemaEntry("ifcflowinstrumenttypeenum",NULL )
-, SchemaEntry("ifcelectricmotortypeenum",NULL )
-, SchemaEntry("ifcsurfaceside",NULL )
-, SchemaEntry("ifcstructuralcurvetypeenum",NULL )
-, SchemaEntry("ifccondensertypeenum",NULL )
-, SchemaEntry("ifclinearstiffnessmeasure",NULL )
-, SchemaEntry("ifcunitenum",NULL )
-, SchemaEntry("ifcoccupanttypeenum",NULL )
-, SchemaEntry("ifcthermalloadtypeenum",NULL )
-, SchemaEntry("ifcreinforcingbarroleenum",NULL )
-, SchemaEntry("ifcbenchmarkenum",NULL )
-, SchemaEntry("ifcpositiveplaneanglemeasure",NULL )
-, SchemaEntry("ifctexttransformation",NULL )
-, SchemaEntry("ifcdraughtingcalloutelement",NULL )
-, SchemaEntry("ifcratiomeasure",NULL )
-, SchemaEntry("ifcsolidanglemeasure",NULL )
-, SchemaEntry("ifcpipesegmenttypeenum",NULL )
-, SchemaEntry("ifccablecarriersegmenttypeenum",NULL )
-, SchemaEntry("ifccolourorfactor",NULL )
-, SchemaEntry("ifcidentifier",NULL )
-, SchemaEntry("ifctendontypeenum",NULL )
-, SchemaEntry("ifccontrollertypeenum",NULL )
-, SchemaEntry("ifcradioactivitymeasure",NULL )
-, SchemaEntry("ifctimemeasure",NULL )
-, SchemaEntry("ifcpumptypeenum",NULL )
-, SchemaEntry("ifcelectricheatertypeenum",NULL )
-, SchemaEntry("ifcbeamtypeenum",NULL )
-, SchemaEntry("ifcstateenum",NULL )
-, SchemaEntry("ifcsiprefix",NULL )
-, SchemaEntry("ifcnumericmeasure",NULL )
-, SchemaEntry("ifcoutlettypeenum",NULL )
-, SchemaEntry("ifccompoundplaneanglemeasure",NULL )
-, SchemaEntry("ifcservicelifefactortypeenum",NULL )
-, SchemaEntry("ifclogicaloperatorenum",NULL )
-, SchemaEntry("ifcbooleanoperand",NULL )
-, SchemaEntry("ifcobjectreferenceselect",NULL )
-, SchemaEntry("ifccooledbeamtypeenum",NULL )
-, SchemaEntry("ifcductsilencertypeenum",NULL )
-, SchemaEntry("ifcsectionalareaintegralmeasure",NULL )
-, SchemaEntry("ifcfontvariant",NULL )
-, SchemaEntry("ifcvolumetricflowratemeasure",NULL )
-, SchemaEntry("ifcplatetypeenum",NULL )
-, SchemaEntry("ifcenvironmentalimpactcategoryenum",NULL )
-, SchemaEntry("ifcvibrationisolatortypeenum",NULL )
-, SchemaEntry("ifcthermodynamictemperaturemeasure",NULL )
-, SchemaEntry("ifcrotationalmassmeasure",NULL )
-, SchemaEntry("ifcsecondinminute",NULL )
-, SchemaEntry("ifcdayinmonthnumber",NULL )
-, SchemaEntry("ifcdimensioncount",NULL )
-, SchemaEntry("ifcwindowstyleoperationenum",NULL )
-, SchemaEntry("ifcthermalresistancemeasure",NULL )
-, SchemaEntry("ifcmeasurevalue",NULL )
-, SchemaEntry("ifcwindowpaneloperationenum",NULL )
-, SchemaEntry("ifcchillertypeenum",NULL )
-, SchemaEntry("ifcpositiveratiomeasure",NULL )
-, SchemaEntry("ifcinteger",NULL )
-, SchemaEntry("ifclogical",NULL )
-, SchemaEntry("ifcjunctionboxtypeenum",NULL )
-, SchemaEntry("ifcaddresstypeenum",NULL )
-, SchemaEntry("ifcwasteterminaltypeenum",NULL )
-, SchemaEntry("ifctrimmingselect",NULL )
-, SchemaEntry("ifclightemissionsourceenum",NULL )
-, SchemaEntry("ifcsoundscaleenum",NULL )
-, SchemaEntry("ifcluminousfluxmeasure",NULL )
-, SchemaEntry("ifcelectricresistancemeasure",NULL )
-, SchemaEntry("ifcintegercountratemeasure",NULL )
-, SchemaEntry("ifcphysicalorvirtualenum",NULL )
-, SchemaEntry("ifcmolecularweightmeasure",NULL )
-, SchemaEntry("ifcprofiletypeenum",NULL )
-, SchemaEntry("ifcboxalignment",NULL )
-, SchemaEntry("ifcglobalorlocalenum",NULL )
-, SchemaEntry("ifcspecularroughness",NULL )
-, SchemaEntry("ifclamptypeenum",NULL )
-, SchemaEntry("ifcpiletypeenum",NULL )
-, SchemaEntry("ifcelectriccurrentmeasure",NULL )
-, SchemaEntry("ifcfantypeenum",NULL )
-, SchemaEntry("ifcsurfaceorfacesurface",NULL )
-, SchemaEntry("ifcpipefittingtypeenum",NULL )
-, SchemaEntry("ifctanktypeenum",NULL )
-, SchemaEntry("ifccurvefontorscaledcurvefontselect",NULL )
-, SchemaEntry("ifcwindowstyleconstructionenum",NULL )
-, SchemaEntry("ifcairterminalboxtypeenum",NULL )
-, SchemaEntry("ifcstairflighttypeenum",NULL )
-, SchemaEntry("ifcluminousintensitymeasure",NULL )
-, SchemaEntry("ifcmotorconnectiontypeenum",NULL )
-, SchemaEntry("ifcplaneanglemeasure",NULL )
-, SchemaEntry("ifcactuatortypeenum",NULL )
-, SchemaEntry("ifccolumntypeenum",NULL )
-, SchemaEntry("ifctextfontselect",NULL )
-, SchemaEntry("ifcdoorpanelpositionenum",NULL )
-, SchemaEntry("ifccoiltypeenum",NULL )
-, SchemaEntry("ifcangularvelocitymeasure",NULL )
-, SchemaEntry("ifcanalysismodeltypeenum",NULL )
-, SchemaEntry("ifclibraryselect",NULL )
-, SchemaEntry("ifcforcemeasure",NULL )
-, SchemaEntry("ifcfillareastyletileshapeselect",NULL )
-, SchemaEntry("ifcelectricappliancetypeenum",NULL )
-, SchemaEntry("ifcsurfacetextureenum",NULL )
-, SchemaEntry("ifccharacterstyleselect",NULL )
-, SchemaEntry("ifcenergymeasure",NULL )
-, SchemaEntry("ifcreal",NULL )
-, SchemaEntry("ifccompressortypeenum",NULL )
-, SchemaEntry("ifcelectricdistributionpointfunctionenum",NULL )
-, SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct )
-, SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct )
-, SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct )
-, SchemaEntry("ifctypeproduct",&STEP::ObjectHelper<IfcTypeProduct,2>::Construct )
-, SchemaEntry("ifcelementtype",&STEP::ObjectHelper<IfcElementType,1>::Construct )
-, SchemaEntry("ifcdistributionelementtype",&STEP::ObjectHelper<IfcDistributionElementType,0>::Construct )
-, SchemaEntry("ifcdistributionflowelementtype",&STEP::ObjectHelper<IfcDistributionFlowElementType,0>::Construct )
-, SchemaEntry("ifcflowcontrollertype",&STEP::ObjectHelper<IfcFlowControllerType,0>::Construct )
-, SchemaEntry("ifcelectrictimecontroltype",&STEP::ObjectHelper<IfcElectricTimeControlType,1>::Construct )
-, SchemaEntry("ifcrepresentation",&STEP::ObjectHelper<IfcRepresentation,4>::Construct )
-, SchemaEntry("ifcshapemodel",&STEP::ObjectHelper<IfcShapeModel,0>::Construct )
-, SchemaEntry("ifctopologyrepresentation",&STEP::ObjectHelper<IfcTopologyRepresentation,0>::Construct )
-, SchemaEntry("ifcrelationship",&STEP::ObjectHelper<IfcRelationship,0>::Construct )
-, SchemaEntry("ifcrelconnects",&STEP::ObjectHelper<IfcRelConnects,0>::Construct )
-, SchemaEntry("ifcrelcoversspaces",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowfittingtype",&STEP::ObjectHelper<IfcFlowFittingType,0>::Construct )
-, SchemaEntry("ifccablecarrierfittingtype",&STEP::ObjectHelper<IfcCableCarrierFittingType,1>::Construct )
-, SchemaEntry("ifcstructuralconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcslippageconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcenergyconversiondevicetype",&STEP::ObjectHelper<IfcEnergyConversionDeviceType,0>::Construct )
-, SchemaEntry("ifccoiltype",&STEP::ObjectHelper<IfcCoilType,1>::Construct )
-, SchemaEntry("ifcobject",&STEP::ObjectHelper<IfcObject,1>::Construct )
-, SchemaEntry("ifccontrol",&STEP::ObjectHelper<IfcControl,0>::Construct )
-, SchemaEntry("ifcperformancehistory",&STEP::ObjectHelper<IfcPerformanceHistory,1>::Construct )
-, SchemaEntry("ifcrepresentationitem",&STEP::ObjectHelper<IfcRepresentationItem,0>::Construct )
-, SchemaEntry("ifcgeometricrepresentationitem",&STEP::ObjectHelper<IfcGeometricRepresentationItem,0>::Construct )
-, SchemaEntry("ifctextliteral",&STEP::ObjectHelper<IfcTextLiteral,3>::Construct )
-, SchemaEntry("ifctextliteralwithextent",&STEP::ObjectHelper<IfcTextLiteralWithExtent,2>::Construct )
-, SchemaEntry("ifcproductrepresentation",&STEP::ObjectHelper<IfcProductRepresentation,3>::Construct )
-, SchemaEntry("ifcproduct",&STEP::ObjectHelper<IfcProduct,2>::Construct )
-, SchemaEntry("ifcelement",&STEP::ObjectHelper<IfcElement,1>::Construct )
-, SchemaEntry("ifcdistributionelement",&STEP::ObjectHelper<IfcDistributionElement,0>::Construct )
-, SchemaEntry("ifcdistributionflowelement",&STEP::ObjectHelper<IfcDistributionFlowElement,0>::Construct )
-, SchemaEntry("ifccurve",&STEP::ObjectHelper<IfcCurve,0>::Construct )
-, SchemaEntry("ifcboundedcurve",&STEP::ObjectHelper<IfcBoundedCurve,0>::Construct )
-, SchemaEntry("ifccompositecurve",&STEP::ObjectHelper<IfcCompositeCurve,2>::Construct )
-, SchemaEntry("ifc2dcompositecurve",&STEP::ObjectHelper<Ifc2DCompositeCurve,0>::Construct )
-, SchemaEntry("ifcboundarycondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcboundaryfacecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccartesiantransformationoperator",&STEP::ObjectHelper<IfcCartesianTransformationOperator,4>::Construct )
-, SchemaEntry("ifccartesiantransformationoperator3d",&STEP::ObjectHelper<IfcCartesianTransformationOperator3D,1>::Construct )
-, SchemaEntry("ifcproperty",&STEP::ObjectHelper<IfcProperty,2>::Construct )
-, SchemaEntry("ifcsimpleproperty",&STEP::ObjectHelper<IfcSimpleProperty,0>::Construct )
-, SchemaEntry("ifcpropertyenumeratedvalue",&STEP::ObjectHelper<IfcPropertyEnumeratedValue,2>::Construct )
-, SchemaEntry("ifcpresentationlayerassignment",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpresentationlayerwithstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcbuildingelementtype",&STEP::ObjectHelper<IfcBuildingElementType,0>::Construct )
-, SchemaEntry("ifcstairflighttype",&STEP::ObjectHelper<IfcStairFlightType,1>::Construct )
-, SchemaEntry("ifcsurface",&STEP::ObjectHelper<IfcSurface,0>::Construct )
-, SchemaEntry("ifcelementarysurface",&STEP::ObjectHelper<IfcElementarySurface,1>::Construct )
-, SchemaEntry("ifcplane",&STEP::ObjectHelper<IfcPlane,0>::Construct )
-, SchemaEntry("ifcbooleanresult",&STEP::ObjectHelper<IfcBooleanResult,3>::Construct )
-, SchemaEntry("ifcbooleanclippingresult",&STEP::ObjectHelper<IfcBooleanClippingResult,0>::Construct )
-, SchemaEntry("ifcsolidmodel",&STEP::ObjectHelper<IfcSolidModel,0>::Construct )
-, SchemaEntry("ifcmanifoldsolidbrep",&STEP::ObjectHelper<IfcManifoldSolidBrep,1>::Construct )
-, SchemaEntry("ifcprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcgeneralprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowterminaltype",&STEP::ObjectHelper<IfcFlowTerminalType,0>::Construct )
-, SchemaEntry("ifcstackterminaltype",&STEP::ObjectHelper<IfcStackTerminalType,1>::Construct )
-, SchemaEntry("ifcstructuralitem",&STEP::ObjectHelper<IfcStructuralItem,0>::Construct )
-, SchemaEntry("ifcstructuralconnection",&STEP::ObjectHelper<IfcStructuralConnection,1>::Construct )
-, SchemaEntry("ifcstructuralcurveconnection",&STEP::ObjectHelper<IfcStructuralCurveConnection,0>::Construct )
-, SchemaEntry("ifcjunctionboxtype",&STEP::ObjectHelper<IfcJunctionBoxType,1>::Construct )
-, SchemaEntry("ifcrelassociates",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociatesconstraint",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpropertydefinition",&STEP::ObjectHelper<IfcPropertyDefinition,0>::Construct )
-, SchemaEntry("ifcpropertysetdefinition",&STEP::ObjectHelper<IfcPropertySetDefinition,0>::Construct )
-, SchemaEntry("ifcdoorpanelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconstraintrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcspacethermalloadproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifclibraryinformation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcprocess",&STEP::ObjectHelper<IfcProcess,0>::Construct )
-, SchemaEntry("ifctask",&STEP::ObjectHelper<IfcTask,5>::Construct )
-, SchemaEntry("ifcappliedvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcenvironmentalimpactvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelfillselement",&STEP::ObjectHelper<IfcRelFillsElement,2>::Construct )
-, SchemaEntry("ifcprocedure",&STEP::ObjectHelper<IfcProcedure,3>::Construct )
-, SchemaEntry("ifcstructuralload",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadstatic",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadsingledisplacement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcproxy",&STEP::ObjectHelper<IfcProxy,2>::Construct )
-, SchemaEntry("ifccurvestylefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcresource",&STEP::ObjectHelper<IfcResource,0>::Construct )
-, SchemaEntry("ifcconstructionresource",&STEP::ObjectHelper<IfcConstructionResource,4>::Construct )
-, SchemaEntry("ifcsubcontractresource",&STEP::ObjectHelper<IfcSubContractResource,2>::Construct )
-, SchemaEntry("ifccalendardate",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdocumentelectronicformat",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelcontainedinspatialstructure",&STEP::ObjectHelper<IfcRelContainedInSpatialStructure,2>::Construct )
-, SchemaEntry("ifcmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcproductsofcombustionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctopologicalrepresentationitem",&STEP::ObjectHelper<IfcTopologicalRepresentationItem,0>::Construct )
-, SchemaEntry("ifcedge",&STEP::ObjectHelper<IfcEdge,2>::Construct )
-, SchemaEntry("ifcedgecurve",&STEP::ObjectHelper<IfcEdgeCurve,2>::Construct )
-, SchemaEntry("ifcplatetype",&STEP::ObjectHelper<IfcPlateType,1>::Construct )
-, SchemaEntry("ifcobjectplacement",&STEP::ObjectHelper<IfcObjectPlacement,0>::Construct )
-, SchemaEntry("ifcgridplacement",&STEP::ObjectHelper<IfcGridPlacement,2>::Construct )
-, SchemaEntry("ifcfiresuppressionterminaltype",&STEP::ObjectHelper<IfcFireSuppressionTerminalType,1>::Construct )
-, SchemaEntry("ifcmechanicalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowstoragedevice",&STEP::ObjectHelper<IfcFlowStorageDevice,0>::Construct )
-, SchemaEntry("ifcperson",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsweptsurface",&STEP::ObjectHelper<IfcSweptSurface,2>::Construct )
-, SchemaEntry("ifcsurfaceofrevolution",&STEP::ObjectHelper<IfcSurfaceOfRevolution,1>::Construct )
-, SchemaEntry("ifcorientededge",&STEP::ObjectHelper<IfcOrientedEdge,2>::Construct )
-, SchemaEntry("ifcownerhistory",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassigns",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassignstoactor",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdirection",&STEP::ObjectHelper<IfcDirection,1>::Construct )
-, SchemaEntry("ifcreinforcementbarproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcprofiledef",&STEP::ObjectHelper<IfcProfileDef,2>::Construct )
-, SchemaEntry("ifcparameterizedprofiledef",&STEP::ObjectHelper<IfcParameterizedProfileDef,1>::Construct )
-, SchemaEntry("ifccshapeprofiledef",&STEP::ObjectHelper<IfcCShapeProfileDef,6>::Construct )
-, SchemaEntry("ifcfeatureelement",&STEP::ObjectHelper<IfcFeatureElement,0>::Construct )
-, SchemaEntry("ifcfeatureelementsubtraction",&STEP::ObjectHelper<IfcFeatureElementSubtraction,0>::Construct )
-, SchemaEntry("ifcedgefeature",&STEP::ObjectHelper<IfcEdgeFeature,1>::Construct )
-, SchemaEntry("ifcchamferedgefeature",&STEP::ObjectHelper<IfcChamferEdgeFeature,2>::Construct )
-, SchemaEntry("ifcbuildingelement",&STEP::ObjectHelper<IfcBuildingElement,0>::Construct )
-, SchemaEntry("ifccolumn",&STEP::ObjectHelper<IfcColumn,0>::Construct )
-, SchemaEntry("ifcpropertyreferencevalue",&STEP::ObjectHelper<IfcPropertyReferenceValue,2>::Construct )
-, SchemaEntry("ifcmaterialclassificationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelectricmotortype",&STEP::ObjectHelper<IfcElectricMotorType,1>::Construct )
-, SchemaEntry("ifcspatialstructureelementtype",&STEP::ObjectHelper<IfcSpatialStructureElementType,0>::Construct )
-, SchemaEntry("ifcspacetype",&STEP::ObjectHelper<IfcSpaceType,1>::Construct )
-, SchemaEntry("ifcexternalreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcexternallydefinedhatchstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccolumntype",&STEP::ObjectHelper<IfcColumnType,1>::Construct )
-, SchemaEntry("ifccranerailashapeprofiledef",&STEP::ObjectHelper<IfcCraneRailAShapeProfileDef,12>::Construct )
-, SchemaEntry("ifccondensertype",&STEP::ObjectHelper<IfcCondenserType,1>::Construct )
-, SchemaEntry("ifcrelconnectselements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelconnectswithrealizingelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccircleprofiledef",&STEP::ObjectHelper<IfcCircleProfileDef,1>::Construct )
-, SchemaEntry("ifccirclehollowprofiledef",&STEP::ObjectHelper<IfcCircleHollowProfileDef,1>::Construct )
-, SchemaEntry("ifcorganizationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcplacement",&STEP::ObjectHelper<IfcPlacement,1>::Construct )
-, SchemaEntry("ifcaxis2placement3d",&STEP::ObjectHelper<IfcAxis2Placement3D,2>::Construct )
-, SchemaEntry("ifcpresentationstyle",&STEP::ObjectHelper<IfcPresentationStyle,1>::Construct )
-, SchemaEntry("ifccurvestyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcequipmentelement",&STEP::ObjectHelper<IfcEquipmentElement,0>::Construct )
-, SchemaEntry("ifccompositecurvesegment",&STEP::ObjectHelper<IfcCompositeCurveSegment,3>::Construct )
-, SchemaEntry("ifcrectangleprofiledef",&STEP::ObjectHelper<IfcRectangleProfileDef,2>::Construct )
-, SchemaEntry("ifcphysicalquantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcphysicalcomplexquantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociateslibrary",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelsequence",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcbuildingelementproxy",&STEP::ObjectHelper<IfcBuildingElementProxy,1>::Construct )
-, SchemaEntry("ifcdistributioncontrolelementtype",&STEP::ObjectHelper<IfcDistributionControlElementType,0>::Construct )
-, SchemaEntry("ifcflowinstrumenttype",&STEP::ObjectHelper<IfcFlowInstrumentType,1>::Construct )
-, SchemaEntry("ifcdraughtingcallout",&STEP::ObjectHelper<IfcDraughtingCallout,1>::Construct )
-, SchemaEntry("ifcdimensioncurvedirectedcallout",&STEP::ObjectHelper<IfcDimensionCurveDirectedCallout,0>::Construct )
-, SchemaEntry("ifclineardimension",&STEP::ObjectHelper<IfcLinearDimension,0>::Construct )
-, SchemaEntry("ifcelementassembly",&STEP::ObjectHelper<IfcElementAssembly,2>::Construct )
-, SchemaEntry("ifcdraughtingcalloutrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccsgprimitive3d",&STEP::ObjectHelper<IfcCsgPrimitive3D,1>::Construct )
-, SchemaEntry("ifcrightcircularcone",&STEP::ObjectHelper<IfcRightCircularCone,2>::Construct )
-, SchemaEntry("ifcexternallydefinedsurfacestyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcprojectorder",&STEP::ObjectHelper<IfcProjectOrder,3>::Construct )
-, SchemaEntry("ifcpropertyconstraintrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifclshapeprofiledef",&STEP::ObjectHelper<IfcLShapeProfileDef,8>::Construct )
-, SchemaEntry("ifcangulardimension",&STEP::ObjectHelper<IfcAngularDimension,0>::Construct )
-, SchemaEntry("ifctextstylefordefinedfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifclocalplacement",&STEP::ObjectHelper<IfcLocalPlacement,2>::Construct )
-, SchemaEntry("ifcsweptareasolid",&STEP::ObjectHelper<IfcSweptAreaSolid,2>::Construct )
-, SchemaEntry("ifcrevolvedareasolid",&STEP::ObjectHelper<IfcRevolvedAreaSolid,2>::Construct )
-, SchemaEntry("ifcstructuralsurfaceconnection",&STEP::ObjectHelper<IfcStructuralSurfaceConnection,0>::Construct )
-, SchemaEntry("ifcradiusdimension",&STEP::ObjectHelper<IfcRadiusDimension,0>::Construct )
-, SchemaEntry("ifcsweptdisksolid",&STEP::ObjectHelper<IfcSweptDiskSolid,5>::Construct )
-, SchemaEntry("ifchalfspacesolid",&STEP::ObjectHelper<IfcHalfSpaceSolid,2>::Construct )
-, SchemaEntry("ifcpolygonalboundedhalfspace",&STEP::ObjectHelper<IfcPolygonalBoundedHalfSpace,2>::Construct )
-, SchemaEntry("ifctimeseriesschedule",&STEP::ObjectHelper<IfcTimeSeriesSchedule,3>::Construct )
-, SchemaEntry("ifcdimensioncalloutrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccooledbeamtype",&STEP::ObjectHelper<IfcCooledBeamType,1>::Construct )
-, SchemaEntry("ifcproject",&STEP::ObjectHelper<IfcProject,4>::Construct )
-, SchemaEntry("ifcapprovalrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcevaporatortype",&STEP::ObjectHelper<IfcEvaporatorType,1>::Construct )
-, SchemaEntry("ifclaborresource",&STEP::ObjectHelper<IfcLaborResource,1>::Construct )
-, SchemaEntry("ifcstructuralloadsingledisplacementdistortion",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpropertyboundedvalue",&STEP::ObjectHelper<IfcPropertyBoundedValue,3>::Construct )
-, SchemaEntry("ifcrampflighttype",&STEP::ObjectHelper<IfcRampFlightType,1>::Construct )
-, SchemaEntry("ifcmember",&STEP::ObjectHelper<IfcMember,0>::Construct )
-, SchemaEntry("ifcstructuralloadplanarforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctubebundletype",&STEP::ObjectHelper<IfcTubeBundleType,1>::Construct )
-, SchemaEntry("ifcvalvetype",&STEP::ObjectHelper<IfcValveType,1>::Construct )
-, SchemaEntry("ifcexternallydefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctrimmedcurve",&STEP::ObjectHelper<IfcTrimmedCurve,5>::Construct )
-, SchemaEntry("ifcreldefines",&STEP::ObjectHelper<IfcRelDefines,1>::Construct )
-, SchemaEntry("ifcreldefinesbyproperties",&STEP::ObjectHelper<IfcRelDefinesByProperties,1>::Construct )
-, SchemaEntry("ifcrelassignstocontrol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcactor",&STEP::ObjectHelper<IfcActor,1>::Construct )
-, SchemaEntry("ifcoccupant",&STEP::ObjectHelper<IfcOccupant,1>::Construct )
-, SchemaEntry("ifchumidifiertype",&STEP::ObjectHelper<IfcHumidifierType,1>::Construct )
-, SchemaEntry("ifcarbitraryopenprofiledef",&STEP::ObjectHelper<IfcArbitraryOpenProfileDef,1>::Construct )
-, SchemaEntry("ifcrelassignstoprojectorder",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpermit",&STEP::ObjectHelper<IfcPermit,1>::Construct )
-, SchemaEntry("ifcoffsetcurve3d",&STEP::ObjectHelper<IfcOffsetCurve3D,4>::Construct )
-, SchemaEntry("ifclightsource",&STEP::ObjectHelper<IfcLightSource,4>::Construct )
-, SchemaEntry("ifclightsourcepositional",&STEP::ObjectHelper<IfcLightSourcePositional,5>::Construct )
-, SchemaEntry("ifcsurfacetexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcblobtexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccompositeprofiledef",&STEP::ObjectHelper<IfcCompositeProfileDef,2>::Construct )
-, SchemaEntry("ifcdocumentinformation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsurfacestylelighting",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcphysicalsimplequantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcquantityarea",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcclassificationnotation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcramp",&STEP::ObjectHelper<IfcRamp,1>::Construct )
-, SchemaEntry("ifcpredefineditem",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpredefinedcurvefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpredefinedcolour",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccurrencyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowmovingdevice",&STEP::ObjectHelper<IfcFlowMovingDevice,0>::Construct )
-, SchemaEntry("ifcspaceheatertype",&STEP::ObjectHelper<IfcSpaceHeaterType,1>::Construct )
-, SchemaEntry("ifclamptype",&STEP::ObjectHelper<IfcLampType,1>::Construct )
-, SchemaEntry("ifcbuildingelementcomponent",&STEP::ObjectHelper<IfcBuildingElementComponent,0>::Construct )
-, SchemaEntry("ifcreinforcingelement",&STEP::ObjectHelper<IfcReinforcingElement,1>::Construct )
-, SchemaEntry("ifcreinforcingbar",&STEP::ObjectHelper<IfcReinforcingBar,5>::Construct )
-, SchemaEntry("ifcelectricheatertype",&STEP::ObjectHelper<IfcElectricHeaterType,1>::Construct )
-, SchemaEntry("ifctshapeprofiledef",&STEP::ObjectHelper<IfcTShapeProfileDef,10>::Construct )
-, SchemaEntry("ifcconstraint",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcobjective",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralactivity",&STEP::ObjectHelper<IfcStructuralActivity,2>::Construct )
-, SchemaEntry("ifcstructuralaction",&STEP::ObjectHelper<IfcStructuralAction,2>::Construct )
-, SchemaEntry("ifctexturecoordinate",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctexturemap",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcmonetaryunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcquantitytime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctablerow",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifclightdistributiondata",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcductfittingtype",&STEP::ObjectHelper<IfcDuctFittingType,1>::Construct )
-, SchemaEntry("ifccartesiantransformationoperator2d",&STEP::ObjectHelper<IfcCartesianTransformationOperator2D,0>::Construct )
-, SchemaEntry("ifccartesiantransformationoperator2dnonuniform",&STEP::ObjectHelper<IfcCartesianTransformationOperator2DnonUniform,1>::Construct )
-, SchemaEntry("ifcclassificationnotationfacet",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociatesapproval",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdraughtingpredefinedcurvefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadsingleforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadsingleforcewarping",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccurvestylefontandscaling",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcvirtualelement",&STEP::ObjectHelper<IfcVirtualElement,0>::Construct )
-, SchemaEntry("ifcrightcircularcylinder",&STEP::ObjectHelper<IfcRightCircularCylinder,2>::Construct )
-, SchemaEntry("ifcoutlettype",&STEP::ObjectHelper<IfcOutletType,1>::Construct )
-, SchemaEntry("ifcreldecomposes",&STEP::ObjectHelper<IfcRelDecomposes,2>::Construct )
-, SchemaEntry("ifcrelnests",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccovering",&STEP::ObjectHelper<IfcCovering,1>::Construct )
-, SchemaEntry("ifcexternallydefinedsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcirregulartimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpolyline",&STEP::ObjectHelper<IfcPolyline,1>::Construct )
-, SchemaEntry("ifcpath",&STEP::ObjectHelper<IfcPath,1>::Construct )
-, SchemaEntry("ifcelementcomponent",&STEP::ObjectHelper<IfcElementComponent,0>::Construct )
-, SchemaEntry("ifcfastener",&STEP::ObjectHelper<IfcFastener,0>::Construct )
-, SchemaEntry("ifcmappeditem",&STEP::ObjectHelper<IfcMappedItem,2>::Construct )
-, SchemaEntry("ifcmetric",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdocumentreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsectionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrectangularpyramid",&STEP::ObjectHelper<IfcRectangularPyramid,3>::Construct )
-, SchemaEntry("ifcrelreferencedinspatialstructure",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccrewresource",&STEP::ObjectHelper<IfcCrewResource,0>::Construct )
-, SchemaEntry("ifcnamedunit",&STEP::ObjectHelper<IfcNamedUnit,2>::Construct )
-, SchemaEntry("ifccontextdependentunit",&STEP::ObjectHelper<IfcContextDependentUnit,1>::Construct )
-, SchemaEntry("ifcunitaryequipmenttype",&STEP::ObjectHelper<IfcUnitaryEquipmentType,1>::Construct )
-, SchemaEntry("ifcroof",&STEP::ObjectHelper<IfcRoof,1>::Construct )
-, SchemaEntry("ifcrelassignstasks",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralmember",&STEP::ObjectHelper<IfcStructuralMember,0>::Construct )
-, SchemaEntry("ifcrelconnectsports",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstylemodel",&STEP::ObjectHelper<IfcStyleModel,0>::Construct )
-, SchemaEntry("ifcstyledrepresentation",&STEP::ObjectHelper<IfcStyledRepresentation,0>::Construct )
-, SchemaEntry("ifcspatialstructureelement",&STEP::ObjectHelper<IfcSpatialStructureElement,2>::Construct )
-, SchemaEntry("ifcbuilding",&STEP::ObjectHelper<IfcBuilding,3>::Construct )
-, SchemaEntry("ifcconnectedfaceset",&STEP::ObjectHelper<IfcConnectedFaceSet,1>::Construct )
-, SchemaEntry("ifcopenshell",&STEP::ObjectHelper<IfcOpenShell,0>::Construct )
-, SchemaEntry("ifcfacetedbrep",&STEP::ObjectHelper<IfcFacetedBrep,0>::Construct )
-, SchemaEntry("ifclocaltime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcmechanicalconcretematerialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconic",&STEP::ObjectHelper<IfcConic,1>::Construct )
-, SchemaEntry("ifccoveringtype",&STEP::ObjectHelper<IfcCoveringType,1>::Construct )
-, SchemaEntry("ifcroundedrectangleprofiledef",&STEP::ObjectHelper<IfcRoundedRectangleProfileDef,1>::Construct )
-, SchemaEntry("ifcairterminaltype",&STEP::ObjectHelper<IfcAirTerminalType,1>::Construct )
-, SchemaEntry("ifcflowmovingdevicetype",&STEP::ObjectHelper<IfcFlowMovingDeviceType,0>::Construct )
-, SchemaEntry("ifccompressortype",&STEP::ObjectHelper<IfcCompressorType,1>::Construct )
-, SchemaEntry("ifcwindowpanelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpredefinedsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpredefinedterminatorsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcishapeprofiledef",&STEP::ObjectHelper<IfcIShapeProfileDef,5>::Construct )
-, SchemaEntry("ifcasymmetricishapeprofiledef",&STEP::ObjectHelper<IfcAsymmetricIShapeProfileDef,4>::Construct )
-, SchemaEntry("ifccontrollertype",&STEP::ObjectHelper<IfcControllerType,1>::Construct )
-, SchemaEntry("ifcrailing",&STEP::ObjectHelper<IfcRailing,1>::Construct )
-, SchemaEntry("ifcgroup",&STEP::ObjectHelper<IfcGroup,0>::Construct )
-, SchemaEntry("ifcasset",&STEP::ObjectHelper<IfcAsset,9>::Construct )
-, SchemaEntry("ifcmaterialdefinitionrepresentation",&STEP::ObjectHelper<IfcMaterialDefinitionRepresentation,1>::Construct )
-, SchemaEntry("ifccurvestylefontpattern",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcapprovalpropertyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrailingtype",&STEP::ObjectHelper<IfcRailingType,1>::Construct )
-, SchemaEntry("ifcwall",&STEP::ObjectHelper<IfcWall,0>::Construct )
-, SchemaEntry("ifcclassificationitem",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralpointconnection",&STEP::ObjectHelper<IfcStructuralPointConnection,0>::Construct )
-, SchemaEntry("ifcconnectiongeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconnectionpointgeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctimeseriesvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpropertylistvalue",&STEP::ObjectHelper<IfcPropertyListValue,2>::Construct )
-, SchemaEntry("ifcfurniturestandard",&STEP::ObjectHelper<IfcFurnitureStandard,0>::Construct )
-, SchemaEntry("ifcrelschedulescostitems",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelectricgeneratortype",&STEP::ObjectHelper<IfcElectricGeneratorType,1>::Construct )
-, SchemaEntry("ifcdoor",&STEP::ObjectHelper<IfcDoor,2>::Construct )
-, SchemaEntry("ifcstyleditem",&STEP::ObjectHelper<IfcStyledItem,3>::Construct )
-, SchemaEntry("ifcannotationoccurrence",&STEP::ObjectHelper<IfcAnnotationOccurrence,0>::Construct )
-, SchemaEntry("ifcannotationsymboloccurrence",&STEP::ObjectHelper<IfcAnnotationSymbolOccurrence,0>::Construct )
-, SchemaEntry("ifcarbitraryclosedprofiledef",&STEP::ObjectHelper<IfcArbitraryClosedProfileDef,1>::Construct )
-, SchemaEntry("ifcarbitraryprofiledefwithvoids",&STEP::ObjectHelper<IfcArbitraryProfileDefWithVoids,1>::Construct )
-, SchemaEntry("ifcline",&STEP::ObjectHelper<IfcLine,2>::Construct )
-, SchemaEntry("ifcmateriallayerset",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowsegmenttype",&STEP::ObjectHelper<IfcFlowSegmentType,0>::Construct )
-, SchemaEntry("ifcairterminalboxtype",&STEP::ObjectHelper<IfcAirTerminalBoxType,1>::Construct )
-, SchemaEntry("ifcrelconnectsstructuralmember",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpropertysinglevalue",&STEP::ObjectHelper<IfcPropertySingleValue,2>::Construct )
-, SchemaEntry("ifcalarmtype",&STEP::ObjectHelper<IfcAlarmType,1>::Construct )
-, SchemaEntry("ifcellipseprofiledef",&STEP::ObjectHelper<IfcEllipseProfileDef,2>::Construct )
-, SchemaEntry("ifcstair",&STEP::ObjectHelper<IfcStair,1>::Construct )
-, SchemaEntry("ifcpredefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctextstylefontmodel",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsurfacestyleshading",&STEP::ObjectHelper<IfcSurfaceStyleShading,1>::Construct )
-, SchemaEntry("ifcpumptype",&STEP::ObjectHelper<IfcPumpType,1>::Construct )
-, SchemaEntry("ifcdefinedsymbol",&STEP::ObjectHelper<IfcDefinedSymbol,2>::Construct )
-, SchemaEntry("ifcclassificationitemrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcgeneralmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelementcomponenttype",&STEP::ObjectHelper<IfcElementComponentType,0>::Construct )
-, SchemaEntry("ifcfastenertype",&STEP::ObjectHelper<IfcFastenerType,0>::Construct )
-, SchemaEntry("ifcmechanicalfastenertype",&STEP::ObjectHelper<IfcMechanicalFastenerType,0>::Construct )
-, SchemaEntry("ifcpermeablecoveringproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowfitting",&STEP::ObjectHelper<IfcFlowFitting,0>::Construct )
-, SchemaEntry("ifcapproval",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcshapeaspect",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconstraintclassificationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifclightsourcedirectional",&STEP::ObjectHelper<IfcLightSourceDirectional,1>::Construct )
-, SchemaEntry("ifcsurfacestyle",&STEP::ObjectHelper<IfcSurfaceStyle,2>::Construct )
-, SchemaEntry("ifcrelconnectsstructuralactivity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociatesprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcannotationsurface",&STEP::ObjectHelper<IfcAnnotationSurface,2>::Construct )
-, SchemaEntry("ifcfuelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowcontroller",&STEP::ObjectHelper<IfcFlowController,0>::Construct )
-, SchemaEntry("ifcfailureconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcbuildingstorey",&STEP::ObjectHelper<IfcBuildingStorey,1>::Construct )
-, SchemaEntry("ifcworkcontrol",&STEP::ObjectHelper<IfcWorkControl,10>::Construct )
-, SchemaEntry("ifcworkschedule",&STEP::ObjectHelper<IfcWorkSchedule,0>::Construct )
-, SchemaEntry("ifctable",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcductsegmenttype",&STEP::ObjectHelper<IfcDuctSegmentType,1>::Construct )
-, SchemaEntry("ifcstructuralsteelprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdraughtingpredefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcface",&STEP::ObjectHelper<IfcFace,1>::Construct )
-, SchemaEntry("ifcstructuralsurfacemember",&STEP::ObjectHelper<IfcStructuralSurfaceMember,2>::Construct )
-, SchemaEntry("ifcstructuralsurfacemembervarying",&STEP::ObjectHelper<IfcStructuralSurfaceMemberVarying,2>::Construct )
-, SchemaEntry("ifcfacesurface",&STEP::ObjectHelper<IfcFaceSurface,2>::Construct )
-, SchemaEntry("ifcclassification",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcmateriallist",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccostschedule",&STEP::ObjectHelper<IfcCostSchedule,8>::Construct )
-, SchemaEntry("ifccoordinateduniversaltimeoffset",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcplanarextent",&STEP::ObjectHelper<IfcPlanarExtent,2>::Construct )
-, SchemaEntry("ifcplanarbox",&STEP::ObjectHelper<IfcPlanarBox,1>::Construct )
-, SchemaEntry("ifcfillareastyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsectionreinforcementproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccolourspecification",&STEP::ObjectHelper<IfcColourSpecification,1>::Construct )
-, SchemaEntry("ifcvector",&STEP::ObjectHelper<IfcVector,2>::Construct )
-, SchemaEntry("ifcbeam",&STEP::ObjectHelper<IfcBeam,0>::Construct )
-, SchemaEntry("ifccolourrgb",&STEP::ObjectHelper<IfcColourRgb,3>::Construct )
-, SchemaEntry("ifcstructuralplanaraction",&STEP::ObjectHelper<IfcStructuralPlanarAction,1>::Construct )
-, SchemaEntry("ifcstructuralplanaractionvarying",&STEP::ObjectHelper<IfcStructuralPlanarActionVarying,2>::Construct )
-, SchemaEntry("ifcsite",&STEP::ObjectHelper<IfcSite,5>::Construct )
-, SchemaEntry("ifcdiscreteaccessorytype",&STEP::ObjectHelper<IfcDiscreteAccessoryType,0>::Construct )
-, SchemaEntry("ifcvibrationisolatortype",&STEP::ObjectHelper<IfcVibrationIsolatorType,1>::Construct )
-, SchemaEntry("ifcevaporativecoolertype",&STEP::ObjectHelper<IfcEvaporativeCoolerType,1>::Construct )
-, SchemaEntry("ifcdistributionchamberelementtype",&STEP::ObjectHelper<IfcDistributionChamberElementType,1>::Construct )
-, SchemaEntry("ifcfeatureelementaddition",&STEP::ObjectHelper<IfcFeatureElementAddition,0>::Construct )
-, SchemaEntry("ifcrelassignstoresource",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructureddimensioncallout",&STEP::ObjectHelper<IfcStructuredDimensionCallout,0>::Construct )
-, SchemaEntry("ifccoolingtowertype",&STEP::ObjectHelper<IfcCoolingTowerType,1>::Construct )
-, SchemaEntry("ifccenterlineprofiledef",&STEP::ObjectHelper<IfcCenterLineProfileDef,1>::Construct )
-, SchemaEntry("ifctexturevertex",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcorganization",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcwindowstyle",&STEP::ObjectHelper<IfcWindowStyle,4>::Construct )
-, SchemaEntry("ifclightsourcegoniometric",&STEP::ObjectHelper<IfcLightSourceGoniometric,6>::Construct )
-, SchemaEntry("ifcribplateprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctransformertype",&STEP::ObjectHelper<IfcTransformerType,1>::Construct )
-, SchemaEntry("ifcmembertype",&STEP::ObjectHelper<IfcMemberType,1>::Construct )
-, SchemaEntry("ifcsurfaceoflinearextrusion",&STEP::ObjectHelper<IfcSurfaceOfLinearExtrusion,2>::Construct )
-, SchemaEntry("ifcmotorconnectiontype",&STEP::ObjectHelper<IfcMotorConnectionType,1>::Construct )
-, SchemaEntry("ifcflowtreatmentdevicetype",&STEP::ObjectHelper<IfcFlowTreatmentDeviceType,0>::Construct )
-, SchemaEntry("ifcductsilencertype",&STEP::ObjectHelper<IfcDuctSilencerType,1>::Construct )
-, SchemaEntry("ifcwindowliningproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcfurnishingelementtype",&STEP::ObjectHelper<IfcFurnishingElementType,0>::Construct )
-, SchemaEntry("ifcsystemfurnitureelementtype",&STEP::ObjectHelper<IfcSystemFurnitureElementType,0>::Construct )
-, SchemaEntry("ifcconnectionpointeccentricity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcwasteterminaltype",&STEP::ObjectHelper<IfcWasteTerminalType,1>::Construct )
-, SchemaEntry("ifcbsplinecurve",&STEP::ObjectHelper<IfcBSplineCurve,5>::Construct )
-, SchemaEntry("ifcbeziercurve",&STEP::ObjectHelper<IfcBezierCurve,0>::Construct )
-, SchemaEntry("ifcdocumentinformationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcactuatortype",&STEP::ObjectHelper<IfcActuatorType,1>::Construct )
-, SchemaEntry("ifcdistributioncontrolelement",&STEP::ObjectHelper<IfcDistributionControlElement,1>::Construct )
-, SchemaEntry("ifcannotation",&STEP::ObjectHelper<IfcAnnotation,0>::Construct )
-, SchemaEntry("ifcrelassociatesdocument",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdoorliningproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcshellbasedsurfacemodel",&STEP::ObjectHelper<IfcShellBasedSurfaceModel,1>::Construct )
-, SchemaEntry("ifcactionrequest",&STEP::ObjectHelper<IfcActionRequest,1>::Construct )
-, SchemaEntry("ifcextrudedareasolid",&STEP::ObjectHelper<IfcExtrudedAreaSolid,2>::Construct )
-, SchemaEntry("ifcsystem",&STEP::ObjectHelper<IfcSystem,0>::Construct )
-, SchemaEntry("ifcfillareastylehatching",&STEP::ObjectHelper<IfcFillAreaStyleHatching,5>::Construct )
-, SchemaEntry("ifcrelvoidselement",&STEP::ObjectHelper<IfcRelVoidsElement,2>::Construct )
-, SchemaEntry("ifcrelconnectspathelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelspaceboundary",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsurfacecurvesweptareasolid",&STEP::ObjectHelper<IfcSurfaceCurveSweptAreaSolid,4>::Construct )
-, SchemaEntry("ifccartesiantransformationoperator3dnonuniform",&STEP::ObjectHelper<IfcCartesianTransformationOperator3DnonUniform,2>::Construct )
-, SchemaEntry("ifcrelinteractionrequirements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccurtainwalltype",&STEP::ObjectHelper<IfcCurtainWallType,1>::Construct )
-, SchemaEntry("ifcquantitylength",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcequipmentstandard",&STEP::ObjectHelper<IfcEquipmentStandard,0>::Construct )
-, SchemaEntry("ifcflowstoragedevicetype",&STEP::ObjectHelper<IfcFlowStorageDeviceType,0>::Construct )
-, SchemaEntry("ifcvirtualgridintersection",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdiameterdimension",&STEP::ObjectHelper<IfcDiameterDimension,0>::Construct )
-, SchemaEntry("ifcswitchingdevicetype",&STEP::ObjectHelper<IfcSwitchingDeviceType,1>::Construct )
-, SchemaEntry("ifcaddress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctelecomaddress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcwindow",&STEP::ObjectHelper<IfcWindow,2>::Construct )
-, SchemaEntry("ifcmechanicalsteelmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowtreatmentdevice",&STEP::ObjectHelper<IfcFlowTreatmentDevice,0>::Construct )
-, SchemaEntry("ifcrelservicesbuildings",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcchillertype",&STEP::ObjectHelper<IfcChillerType,1>::Construct )
-, SchemaEntry("ifcrelassignstoproduct",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrectanglehollowprofiledef",&STEP::ObjectHelper<IfcRectangleHollowProfileDef,3>::Construct )
-, SchemaEntry("ifcenergyproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcboxedhalfspace",&STEP::ObjectHelper<IfcBoxedHalfSpace,1>::Construct )
-, SchemaEntry("ifcaxis2placement2d",&STEP::ObjectHelper<IfcAxis2Placement2D,1>::Construct )
-, SchemaEntry("ifcspaceprogram",&STEP::ObjectHelper<IfcSpaceProgram,5>::Construct )
-, SchemaEntry("ifcpoint",&STEP::ObjectHelper<IfcPoint,0>::Construct )
-, SchemaEntry("ifccartesianpoint",&STEP::ObjectHelper<IfcCartesianPoint,1>::Construct )
-, SchemaEntry("ifcboundedsurface",&STEP::ObjectHelper<IfcBoundedSurface,0>::Construct )
-, SchemaEntry("ifcloop",&STEP::ObjectHelper<IfcLoop,0>::Construct )
-, SchemaEntry("ifcpolyloop",&STEP::ObjectHelper<IfcPolyLoop,1>::Construct )
-, SchemaEntry("ifcpredefinedpointmarkersymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcterminatorsymbol",&STEP::ObjectHelper<IfcTerminatorSymbol,1>::Construct )
-, SchemaEntry("ifcdimensioncurveterminator",&STEP::ObjectHelper<IfcDimensionCurveTerminator,1>::Construct )
-, SchemaEntry("ifcrelprojectselement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctrapeziumprofiledef",&STEP::ObjectHelper<IfcTrapeziumProfileDef,4>::Construct )
-, SchemaEntry("ifcrepresentationcontext",&STEP::ObjectHelper<IfcRepresentationContext,2>::Construct )
-, SchemaEntry("ifcgeometricrepresentationcontext",&STEP::ObjectHelper<IfcGeometricRepresentationContext,4>::Construct )
-, SchemaEntry("ifctextstylewithboxcharacteristics",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccurveboundedplane",&STEP::ObjectHelper<IfcCurveBoundedPlane,3>::Construct )
-, SchemaEntry("ifcquantitycount",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctimeseriesreferencerelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadtemperature",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsiunit",&STEP::ObjectHelper<IfcSIUnit,2>::Construct )
-, SchemaEntry("ifcstructuralreaction",&STEP::ObjectHelper<IfcStructuralReaction,0>::Construct )
-, SchemaEntry("ifcstructuralpointreaction",&STEP::ObjectHelper<IfcStructuralPointReaction,0>::Construct )
-, SchemaEntry("ifcaxis1placement",&STEP::ObjectHelper<IfcAxis1Placement,1>::Construct )
-, SchemaEntry("ifcreinforcementdefinitionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelectricappliancetype",&STEP::ObjectHelper<IfcElectricApplianceType,1>::Construct )
-, SchemaEntry("ifcsensortype",&STEP::ObjectHelper<IfcSensorType,1>::Construct )
-, SchemaEntry("ifcfurnishingelement",&STEP::ObjectHelper<IfcFurnishingElement,0>::Construct )
-, SchemaEntry("ifcprotectivedevicetype",&STEP::ObjectHelper<IfcProtectiveDeviceType,1>::Construct )
-, SchemaEntry("ifczshapeprofiledef",&STEP::ObjectHelper<IfcZShapeProfileDef,6>::Construct )
-, SchemaEntry("ifcscheduletimecontrol",&STEP::ObjectHelper<IfcScheduleTimeControl,18>::Construct )
-, SchemaEntry("ifcrepresentationmap",&STEP::ObjectHelper<IfcRepresentationMap,2>::Construct )
-, SchemaEntry("ifcclosedshell",&STEP::ObjectHelper<IfcClosedShell,0>::Construct )
-, SchemaEntry("ifcbuildingelementpart",&STEP::ObjectHelper<IfcBuildingElementPart,0>::Construct )
-, SchemaEntry("ifcdraughtingpredefinedcolour",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpostaladdress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcblock",&STEP::ObjectHelper<IfcBlock,3>::Construct )
-, SchemaEntry("ifclightfixturetype",&STEP::ObjectHelper<IfcLightFixtureType,1>::Construct )
-, SchemaEntry("ifcopeningelement",&STEP::ObjectHelper<IfcOpeningElement,0>::Construct )
-, SchemaEntry("ifclightsourcespot",&STEP::ObjectHelper<IfcLightSourceSpot,4>::Construct )
-, SchemaEntry("ifctendonanchor",&STEP::ObjectHelper<IfcTendonAnchor,0>::Construct )
-, SchemaEntry("ifcsurfacestylerefraction",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelectricflowstoragedevicetype",&STEP::ObjectHelper<IfcElectricFlowStorageDeviceType,1>::Construct )
-, SchemaEntry("ifcfluidflowproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsphere",&STEP::ObjectHelper<IfcSphere,1>::Construct )
-, SchemaEntry("ifcrelassociatesappliedvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdampertype",&STEP::ObjectHelper<IfcDamperType,1>::Construct )
-, SchemaEntry("ifcprojectorderrecord",&STEP::ObjectHelper<IfcProjectOrderRecord,2>::Construct )
-, SchemaEntry("ifcdimensionalexponents",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcreldefinesbytype",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcdistributionchamberelement",&STEP::ObjectHelper<IfcDistributionChamberElement,0>::Construct )
-, SchemaEntry("ifcmechanicalfastener",&STEP::ObjectHelper<IfcMechanicalFastener,2>::Construct )
-, SchemaEntry("ifcquantityvolume",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrectangulartrimmedsurface",&STEP::ObjectHelper<IfcRectangularTrimmedSurface,7>::Construct )
-, SchemaEntry("ifcdateandtime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifczone",&STEP::ObjectHelper<IfcZone,0>::Construct )
-, SchemaEntry("ifcfantype",&STEP::ObjectHelper<IfcFanType,1>::Construct )
-, SchemaEntry("ifcgeometricset",&STEP::ObjectHelper<IfcGeometricSet,1>::Construct )
-, SchemaEntry("ifcfillareastyletiles",&STEP::ObjectHelper<IfcFillAreaStyleTiles,3>::Construct )
-, SchemaEntry("ifcpixeltexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccablesegmenttype",&STEP::ObjectHelper<IfcCableSegmentType,1>::Construct )
-, SchemaEntry("ifcreloverridesproperties",&STEP::ObjectHelper<IfcRelOverridesProperties,1>::Construct )
-, SchemaEntry("ifcmeasurewithunit",&STEP::ObjectHelper<IfcMeasureWithUnit,2>::Construct )
-, SchemaEntry("ifcslabtype",&STEP::ObjectHelper<IfcSlabType,1>::Construct )
-, SchemaEntry("ifcservicelife",&STEP::ObjectHelper<IfcServiceLife,2>::Construct )
-, SchemaEntry("ifcfurnituretype",&STEP::ObjectHelper<IfcFurnitureType,1>::Construct )
-, SchemaEntry("ifccostitem",&STEP::ObjectHelper<IfcCostItem,0>::Construct )
-, SchemaEntry("ifcreinforcingmesh",&STEP::ObjectHelper<IfcReinforcingMesh,8>::Construct )
-, SchemaEntry("ifcextendedmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcactorrole",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcfacetedbrepwithvoids",&STEP::ObjectHelper<IfcFacetedBrepWithVoids,1>::Construct )
-, SchemaEntry("ifcconstraintaggregationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcgasterminaltype",&STEP::ObjectHelper<IfcGasTerminalType,1>::Construct )
-, SchemaEntry("ifcrelconnectswitheccentricity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpile",&STEP::ObjectHelper<IfcPile,2>::Construct )
-, SchemaEntry("ifcfillareastyletilesymbolwithstyle",&STEP::ObjectHelper<IfcFillAreaStyleTileSymbolWithStyle,1>::Construct )
-, SchemaEntry("ifcelectricalbaseproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconstructionmaterialresource",&STEP::ObjectHelper<IfcConstructionMaterialResource,2>::Construct )
-, SchemaEntry("ifcannotationcurveoccurrence",&STEP::ObjectHelper<IfcAnnotationCurveOccurrence,0>::Construct )
-, SchemaEntry("ifcdimensioncurve",&STEP::ObjectHelper<IfcDimensionCurve,0>::Construct )
-, SchemaEntry("ifcgeometriccurveset",&STEP::ObjectHelper<IfcGeometricCurveSet,0>::Construct )
-, SchemaEntry("ifcrelaggregates",&STEP::ObjectHelper<IfcRelAggregates,0>::Construct )
-, SchemaEntry("ifcfacebasedsurfacemodel",&STEP::ObjectHelper<IfcFaceBasedSurfaceModel,1>::Construct )
-, SchemaEntry("ifcenergyconversiondevice",&STEP::ObjectHelper<IfcEnergyConversionDevice,0>::Construct )
-, SchemaEntry("ifcrampflight",&STEP::ObjectHelper<IfcRampFlight,0>::Construct )
-, SchemaEntry("ifcpropertyenumeration",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcvertexloop",&STEP::ObjectHelper<IfcVertexLoop,1>::Construct )
-, SchemaEntry("ifcplate",&STEP::ObjectHelper<IfcPlate,0>::Construct )
-, SchemaEntry("ifcushapeprofiledef",&STEP::ObjectHelper<IfcUShapeProfileDef,8>::Construct )
-, SchemaEntry("ifchygroscopicmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcfacebound",&STEP::ObjectHelper<IfcFaceBound,2>::Construct )
-, SchemaEntry("ifcfaceouterbound",&STEP::ObjectHelper<IfcFaceOuterBound,0>::Construct )
-, SchemaEntry("ifconedirectionrepeatfactor",&STEP::ObjectHelper<IfcOneDirectionRepeatFactor,1>::Construct )
-, SchemaEntry("ifcboilertype",&STEP::ObjectHelper<IfcBoilerType,1>::Construct )
-, SchemaEntry("ifcconstructionequipmentresource",&STEP::ObjectHelper<IfcConstructionEquipmentResource,0>::Construct )
-, SchemaEntry("ifccomplexproperty",&STEP::ObjectHelper<IfcComplexProperty,2>::Construct )
-, SchemaEntry("ifcfooting",&STEP::ObjectHelper<IfcFooting,1>::Construct )
-, SchemaEntry("ifcopticalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconstructionproductresource",&STEP::ObjectHelper<IfcConstructionProductResource,0>::Construct )
-, SchemaEntry("ifcboundaryedgecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcderivedprofiledef",&STEP::ObjectHelper<IfcDerivedProfileDef,3>::Construct )
-, SchemaEntry("ifcpropertytablevalue",&STEP::ObjectHelper<IfcPropertyTableValue,5>::Construct )
-, SchemaEntry("ifcrelassignstogroup",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcflowmetertype",&STEP::ObjectHelper<IfcFlowMeterType,1>::Construct )
-, SchemaEntry("ifcdoorstyle",&STEP::ObjectHelper<IfcDoorStyle,4>::Construct )
-, SchemaEntry("ifcrelconnectsporttoelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociatesclassification",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcunitassignment",&STEP::ObjectHelper<IfcUnitAssignment,1>::Construct )
-, SchemaEntry("ifcflowterminal",&STEP::ObjectHelper<IfcFlowTerminal,0>::Construct )
-, SchemaEntry("ifccranerailfshapeprofiledef",&STEP::ObjectHelper<IfcCraneRailFShapeProfileDef,9>::Construct )
-, SchemaEntry("ifcflowsegment",&STEP::ObjectHelper<IfcFlowSegment,0>::Construct )
-, SchemaEntry("ifcelementquantity",&STEP::ObjectHelper<IfcElementQuantity,2>::Construct )
-, SchemaEntry("ifcboundarynodecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcboundarynodeconditionwarping",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccurtainwall",&STEP::ObjectHelper<IfcCurtainWall,0>::Construct )
-, SchemaEntry("ifcdiscreteaccessory",&STEP::ObjectHelper<IfcDiscreteAccessory,0>::Construct )
-, SchemaEntry("ifcgrid",&STEP::ObjectHelper<IfcGrid,3>::Construct )
-, SchemaEntry("ifcsanitaryterminaltype",&STEP::ObjectHelper<IfcSanitaryTerminalType,1>::Construct )
-, SchemaEntry("ifcsoundproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsubedge",&STEP::ObjectHelper<IfcSubedge,1>::Construct )
-, SchemaEntry("ifctextstyletextmodel",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcfiltertype",&STEP::ObjectHelper<IfcFilterType,1>::Construct )
-, SchemaEntry("ifcsymbolstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctendon",&STEP::ObjectHelper<IfcTendon,8>::Construct )
-, SchemaEntry("ifcdimensionpair",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralloadgroup",&STEP::ObjectHelper<IfcStructuralLoadGroup,5>::Construct )
-, SchemaEntry("ifcpresentationstyleassignment",&STEP::ObjectHelper<IfcPresentationStyleAssignment,1>::Construct )
-, SchemaEntry("ifcregulartimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralcurvemember",&STEP::ObjectHelper<IfcStructuralCurveMember,1>::Construct )
-, SchemaEntry("ifclightsourceambient",&STEP::ObjectHelper<IfcLightSourceAmbient,0>::Construct )
-, SchemaEntry("ifccondition",&STEP::ObjectHelper<IfcCondition,0>::Construct )
-, SchemaEntry("ifcport",&STEP::ObjectHelper<IfcPort,0>::Construct )
-, SchemaEntry("ifcspace",&STEP::ObjectHelper<IfcSpace,2>::Construct )
-, SchemaEntry("ifcheatexchangertype",&STEP::ObjectHelper<IfcHeatExchangerType,1>::Construct )
-, SchemaEntry("ifctanktype",&STEP::ObjectHelper<IfcTankType,1>::Construct )
-, SchemaEntry("ifcinventory",&STEP::ObjectHelper<IfcInventory,6>::Construct )
-, SchemaEntry("ifctextstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcappliedvaluerelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsoundvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctransportelementtype",&STEP::ObjectHelper<IfcTransportElementType,1>::Construct )
-, SchemaEntry("ifcairtoairheatrecoverytype",&STEP::ObjectHelper<IfcAirToAirHeatRecoveryType,1>::Construct )
-, SchemaEntry("ifcstairflight",&STEP::ObjectHelper<IfcStairFlight,4>::Construct )
-, SchemaEntry("ifcelectricalelement",&STEP::ObjectHelper<IfcElectricalElement,0>::Construct )
-, SchemaEntry("ifclightintensitydistribution",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcclassificationreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcsurfacestylewithtextures",&STEP::ObjectHelper<IfcSurfaceStyleWithTextures,1>::Construct )
-, SchemaEntry("ifcboundingbox",&STEP::ObjectHelper<IfcBoundingBox,4>::Construct )
-, SchemaEntry("ifcapplication",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcwalltype",&STEP::ObjectHelper<IfcWallType,1>::Construct )
-, SchemaEntry("ifcmove",&STEP::ObjectHelper<IfcMove,3>::Construct )
-, SchemaEntry("ifccircle",&STEP::ObjectHelper<IfcCircle,1>::Construct )
-, SchemaEntry("ifcoffsetcurve2d",&STEP::ObjectHelper<IfcOffsetCurve2D,3>::Construct )
-, SchemaEntry("ifcmateriallayersetusage",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpointoncurve",&STEP::ObjectHelper<IfcPointOnCurve,2>::Construct )
-, SchemaEntry("ifcstructuralresultgroup",&STEP::ObjectHelper<IfcStructuralResultGroup,3>::Construct )
-, SchemaEntry("ifcsectionedspine",&STEP::ObjectHelper<IfcSectionedSpine,3>::Construct )
-, SchemaEntry("ifcslab",&STEP::ObjectHelper<IfcSlab,1>::Construct )
-, SchemaEntry("ifcconnectionportgeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcquantityweight",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassociatesmaterial",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcvertex",&STEP::ObjectHelper<IfcVertex,0>::Construct )
-, SchemaEntry("ifcvertexpoint",&STEP::ObjectHelper<IfcVertexPoint,1>::Construct )
-, SchemaEntry("ifcreferencesvaluedocument",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpersonandorganization",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelflowcontrolelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcrelassignstoprocess",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructurallinearaction",&STEP::ObjectHelper<IfcStructuralLinearAction,1>::Construct )
-, SchemaEntry("ifcstructurallinearactionvarying",&STEP::ObjectHelper<IfcStructuralLinearActionVarying,2>::Construct )
-, SchemaEntry("ifcbuildingelementproxytype",&STEP::ObjectHelper<IfcBuildingElementProxyType,1>::Construct )
-, SchemaEntry("ifcprojectionelement",&STEP::ObjectHelper<IfcProjectionElement,0>::Construct )
-, SchemaEntry("ifcderivedunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcapprovalactorrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconversionbasedunit",&STEP::ObjectHelper<IfcConversionBasedUnit,2>::Construct )
-, SchemaEntry("ifcmaterial",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcgeometricrepresentationsubcontext",&STEP::ObjectHelper<IfcGeometricRepresentationSubContext,4>::Construct )
-, SchemaEntry("ifcannotationsurfaceoccurrence",&STEP::ObjectHelper<IfcAnnotationSurfaceOccurrence,0>::Construct )
-, SchemaEntry("ifcpredefineddimensionsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcroundededgefeature",&STEP::ObjectHelper<IfcRoundedEdgeFeature,1>::Construct )
-, SchemaEntry("ifcrelcoversbldgelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcelectricdistributionpoint",&STEP::ObjectHelper<IfcElectricDistributionPoint,2>::Construct )
-, SchemaEntry("ifccablecarriersegmenttype",&STEP::ObjectHelper<IfcCableCarrierSegmentType,1>::Construct )
-, SchemaEntry("ifcstructuralloadlinearforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcgridaxis",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcirregulartimeseriesvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcwallstandardcase",&STEP::ObjectHelper<IfcWallStandardCase,0>::Construct )
-, SchemaEntry("ifcreloccupiesspaces",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcderivedunitelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccsgsolid",&STEP::ObjectHelper<IfcCsgSolid,1>::Construct )
-, SchemaEntry("ifcbeamtype",&STEP::ObjectHelper<IfcBeamType,1>::Construct )
-, SchemaEntry("ifcannotationfillarea",&STEP::ObjectHelper<IfcAnnotationFillArea,2>::Construct )
-, SchemaEntry("ifcrelaxation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralcurvemembervarying",&STEP::ObjectHelper<IfcStructuralCurveMemberVarying,0>::Construct )
-, SchemaEntry("ifcpointonsurface",&STEP::ObjectHelper<IfcPointOnSurface,3>::Construct )
-, SchemaEntry("ifcpropertydependencyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcvertexbasedtexturemap",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcorderaction",&STEP::ObjectHelper<IfcOrderAction,1>::Construct )
-, SchemaEntry("ifclibraryreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcedgeloop",&STEP::ObjectHelper<IfcEdgeLoop,1>::Construct )
-, SchemaEntry("ifcannotationfillareaoccurrence",&STEP::ObjectHelper<IfcAnnotationFillAreaOccurrence,2>::Construct )
-, SchemaEntry("ifcrelconnectsstructuralelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcworkplan",&STEP::ObjectHelper<IfcWorkPlan,0>::Construct )
-, SchemaEntry("ifcellipse",&STEP::ObjectHelper<IfcEllipse,2>::Construct )
-, SchemaEntry("ifcproductdefinitionshape",&STEP::ObjectHelper<IfcProductDefinitionShape,0>::Construct )
-, SchemaEntry("ifcprojectioncurve",&STEP::ObjectHelper<IfcProjectionCurve,0>::Construct )
-, SchemaEntry("ifcelectricalcircuit",&STEP::ObjectHelper<IfcElectricalCircuit,0>::Construct )
-, SchemaEntry("ifcrationalbeziercurve",&STEP::ObjectHelper<IfcRationalBezierCurve,1>::Construct )
-, SchemaEntry("ifcstructuralpointaction",&STEP::ObjectHelper<IfcStructuralPointAction,0>::Construct )
-, SchemaEntry("ifcservicelifefactor",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcthermalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifctexturecoordinategenerator",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpipesegmenttype",&STEP::ObjectHelper<IfcPipeSegmentType,1>::Construct )
-, SchemaEntry("ifctwodirectionrepeatfactor",&STEP::ObjectHelper<IfcTwoDirectionRepeatFactor,1>::Construct )
-, SchemaEntry("ifcshaperepresentation",&STEP::ObjectHelper<IfcShapeRepresentation,0>::Construct )
-, SchemaEntry("ifcpropertyset",&STEP::ObjectHelper<IfcPropertySet,1>::Construct )
-, SchemaEntry("ifcsurfacestylerendering",&STEP::ObjectHelper<IfcSurfaceStyleRendering,8>::Construct )
-, SchemaEntry("ifcdistributionport",&STEP::ObjectHelper<IfcDistributionPort,1>::Construct )
-, SchemaEntry("ifcimagetexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcpipefittingtype",&STEP::ObjectHelper<IfcPipeFittingType,1>::Construct )
-, SchemaEntry("ifctransportelement",&STEP::ObjectHelper<IfcTransportElement,3>::Construct )
-, SchemaEntry("ifcannotationtextoccurrence",&STEP::ObjectHelper<IfcAnnotationTextOccurrence,0>::Construct )
-, SchemaEntry("ifcconnectionsurfacegeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcstructuralanalysismodel",&STEP::ObjectHelper<IfcStructuralAnalysisModel,4>::Construct )
-, SchemaEntry("ifcconnectioncurvegeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcconditioncriterion",&STEP::ObjectHelper<IfcConditionCriterion,2>::Construct )
-, SchemaEntry("ifcwaterproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifcmateriallayer",&STEP::ObjectHelper<NotImplemented,0>::Construct )
-, SchemaEntry("ifccostvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+ typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
+ const SchemaEntry schema_raw[] = {
+ SchemaEntry("ifcabsorbeddosemeasure",NULL )
+, SchemaEntry("ifcaccelerationmeasure",NULL )
+, SchemaEntry("ifcamountofsubstancemeasure",NULL )
+, SchemaEntry("ifcangularvelocitymeasure",NULL )
+, SchemaEntry("ifcareameasure",NULL )
+, SchemaEntry("ifcboolean",NULL )
+, SchemaEntry("ifcboxalignment",NULL )
+, SchemaEntry("ifccomplexnumber",NULL )
+, SchemaEntry("ifccompoundplaneanglemeasure",NULL )
+, SchemaEntry("ifccontextdependentmeasure",NULL )
+, SchemaEntry("ifccountmeasure",NULL )
+, SchemaEntry("ifccurvaturemeasure",NULL )
+, SchemaEntry("ifcdayinmonthnumber",NULL )
+, SchemaEntry("ifcdaylightsavinghour",NULL )
+, SchemaEntry("ifcdescriptivemeasure",NULL )
+, SchemaEntry("ifcdimensioncount",NULL )
+, SchemaEntry("ifcdoseequivalentmeasure",NULL )
+, SchemaEntry("ifcdynamicviscositymeasure",NULL )
+, SchemaEntry("ifcelectriccapacitancemeasure",NULL )
+, SchemaEntry("ifcelectricchargemeasure",NULL )
+, SchemaEntry("ifcelectricconductancemeasure",NULL )
+, SchemaEntry("ifcelectriccurrentmeasure",NULL )
+, SchemaEntry("ifcelectricresistancemeasure",NULL )
+, SchemaEntry("ifcelectricvoltagemeasure",NULL )
+, SchemaEntry("ifcenergymeasure",NULL )
+, SchemaEntry("ifcfontstyle",NULL )
+, SchemaEntry("ifcfontvariant",NULL )
+, SchemaEntry("ifcfontweight",NULL )
+, SchemaEntry("ifcforcemeasure",NULL )
+, SchemaEntry("ifcfrequencymeasure",NULL )
+, SchemaEntry("ifcgloballyuniqueid",NULL )
+, SchemaEntry("ifcheatfluxdensitymeasure",NULL )
+, SchemaEntry("ifcheatingvaluemeasure",NULL )
+, SchemaEntry("ifchourinday",NULL )
+, SchemaEntry("ifcidentifier",NULL )
+, SchemaEntry("ifcilluminancemeasure",NULL )
+, SchemaEntry("ifcinductancemeasure",NULL )
+, SchemaEntry("ifcinteger",NULL )
+, SchemaEntry("ifcintegercountratemeasure",NULL )
+, SchemaEntry("ifcionconcentrationmeasure",NULL )
+, SchemaEntry("ifcisothermalmoisturecapacitymeasure",NULL )
+, SchemaEntry("ifckinematicviscositymeasure",NULL )
+, SchemaEntry("ifclabel",NULL )
+, SchemaEntry("ifclengthmeasure",NULL )
+, SchemaEntry("ifclinearforcemeasure",NULL )
+, SchemaEntry("ifclinearmomentmeasure",NULL )
+, SchemaEntry("ifclinearstiffnessmeasure",NULL )
+, SchemaEntry("ifclinearvelocitymeasure",NULL )
+, SchemaEntry("ifclogical",NULL )
+, SchemaEntry("ifcluminousfluxmeasure",NULL )
+, SchemaEntry("ifcluminousintensitydistributionmeasure",NULL )
+, SchemaEntry("ifcluminousintensitymeasure",NULL )
+, SchemaEntry("ifcmagneticfluxdensitymeasure",NULL )
+, SchemaEntry("ifcmagneticfluxmeasure",NULL )
+, SchemaEntry("ifcmassdensitymeasure",NULL )
+, SchemaEntry("ifcmassflowratemeasure",NULL )
+, SchemaEntry("ifcmassmeasure",NULL )
+, SchemaEntry("ifcmassperlengthmeasure",NULL )
+, SchemaEntry("ifcminuteinhour",NULL )
+, SchemaEntry("ifcmodulusofelasticitymeasure",NULL )
+, SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",NULL )
+, SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",NULL )
+, SchemaEntry("ifcmodulusofsubgradereactionmeasure",NULL )
+, SchemaEntry("ifcmoisturediffusivitymeasure",NULL )
+, SchemaEntry("ifcmolecularweightmeasure",NULL )
+, SchemaEntry("ifcmomentofinertiameasure",NULL )
+, SchemaEntry("ifcmonetarymeasure",NULL )
+, SchemaEntry("ifcmonthinyearnumber",NULL )
+, SchemaEntry("ifcnormalisedratiomeasure",NULL )
+, SchemaEntry("ifcnumericmeasure",NULL )
+, SchemaEntry("ifcphmeasure",NULL )
+, SchemaEntry("ifcparametervalue",NULL )
+, SchemaEntry("ifcplanarforcemeasure",NULL )
+, SchemaEntry("ifcplaneanglemeasure",NULL )
+, SchemaEntry("ifcpositivelengthmeasure",NULL )
+, SchemaEntry("ifcpositiveplaneanglemeasure",NULL )
+, SchemaEntry("ifcpositiveratiomeasure",NULL )
+, SchemaEntry("ifcpowermeasure",NULL )
+, SchemaEntry("ifcpresentabletext",NULL )
+, SchemaEntry("ifcpressuremeasure",NULL )
+, SchemaEntry("ifcradioactivitymeasure",NULL )
+, SchemaEntry("ifcratiomeasure",NULL )
+, SchemaEntry("ifcreal",NULL )
+, SchemaEntry("ifcrotationalfrequencymeasure",NULL )
+, SchemaEntry("ifcrotationalmassmeasure",NULL )
+, SchemaEntry("ifcrotationalstiffnessmeasure",NULL )
+, SchemaEntry("ifcsecondinminute",NULL )
+, SchemaEntry("ifcsectionmodulusmeasure",NULL )
+, SchemaEntry("ifcsectionalareaintegralmeasure",NULL )
+, SchemaEntry("ifcshearmodulusmeasure",NULL )
+, SchemaEntry("ifcsolidanglemeasure",NULL )
+, SchemaEntry("ifcsoundpowermeasure",NULL )
+, SchemaEntry("ifcsoundpressuremeasure",NULL )
+, SchemaEntry("ifcspecificheatcapacitymeasure",NULL )
+, SchemaEntry("ifcspecularexponent",NULL )
+, SchemaEntry("ifcspecularroughness",NULL )
+, SchemaEntry("ifctemperaturegradientmeasure",NULL )
+, SchemaEntry("ifctext",NULL )
+, SchemaEntry("ifctextalignment",NULL )
+, SchemaEntry("ifctextdecoration",NULL )
+, SchemaEntry("ifctextfontname",NULL )
+, SchemaEntry("ifctexttransformation",NULL )
+, SchemaEntry("ifcthermaladmittancemeasure",NULL )
+, SchemaEntry("ifcthermalconductivitymeasure",NULL )
+, SchemaEntry("ifcthermalexpansioncoefficientmeasure",NULL )
+, SchemaEntry("ifcthermalresistancemeasure",NULL )
+, SchemaEntry("ifcthermaltransmittancemeasure",NULL )
+, SchemaEntry("ifcthermodynamictemperaturemeasure",NULL )
+, SchemaEntry("ifctimemeasure",NULL )
+, SchemaEntry("ifctimestamp",NULL )
+, SchemaEntry("ifctorquemeasure",NULL )
+, SchemaEntry("ifcvaporpermeabilitymeasure",NULL )
+, SchemaEntry("ifcvolumemeasure",NULL )
+, SchemaEntry("ifcvolumetricflowratemeasure",NULL )
+, SchemaEntry("ifcwarpingconstantmeasure",NULL )
+, SchemaEntry("ifcwarpingmomentmeasure",NULL )
+, SchemaEntry("ifcyearnumber",NULL )
+, SchemaEntry("ifcactionsourcetypeenum",NULL )
+, SchemaEntry("ifcactiontypeenum",NULL )
+, SchemaEntry("ifcactuatortypeenum",NULL )
+, SchemaEntry("ifcaddresstypeenum",NULL )
+, SchemaEntry("ifcaheadorbehind",NULL )
+, SchemaEntry("ifcairterminalboxtypeenum",NULL )
+, SchemaEntry("ifcairterminaltypeenum",NULL )
+, SchemaEntry("ifcairtoairheatrecoverytypeenum",NULL )
+, SchemaEntry("ifcalarmtypeenum",NULL )
+, SchemaEntry("ifcanalysismodeltypeenum",NULL )
+, SchemaEntry("ifcanalysistheorytypeenum",NULL )
+, SchemaEntry("ifcarithmeticoperatorenum",NULL )
+, SchemaEntry("ifcassemblyplaceenum",NULL )
+, SchemaEntry("ifcbsplinecurveform",NULL )
+, SchemaEntry("ifcbeamtypeenum",NULL )
+, SchemaEntry("ifcbenchmarkenum",NULL )
+, SchemaEntry("ifcboilertypeenum",NULL )
+, SchemaEntry("ifcbooleanoperator",NULL )
+, SchemaEntry("ifcbuildingelementproxytypeenum",NULL )
+, SchemaEntry("ifccablecarrierfittingtypeenum",NULL )
+, SchemaEntry("ifccablecarriersegmenttypeenum",NULL )
+, SchemaEntry("ifccablesegmenttypeenum",NULL )
+, SchemaEntry("ifcchangeactionenum",NULL )
+, SchemaEntry("ifcchillertypeenum",NULL )
+, SchemaEntry("ifccoiltypeenum",NULL )
+, SchemaEntry("ifccolumntypeenum",NULL )
+, SchemaEntry("ifccompressortypeenum",NULL )
+, SchemaEntry("ifccondensertypeenum",NULL )
+, SchemaEntry("ifcconnectiontypeenum",NULL )
+, SchemaEntry("ifcconstraintenum",NULL )
+, SchemaEntry("ifccontrollertypeenum",NULL )
+, SchemaEntry("ifccooledbeamtypeenum",NULL )
+, SchemaEntry("ifccoolingtowertypeenum",NULL )
+, SchemaEntry("ifccostscheduletypeenum",NULL )
+, SchemaEntry("ifccoveringtypeenum",NULL )
+, SchemaEntry("ifccurrencyenum",NULL )
+, SchemaEntry("ifccurtainwalltypeenum",NULL )
+, SchemaEntry("ifcdampertypeenum",NULL )
+, SchemaEntry("ifcdataoriginenum",NULL )
+, SchemaEntry("ifcderivedunitenum",NULL )
+, SchemaEntry("ifcdimensionextentusage",NULL )
+, SchemaEntry("ifcdirectionsenseenum",NULL )
+, SchemaEntry("ifcdistributionchamberelementtypeenum",NULL )
+, SchemaEntry("ifcdocumentconfidentialityenum",NULL )
+, SchemaEntry("ifcdocumentstatusenum",NULL )
+, SchemaEntry("ifcdoorpaneloperationenum",NULL )
+, SchemaEntry("ifcdoorpanelpositionenum",NULL )
+, SchemaEntry("ifcdoorstyleconstructionenum",NULL )
+, SchemaEntry("ifcdoorstyleoperationenum",NULL )
+, SchemaEntry("ifcductfittingtypeenum",NULL )
+, SchemaEntry("ifcductsegmenttypeenum",NULL )
+, SchemaEntry("ifcductsilencertypeenum",NULL )
+, SchemaEntry("ifcelectricappliancetypeenum",NULL )
+, SchemaEntry("ifcelectriccurrentenum",NULL )
+, SchemaEntry("ifcelectricdistributionpointfunctionenum",NULL )
+, SchemaEntry("ifcelectricflowstoragedevicetypeenum",NULL )
+, SchemaEntry("ifcelectricgeneratortypeenum",NULL )
+, SchemaEntry("ifcelectricheatertypeenum",NULL )
+, SchemaEntry("ifcelectricmotortypeenum",NULL )
+, SchemaEntry("ifcelectrictimecontroltypeenum",NULL )
+, SchemaEntry("ifcelementassemblytypeenum",NULL )
+, SchemaEntry("ifcelementcompositionenum",NULL )
+, SchemaEntry("ifcenergysequenceenum",NULL )
+, SchemaEntry("ifcenvironmentalimpactcategoryenum",NULL )
+, SchemaEntry("ifcevaporativecoolertypeenum",NULL )
+, SchemaEntry("ifcevaporatortypeenum",NULL )
+, SchemaEntry("ifcfantypeenum",NULL )
+, SchemaEntry("ifcfiltertypeenum",NULL )
+, SchemaEntry("ifcfiresuppressionterminaltypeenum",NULL )
+, SchemaEntry("ifcflowdirectionenum",NULL )
+, SchemaEntry("ifcflowinstrumenttypeenum",NULL )
+, SchemaEntry("ifcflowmetertypeenum",NULL )
+, SchemaEntry("ifcfootingtypeenum",NULL )
+, SchemaEntry("ifcgasterminaltypeenum",NULL )
+, SchemaEntry("ifcgeometricprojectionenum",NULL )
+, SchemaEntry("ifcglobalorlocalenum",NULL )
+, SchemaEntry("ifcheatexchangertypeenum",NULL )
+, SchemaEntry("ifchumidifiertypeenum",NULL )
+, SchemaEntry("ifcinternalorexternalenum",NULL )
+, SchemaEntry("ifcinventorytypeenum",NULL )
+, SchemaEntry("ifcjunctionboxtypeenum",NULL )
+, SchemaEntry("ifclamptypeenum",NULL )
+, SchemaEntry("ifclayersetdirectionenum",NULL )
+, SchemaEntry("ifclightdistributioncurveenum",NULL )
+, SchemaEntry("ifclightemissionsourceenum",NULL )
+, SchemaEntry("ifclightfixturetypeenum",NULL )
+, SchemaEntry("ifcloadgrouptypeenum",NULL )
+, SchemaEntry("ifclogicaloperatorenum",NULL )
+, SchemaEntry("ifcmembertypeenum",NULL )
+, SchemaEntry("ifcmotorconnectiontypeenum",NULL )
+, SchemaEntry("ifcnullstyle",NULL )
+, SchemaEntry("ifcobjecttypeenum",NULL )
+, SchemaEntry("ifcobjectiveenum",NULL )
+, SchemaEntry("ifcoccupanttypeenum",NULL )
+, SchemaEntry("ifcoutlettypeenum",NULL )
+, SchemaEntry("ifcpermeablecoveringoperationenum",NULL )
+, SchemaEntry("ifcphysicalorvirtualenum",NULL )
+, SchemaEntry("ifcpileconstructionenum",NULL )
+, SchemaEntry("ifcpiletypeenum",NULL )
+, SchemaEntry("ifcpipefittingtypeenum",NULL )
+, SchemaEntry("ifcpipesegmenttypeenum",NULL )
+, SchemaEntry("ifcplatetypeenum",NULL )
+, SchemaEntry("ifcproceduretypeenum",NULL )
+, SchemaEntry("ifcprofiletypeenum",NULL )
+, SchemaEntry("ifcprojectorderrecordtypeenum",NULL )
+, SchemaEntry("ifcprojectordertypeenum",NULL )
+, SchemaEntry("ifcprojectedortruelengthenum",NULL )
+, SchemaEntry("ifcpropertysourceenum",NULL )
+, SchemaEntry("ifcprotectivedevicetypeenum",NULL )
+, SchemaEntry("ifcpumptypeenum",NULL )
+, SchemaEntry("ifcrailingtypeenum",NULL )
+, SchemaEntry("ifcrampflighttypeenum",NULL )
+, SchemaEntry("ifcramptypeenum",NULL )
+, SchemaEntry("ifcreflectancemethodenum",NULL )
+, SchemaEntry("ifcreinforcingbarroleenum",NULL )
+, SchemaEntry("ifcreinforcingbarsurfaceenum",NULL )
+, SchemaEntry("ifcresourceconsumptionenum",NULL )
+, SchemaEntry("ifcribplatedirectionenum",NULL )
+, SchemaEntry("ifcroleenum",NULL )
+, SchemaEntry("ifcrooftypeenum",NULL )
+, SchemaEntry("ifcsiprefix",NULL )
+, SchemaEntry("ifcsiunitname",NULL )
+, SchemaEntry("ifcsanitaryterminaltypeenum",NULL )
+, SchemaEntry("ifcsectiontypeenum",NULL )
+, SchemaEntry("ifcsensortypeenum",NULL )
+, SchemaEntry("ifcsequenceenum",NULL )
+, SchemaEntry("ifcservicelifefactortypeenum",NULL )
+, SchemaEntry("ifcservicelifetypeenum",NULL )
+, SchemaEntry("ifcslabtypeenum",NULL )
+, SchemaEntry("ifcsoundscaleenum",NULL )
+, SchemaEntry("ifcspaceheatertypeenum",NULL )
+, SchemaEntry("ifcspacetypeenum",NULL )
+, SchemaEntry("ifcstackterminaltypeenum",NULL )
+, SchemaEntry("ifcstairflighttypeenum",NULL )
+, SchemaEntry("ifcstairtypeenum",NULL )
+, SchemaEntry("ifcstateenum",NULL )
+, SchemaEntry("ifcstructuralcurvetypeenum",NULL )
+, SchemaEntry("ifcstructuralsurfacetypeenum",NULL )
+, SchemaEntry("ifcsurfaceside",NULL )
+, SchemaEntry("ifcsurfacetextureenum",NULL )
+, SchemaEntry("ifcswitchingdevicetypeenum",NULL )
+, SchemaEntry("ifctanktypeenum",NULL )
+, SchemaEntry("ifctendontypeenum",NULL )
+, SchemaEntry("ifctextpath",NULL )
+, SchemaEntry("ifcthermalloadsourceenum",NULL )
+, SchemaEntry("ifcthermalloadtypeenum",NULL )
+, SchemaEntry("ifctimeseriesdatatypeenum",NULL )
+, SchemaEntry("ifctimeseriesscheduletypeenum",NULL )
+, SchemaEntry("ifctransformertypeenum",NULL )
+, SchemaEntry("ifctransitioncode",NULL )
+, SchemaEntry("ifctransportelementtypeenum",NULL )
+, SchemaEntry("ifctrimmingpreference",NULL )
+, SchemaEntry("ifctubebundletypeenum",NULL )
+, SchemaEntry("ifcunitenum",NULL )
+, SchemaEntry("ifcunitaryequipmenttypeenum",NULL )
+, SchemaEntry("ifcvalvetypeenum",NULL )
+, SchemaEntry("ifcvibrationisolatortypeenum",NULL )
+, SchemaEntry("ifcwalltypeenum",NULL )
+, SchemaEntry("ifcwasteterminaltypeenum",NULL )
+, SchemaEntry("ifcwindowpaneloperationenum",NULL )
+, SchemaEntry("ifcwindowpanelpositionenum",NULL )
+, SchemaEntry("ifcwindowstyleconstructionenum",NULL )
+, SchemaEntry("ifcwindowstyleoperationenum",NULL )
+, SchemaEntry("ifcworkcontroltypeenum",NULL )
+, SchemaEntry("ifcactorselect",NULL )
+, SchemaEntry("ifcappliedvalueselect",NULL )
+, SchemaEntry("ifcaxis2placement",NULL )
+, SchemaEntry("ifcbooleanoperand",NULL )
+, SchemaEntry("ifccharacterstyleselect",NULL )
+, SchemaEntry("ifcclassificationnotationselect",NULL )
+, SchemaEntry("ifccolour",NULL )
+, SchemaEntry("ifccolourorfactor",NULL )
+, SchemaEntry("ifcconditioncriterionselect",NULL )
+, SchemaEntry("ifccsgselect",NULL )
+, SchemaEntry("ifccurvefontorscaledcurvefontselect",NULL )
+, SchemaEntry("ifccurveoredgecurve",NULL )
+, SchemaEntry("ifccurvestylefontselect",NULL )
+, SchemaEntry("ifcdatetimeselect",NULL )
+, SchemaEntry("ifcdefinedsymbolselect",NULL )
+, SchemaEntry("ifcderivedmeasurevalue",NULL )
+, SchemaEntry("ifcdocumentselect",NULL )
+, SchemaEntry("ifcdraughtingcalloutelement",NULL )
+, SchemaEntry("ifcfillareastyletileshapeselect",NULL )
+, SchemaEntry("ifcfillstyleselect",NULL )
+, SchemaEntry("ifcgeometricsetselect",NULL )
+, SchemaEntry("ifchatchlinedistanceselect",NULL )
+, SchemaEntry("ifclayereditem",NULL )
+, SchemaEntry("ifclibraryselect",NULL )
+, SchemaEntry("ifclightdistributiondatasourceselect",NULL )
+, SchemaEntry("ifcmaterialselect",NULL )
+, SchemaEntry("ifcmeasurevalue",NULL )
+, SchemaEntry("ifcmetricvalueselect",NULL )
+, SchemaEntry("ifcobjectreferenceselect",NULL )
+, SchemaEntry("ifcorientationselect",NULL )
+, SchemaEntry("ifcpointorvertexpoint",NULL )
+, SchemaEntry("ifcpresentationstyleselect",NULL )
+, SchemaEntry("ifcshell",NULL )
+, SchemaEntry("ifcsimplevalue",NULL )
+, SchemaEntry("ifcsizeselect",NULL )
+, SchemaEntry("ifcspecularhighlightselect",NULL )
+, SchemaEntry("ifcstructuralactivityassignmentselect",NULL )
+, SchemaEntry("ifcsurfaceorfacesurface",NULL )
+, SchemaEntry("ifcsurfacestyleelementselect",NULL )
+, SchemaEntry("ifcsymbolstyleselect",NULL )
+, SchemaEntry("ifctextfontselect",NULL )
+, SchemaEntry("ifctextstyleselect",NULL )
+, SchemaEntry("ifctrimmingselect",NULL )
+, SchemaEntry("ifcunit",NULL )
+, SchemaEntry("ifcvalue",NULL )
+, SchemaEntry("ifcvectorordirection",NULL )
+, SchemaEntry("ifcrepresentationitem",&STEP::ObjectHelper<IfcRepresentationItem,0>::Construct )
+, SchemaEntry("ifcgeometricrepresentationitem",&STEP::ObjectHelper<IfcGeometricRepresentationItem,0>::Construct )
+, SchemaEntry("ifccurve",&STEP::ObjectHelper<IfcCurve,0>::Construct )
+, SchemaEntry("ifcboundedcurve",&STEP::ObjectHelper<IfcBoundedCurve,0>::Construct )
+, SchemaEntry("ifccompositecurve",&STEP::ObjectHelper<IfcCompositeCurve,2>::Construct )
+, SchemaEntry("ifc2dcompositecurve",&STEP::ObjectHelper<Ifc2DCompositeCurve,0>::Construct )
+, SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct )
+, SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct )
+, SchemaEntry("ifcobject",&STEP::ObjectHelper<IfcObject,1>::Construct )
+, SchemaEntry("ifccontrol",&STEP::ObjectHelper<IfcControl,0>::Construct )
+, SchemaEntry("ifcactionrequest",&STEP::ObjectHelper<IfcActionRequest,1>::Construct )
+, SchemaEntry("ifcactor",&STEP::ObjectHelper<IfcActor,1>::Construct )
+, SchemaEntry("ifcactorrole",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct )
+, SchemaEntry("ifctypeproduct",&STEP::ObjectHelper<IfcTypeProduct,2>::Construct )
+, SchemaEntry("ifcelementtype",&STEP::ObjectHelper<IfcElementType,1>::Construct )
+, SchemaEntry("ifcdistributionelementtype",&STEP::ObjectHelper<IfcDistributionElementType,0>::Construct )
+, SchemaEntry("ifcdistributioncontrolelementtype",&STEP::ObjectHelper<IfcDistributionControlElementType,0>::Construct )
+, SchemaEntry("ifcactuatortype",&STEP::ObjectHelper<IfcActuatorType,1>::Construct )
+, SchemaEntry("ifcaddress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdistributionflowelementtype",&STEP::ObjectHelper<IfcDistributionFlowElementType,0>::Construct )
+, SchemaEntry("ifcflowcontrollertype",&STEP::ObjectHelper<IfcFlowControllerType,0>::Construct )
+, SchemaEntry("ifcairterminalboxtype",&STEP::ObjectHelper<IfcAirTerminalBoxType,1>::Construct )
+, SchemaEntry("ifcflowterminaltype",&STEP::ObjectHelper<IfcFlowTerminalType,0>::Construct )
+, SchemaEntry("ifcairterminaltype",&STEP::ObjectHelper<IfcAirTerminalType,1>::Construct )
+, SchemaEntry("ifcenergyconversiondevicetype",&STEP::ObjectHelper<IfcEnergyConversionDeviceType,0>::Construct )
+, SchemaEntry("ifcairtoairheatrecoverytype",&STEP::ObjectHelper<IfcAirToAirHeatRecoveryType,1>::Construct )
+, SchemaEntry("ifcalarmtype",&STEP::ObjectHelper<IfcAlarmType,1>::Construct )
+, SchemaEntry("ifcdraughtingcallout",&STEP::ObjectHelper<IfcDraughtingCallout,1>::Construct )
+, SchemaEntry("ifcdimensioncurvedirectedcallout",&STEP::ObjectHelper<IfcDimensionCurveDirectedCallout,0>::Construct )
+, SchemaEntry("ifcangulardimension",&STEP::ObjectHelper<IfcAngularDimension,0>::Construct )
+, SchemaEntry("ifcproduct",&STEP::ObjectHelper<IfcProduct,2>::Construct )
+, SchemaEntry("ifcannotation",&STEP::ObjectHelper<IfcAnnotation,0>::Construct )
+, SchemaEntry("ifcstyleditem",&STEP::ObjectHelper<IfcStyledItem,3>::Construct )
+, SchemaEntry("ifcannotationoccurrence",&STEP::ObjectHelper<IfcAnnotationOccurrence,0>::Construct )
+, SchemaEntry("ifcannotationcurveoccurrence",&STEP::ObjectHelper<IfcAnnotationCurveOccurrence,0>::Construct )
+, SchemaEntry("ifcannotationfillarea",&STEP::ObjectHelper<IfcAnnotationFillArea,2>::Construct )
+, SchemaEntry("ifcannotationfillareaoccurrence",&STEP::ObjectHelper<IfcAnnotationFillAreaOccurrence,2>::Construct )
+, SchemaEntry("ifcannotationsurface",&STEP::ObjectHelper<IfcAnnotationSurface,2>::Construct )
+, SchemaEntry("ifcannotationsurfaceoccurrence",&STEP::ObjectHelper<IfcAnnotationSurfaceOccurrence,0>::Construct )
+, SchemaEntry("ifcannotationsymboloccurrence",&STEP::ObjectHelper<IfcAnnotationSymbolOccurrence,0>::Construct )
+, SchemaEntry("ifcannotationtextoccurrence",&STEP::ObjectHelper<IfcAnnotationTextOccurrence,0>::Construct )
+, SchemaEntry("ifcapplication",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcappliedvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcappliedvaluerelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcapproval",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcapprovalactorrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcapprovalpropertyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcapprovalrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcprofiledef",&STEP::ObjectHelper<IfcProfileDef,2>::Construct )
+, SchemaEntry("ifcarbitraryclosedprofiledef",&STEP::ObjectHelper<IfcArbitraryClosedProfileDef,1>::Construct )
+, SchemaEntry("ifcarbitraryopenprofiledef",&STEP::ObjectHelper<IfcArbitraryOpenProfileDef,1>::Construct )
+, SchemaEntry("ifcarbitraryprofiledefwithvoids",&STEP::ObjectHelper<IfcArbitraryProfileDefWithVoids,1>::Construct )
+, SchemaEntry("ifcgroup",&STEP::ObjectHelper<IfcGroup,0>::Construct )
+, SchemaEntry("ifcasset",&STEP::ObjectHelper<IfcAsset,9>::Construct )
+, SchemaEntry("ifcparameterizedprofiledef",&STEP::ObjectHelper<IfcParameterizedProfileDef,1>::Construct )
+, SchemaEntry("ifcishapeprofiledef",&STEP::ObjectHelper<IfcIShapeProfileDef,5>::Construct )
+, SchemaEntry("ifcasymmetricishapeprofiledef",&STEP::ObjectHelper<IfcAsymmetricIShapeProfileDef,4>::Construct )
+, SchemaEntry("ifcplacement",&STEP::ObjectHelper<IfcPlacement,1>::Construct )
+, SchemaEntry("ifcaxis1placement",&STEP::ObjectHelper<IfcAxis1Placement,1>::Construct )
+, SchemaEntry("ifcaxis2placement2d",&STEP::ObjectHelper<IfcAxis2Placement2D,1>::Construct )
+, SchemaEntry("ifcaxis2placement3d",&STEP::ObjectHelper<IfcAxis2Placement3D,2>::Construct )
+, SchemaEntry("ifcbsplinecurve",&STEP::ObjectHelper<IfcBSplineCurve,5>::Construct )
+, SchemaEntry("ifcelement",&STEP::ObjectHelper<IfcElement,1>::Construct )
+, SchemaEntry("ifcbuildingelement",&STEP::ObjectHelper<IfcBuildingElement,0>::Construct )
+, SchemaEntry("ifcbeam",&STEP::ObjectHelper<IfcBeam,0>::Construct )
+, SchemaEntry("ifcbuildingelementtype",&STEP::ObjectHelper<IfcBuildingElementType,0>::Construct )
+, SchemaEntry("ifcbeamtype",&STEP::ObjectHelper<IfcBeamType,1>::Construct )
+, SchemaEntry("ifcbeziercurve",&STEP::ObjectHelper<IfcBezierCurve,0>::Construct )
+, SchemaEntry("ifcsurfacetexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcblobtexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccsgprimitive3d",&STEP::ObjectHelper<IfcCsgPrimitive3D,1>::Construct )
+, SchemaEntry("ifcblock",&STEP::ObjectHelper<IfcBlock,3>::Construct )
+, SchemaEntry("ifcboilertype",&STEP::ObjectHelper<IfcBoilerType,1>::Construct )
+, SchemaEntry("ifcbooleanresult",&STEP::ObjectHelper<IfcBooleanResult,3>::Construct )
+, SchemaEntry("ifcbooleanclippingresult",&STEP::ObjectHelper<IfcBooleanClippingResult,0>::Construct )
+, SchemaEntry("ifcboundarycondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcboundaryedgecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcboundaryfacecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcboundarynodecondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcboundarynodeconditionwarping",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsurface",&STEP::ObjectHelper<IfcSurface,0>::Construct )
+, SchemaEntry("ifcboundedsurface",&STEP::ObjectHelper<IfcBoundedSurface,0>::Construct )
+, SchemaEntry("ifcboundingbox",&STEP::ObjectHelper<IfcBoundingBox,4>::Construct )
+, SchemaEntry("ifchalfspacesolid",&STEP::ObjectHelper<IfcHalfSpaceSolid,2>::Construct )
+, SchemaEntry("ifcboxedhalfspace",&STEP::ObjectHelper<IfcBoxedHalfSpace,1>::Construct )
+, SchemaEntry("ifcspatialstructureelement",&STEP::ObjectHelper<IfcSpatialStructureElement,2>::Construct )
+, SchemaEntry("ifcbuilding",&STEP::ObjectHelper<IfcBuilding,3>::Construct )
+, SchemaEntry("ifcbuildingelementcomponent",&STEP::ObjectHelper<IfcBuildingElementComponent,0>::Construct )
+, SchemaEntry("ifcbuildingelementpart",&STEP::ObjectHelper<IfcBuildingElementPart,0>::Construct )
+, SchemaEntry("ifcbuildingelementproxy",&STEP::ObjectHelper<IfcBuildingElementProxy,1>::Construct )
+, SchemaEntry("ifcbuildingelementproxytype",&STEP::ObjectHelper<IfcBuildingElementProxyType,1>::Construct )
+, SchemaEntry("ifcbuildingstorey",&STEP::ObjectHelper<IfcBuildingStorey,1>::Construct )
+, SchemaEntry("ifccshapeprofiledef",&STEP::ObjectHelper<IfcCShapeProfileDef,6>::Construct )
+, SchemaEntry("ifcflowfittingtype",&STEP::ObjectHelper<IfcFlowFittingType,0>::Construct )
+, SchemaEntry("ifccablecarrierfittingtype",&STEP::ObjectHelper<IfcCableCarrierFittingType,1>::Construct )
+, SchemaEntry("ifcflowsegmenttype",&STEP::ObjectHelper<IfcFlowSegmentType,0>::Construct )
+, SchemaEntry("ifccablecarriersegmenttype",&STEP::ObjectHelper<IfcCableCarrierSegmentType,1>::Construct )
+, SchemaEntry("ifccablesegmenttype",&STEP::ObjectHelper<IfcCableSegmentType,1>::Construct )
+, SchemaEntry("ifccalendardate",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpoint",&STEP::ObjectHelper<IfcPoint,0>::Construct )
+, SchemaEntry("ifccartesianpoint",&STEP::ObjectHelper<IfcCartesianPoint,1>::Construct )
+, SchemaEntry("ifccartesiantransformationoperator",&STEP::ObjectHelper<IfcCartesianTransformationOperator,4>::Construct )
+, SchemaEntry("ifccartesiantransformationoperator2d",&STEP::ObjectHelper<IfcCartesianTransformationOperator2D,0>::Construct )
+, SchemaEntry("ifccartesiantransformationoperator2dnonuniform",&STEP::ObjectHelper<IfcCartesianTransformationOperator2DnonUniform,1>::Construct )
+, SchemaEntry("ifccartesiantransformationoperator3d",&STEP::ObjectHelper<IfcCartesianTransformationOperator3D,1>::Construct )
+, SchemaEntry("ifccartesiantransformationoperator3dnonuniform",&STEP::ObjectHelper<IfcCartesianTransformationOperator3DnonUniform,2>::Construct )
+, SchemaEntry("ifccenterlineprofiledef",&STEP::ObjectHelper<IfcCenterLineProfileDef,1>::Construct )
+, SchemaEntry("ifcfeatureelement",&STEP::ObjectHelper<IfcFeatureElement,0>::Construct )
+, SchemaEntry("ifcfeatureelementsubtraction",&STEP::ObjectHelper<IfcFeatureElementSubtraction,0>::Construct )
+, SchemaEntry("ifcedgefeature",&STEP::ObjectHelper<IfcEdgeFeature,1>::Construct )
+, SchemaEntry("ifcchamferedgefeature",&STEP::ObjectHelper<IfcChamferEdgeFeature,2>::Construct )
+, SchemaEntry("ifcchillertype",&STEP::ObjectHelper<IfcChillerType,1>::Construct )
+, SchemaEntry("ifcconic",&STEP::ObjectHelper<IfcConic,1>::Construct )
+, SchemaEntry("ifccircle",&STEP::ObjectHelper<IfcCircle,1>::Construct )
+, SchemaEntry("ifccircleprofiledef",&STEP::ObjectHelper<IfcCircleProfileDef,1>::Construct )
+, SchemaEntry("ifccirclehollowprofiledef",&STEP::ObjectHelper<IfcCircleHollowProfileDef,1>::Construct )
+, SchemaEntry("ifcclassification",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcclassificationitem",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcclassificationitemrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcclassificationnotation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcclassificationnotationfacet",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcexternalreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcclassificationreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctopologicalrepresentationitem",&STEP::ObjectHelper<IfcTopologicalRepresentationItem,0>::Construct )
+, SchemaEntry("ifcconnectedfaceset",&STEP::ObjectHelper<IfcConnectedFaceSet,1>::Construct )
+, SchemaEntry("ifcclosedshell",&STEP::ObjectHelper<IfcClosedShell,0>::Construct )
+, SchemaEntry("ifccoiltype",&STEP::ObjectHelper<IfcCoilType,1>::Construct )
+, SchemaEntry("ifccolourspecification",&STEP::ObjectHelper<IfcColourSpecification,1>::Construct )
+, SchemaEntry("ifccolourrgb",&STEP::ObjectHelper<IfcColourRgb,3>::Construct )
+, SchemaEntry("ifccolumn",&STEP::ObjectHelper<IfcColumn,0>::Construct )
+, SchemaEntry("ifccolumntype",&STEP::ObjectHelper<IfcColumnType,1>::Construct )
+, SchemaEntry("ifcproperty",&STEP::ObjectHelper<IfcProperty,2>::Construct )
+, SchemaEntry("ifccomplexproperty",&STEP::ObjectHelper<IfcComplexProperty,2>::Construct )
+, SchemaEntry("ifccompositecurvesegment",&STEP::ObjectHelper<IfcCompositeCurveSegment,3>::Construct )
+, SchemaEntry("ifccompositeprofiledef",&STEP::ObjectHelper<IfcCompositeProfileDef,2>::Construct )
+, SchemaEntry("ifcflowmovingdevicetype",&STEP::ObjectHelper<IfcFlowMovingDeviceType,0>::Construct )
+, SchemaEntry("ifccompressortype",&STEP::ObjectHelper<IfcCompressorType,1>::Construct )
+, SchemaEntry("ifccondensertype",&STEP::ObjectHelper<IfcCondenserType,1>::Construct )
+, SchemaEntry("ifccondition",&STEP::ObjectHelper<IfcCondition,0>::Construct )
+, SchemaEntry("ifcconditioncriterion",&STEP::ObjectHelper<IfcConditionCriterion,2>::Construct )
+, SchemaEntry("ifcconnectiongeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconnectioncurvegeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconnectionpointgeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconnectionpointeccentricity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconnectionportgeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconnectionsurfacegeometry",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconstraint",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconstraintaggregationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconstraintclassificationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcconstraintrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcresource",&STEP::ObjectHelper<IfcResource,0>::Construct )
+, SchemaEntry("ifcconstructionresource",&STEP::ObjectHelper<IfcConstructionResource,4>::Construct )
+, SchemaEntry("ifcconstructionequipmentresource",&STEP::ObjectHelper<IfcConstructionEquipmentResource,0>::Construct )
+, SchemaEntry("ifcconstructionmaterialresource",&STEP::ObjectHelper<IfcConstructionMaterialResource,2>::Construct )
+, SchemaEntry("ifcconstructionproductresource",&STEP::ObjectHelper<IfcConstructionProductResource,0>::Construct )
+, SchemaEntry("ifcnamedunit",&STEP::ObjectHelper<IfcNamedUnit,2>::Construct )
+, SchemaEntry("ifccontextdependentunit",&STEP::ObjectHelper<IfcContextDependentUnit,1>::Construct )
+, SchemaEntry("ifccontrollertype",&STEP::ObjectHelper<IfcControllerType,1>::Construct )
+, SchemaEntry("ifcconversionbasedunit",&STEP::ObjectHelper<IfcConversionBasedUnit,2>::Construct )
+, SchemaEntry("ifccooledbeamtype",&STEP::ObjectHelper<IfcCooledBeamType,1>::Construct )
+, SchemaEntry("ifccoolingtowertype",&STEP::ObjectHelper<IfcCoolingTowerType,1>::Construct )
+, SchemaEntry("ifccoordinateduniversaltimeoffset",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccostitem",&STEP::ObjectHelper<IfcCostItem,0>::Construct )
+, SchemaEntry("ifccostschedule",&STEP::ObjectHelper<IfcCostSchedule,8>::Construct )
+, SchemaEntry("ifccostvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccovering",&STEP::ObjectHelper<IfcCovering,1>::Construct )
+, SchemaEntry("ifccoveringtype",&STEP::ObjectHelper<IfcCoveringType,1>::Construct )
+, SchemaEntry("ifccranerailashapeprofiledef",&STEP::ObjectHelper<IfcCraneRailAShapeProfileDef,12>::Construct )
+, SchemaEntry("ifccranerailfshapeprofiledef",&STEP::ObjectHelper<IfcCraneRailFShapeProfileDef,9>::Construct )
+, SchemaEntry("ifccrewresource",&STEP::ObjectHelper<IfcCrewResource,0>::Construct )
+, SchemaEntry("ifcsolidmodel",&STEP::ObjectHelper<IfcSolidModel,0>::Construct )
+, SchemaEntry("ifccsgsolid",&STEP::ObjectHelper<IfcCsgSolid,1>::Construct )
+, SchemaEntry("ifccurrencyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccurtainwall",&STEP::ObjectHelper<IfcCurtainWall,0>::Construct )
+, SchemaEntry("ifccurtainwalltype",&STEP::ObjectHelper<IfcCurtainWallType,1>::Construct )
+, SchemaEntry("ifccurveboundedplane",&STEP::ObjectHelper<IfcCurveBoundedPlane,3>::Construct )
+, SchemaEntry("ifcpresentationstyle",&STEP::ObjectHelper<IfcPresentationStyle,1>::Construct )
+, SchemaEntry("ifccurvestyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccurvestylefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccurvestylefontandscaling",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifccurvestylefontpattern",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdampertype",&STEP::ObjectHelper<IfcDamperType,1>::Construct )
+, SchemaEntry("ifcdateandtime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdefinedsymbol",&STEP::ObjectHelper<IfcDefinedSymbol,2>::Construct )
+, SchemaEntry("ifcderivedprofiledef",&STEP::ObjectHelper<IfcDerivedProfileDef,3>::Construct )
+, SchemaEntry("ifcderivedunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcderivedunitelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdiameterdimension",&STEP::ObjectHelper<IfcDiameterDimension,0>::Construct )
+, SchemaEntry("ifcdraughtingcalloutrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdimensioncalloutrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdimensioncurve",&STEP::ObjectHelper<IfcDimensionCurve,0>::Construct )
+, SchemaEntry("ifcterminatorsymbol",&STEP::ObjectHelper<IfcTerminatorSymbol,1>::Construct )
+, SchemaEntry("ifcdimensioncurveterminator",&STEP::ObjectHelper<IfcDimensionCurveTerminator,1>::Construct )
+, SchemaEntry("ifcdimensionpair",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdimensionalexponents",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdirection",&STEP::ObjectHelper<IfcDirection,1>::Construct )
+, SchemaEntry("ifcelementcomponent",&STEP::ObjectHelper<IfcElementComponent,0>::Construct )
+, SchemaEntry("ifcdiscreteaccessory",&STEP::ObjectHelper<IfcDiscreteAccessory,0>::Construct )
+, SchemaEntry("ifcelementcomponenttype",&STEP::ObjectHelper<IfcElementComponentType,0>::Construct )
+, SchemaEntry("ifcdiscreteaccessorytype",&STEP::ObjectHelper<IfcDiscreteAccessoryType,0>::Construct )
+, SchemaEntry("ifcdistributionelement",&STEP::ObjectHelper<IfcDistributionElement,0>::Construct )
+, SchemaEntry("ifcdistributionflowelement",&STEP::ObjectHelper<IfcDistributionFlowElement,0>::Construct )
+, SchemaEntry("ifcdistributionchamberelement",&STEP::ObjectHelper<IfcDistributionChamberElement,0>::Construct )
+, SchemaEntry("ifcdistributionchamberelementtype",&STEP::ObjectHelper<IfcDistributionChamberElementType,1>::Construct )
+, SchemaEntry("ifcdistributioncontrolelement",&STEP::ObjectHelper<IfcDistributionControlElement,1>::Construct )
+, SchemaEntry("ifcport",&STEP::ObjectHelper<IfcPort,0>::Construct )
+, SchemaEntry("ifcdistributionport",&STEP::ObjectHelper<IfcDistributionPort,1>::Construct )
+, SchemaEntry("ifcdocumentelectronicformat",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdocumentinformation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdocumentinformationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdocumentreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdoor",&STEP::ObjectHelper<IfcDoor,2>::Construct )
+, SchemaEntry("ifcpropertydefinition",&STEP::ObjectHelper<IfcPropertyDefinition,0>::Construct )
+, SchemaEntry("ifcpropertysetdefinition",&STEP::ObjectHelper<IfcPropertySetDefinition,0>::Construct )
+, SchemaEntry("ifcdoorliningproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdoorpanelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdoorstyle",&STEP::ObjectHelper<IfcDoorStyle,4>::Construct )
+, SchemaEntry("ifcpredefineditem",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedcolour",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdraughtingpredefinedcolour",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedcurvefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdraughtingpredefinedcurvefont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcdraughtingpredefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcductfittingtype",&STEP::ObjectHelper<IfcDuctFittingType,1>::Construct )
+, SchemaEntry("ifcductsegmenttype",&STEP::ObjectHelper<IfcDuctSegmentType,1>::Construct )
+, SchemaEntry("ifcflowtreatmentdevicetype",&STEP::ObjectHelper<IfcFlowTreatmentDeviceType,0>::Construct )
+, SchemaEntry("ifcductsilencertype",&STEP::ObjectHelper<IfcDuctSilencerType,1>::Construct )
+, SchemaEntry("ifcedge",&STEP::ObjectHelper<IfcEdge,2>::Construct )
+, SchemaEntry("ifcedgecurve",&STEP::ObjectHelper<IfcEdgeCurve,2>::Construct )
+, SchemaEntry("ifcloop",&STEP::ObjectHelper<IfcLoop,0>::Construct )
+, SchemaEntry("ifcedgeloop",&STEP::ObjectHelper<IfcEdgeLoop,1>::Construct )
+, SchemaEntry("ifcelectricappliancetype",&STEP::ObjectHelper<IfcElectricApplianceType,1>::Construct )
+, SchemaEntry("ifcflowcontroller",&STEP::ObjectHelper<IfcFlowController,0>::Construct )
+, SchemaEntry("ifcelectricdistributionpoint",&STEP::ObjectHelper<IfcElectricDistributionPoint,2>::Construct )
+, SchemaEntry("ifcflowstoragedevicetype",&STEP::ObjectHelper<IfcFlowStorageDeviceType,0>::Construct )
+, SchemaEntry("ifcelectricflowstoragedevicetype",&STEP::ObjectHelper<IfcElectricFlowStorageDeviceType,1>::Construct )
+, SchemaEntry("ifcelectricgeneratortype",&STEP::ObjectHelper<IfcElectricGeneratorType,1>::Construct )
+, SchemaEntry("ifcelectricheatertype",&STEP::ObjectHelper<IfcElectricHeaterType,1>::Construct )
+, SchemaEntry("ifcelectricmotortype",&STEP::ObjectHelper<IfcElectricMotorType,1>::Construct )
+, SchemaEntry("ifcelectrictimecontroltype",&STEP::ObjectHelper<IfcElectricTimeControlType,1>::Construct )
+, SchemaEntry("ifcenergyproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcelectricalbaseproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsystem",&STEP::ObjectHelper<IfcSystem,0>::Construct )
+, SchemaEntry("ifcelectricalcircuit",&STEP::ObjectHelper<IfcElectricalCircuit,0>::Construct )
+, SchemaEntry("ifcelectricalelement",&STEP::ObjectHelper<IfcElectricalElement,0>::Construct )
+, SchemaEntry("ifcelementassembly",&STEP::ObjectHelper<IfcElementAssembly,2>::Construct )
+, SchemaEntry("ifcelementquantity",&STEP::ObjectHelper<IfcElementQuantity,2>::Construct )
+, SchemaEntry("ifcelementarysurface",&STEP::ObjectHelper<IfcElementarySurface,1>::Construct )
+, SchemaEntry("ifcellipse",&STEP::ObjectHelper<IfcEllipse,2>::Construct )
+, SchemaEntry("ifcellipseprofiledef",&STEP::ObjectHelper<IfcEllipseProfileDef,2>::Construct )
+, SchemaEntry("ifcenergyconversiondevice",&STEP::ObjectHelper<IfcEnergyConversionDevice,0>::Construct )
+, SchemaEntry("ifcenvironmentalimpactvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcequipmentelement",&STEP::ObjectHelper<IfcEquipmentElement,0>::Construct )
+, SchemaEntry("ifcequipmentstandard",&STEP::ObjectHelper<IfcEquipmentStandard,0>::Construct )
+, SchemaEntry("ifcevaporativecoolertype",&STEP::ObjectHelper<IfcEvaporativeCoolerType,1>::Construct )
+, SchemaEntry("ifcevaporatortype",&STEP::ObjectHelper<IfcEvaporatorType,1>::Construct )
+, SchemaEntry("ifcmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcextendedmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcexternallydefinedhatchstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcexternallydefinedsurfacestyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcexternallydefinedsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcexternallydefinedtextfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsweptareasolid",&STEP::ObjectHelper<IfcSweptAreaSolid,2>::Construct )
+, SchemaEntry("ifcextrudedareasolid",&STEP::ObjectHelper<IfcExtrudedAreaSolid,2>::Construct )
+, SchemaEntry("ifcface",&STEP::ObjectHelper<IfcFace,1>::Construct )
+, SchemaEntry("ifcfacebasedsurfacemodel",&STEP::ObjectHelper<IfcFaceBasedSurfaceModel,1>::Construct )
+, SchemaEntry("ifcfacebound",&STEP::ObjectHelper<IfcFaceBound,2>::Construct )
+, SchemaEntry("ifcfaceouterbound",&STEP::ObjectHelper<IfcFaceOuterBound,0>::Construct )
+, SchemaEntry("ifcfacesurface",&STEP::ObjectHelper<IfcFaceSurface,2>::Construct )
+, SchemaEntry("ifcmanifoldsolidbrep",&STEP::ObjectHelper<IfcManifoldSolidBrep,1>::Construct )
+, SchemaEntry("ifcfacetedbrep",&STEP::ObjectHelper<IfcFacetedBrep,0>::Construct )
+, SchemaEntry("ifcfacetedbrepwithvoids",&STEP::ObjectHelper<IfcFacetedBrepWithVoids,1>::Construct )
+, SchemaEntry("ifcstructuralconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcfailureconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcfantype",&STEP::ObjectHelper<IfcFanType,1>::Construct )
+, SchemaEntry("ifcfastener",&STEP::ObjectHelper<IfcFastener,0>::Construct )
+, SchemaEntry("ifcfastenertype",&STEP::ObjectHelper<IfcFastenerType,0>::Construct )
+, SchemaEntry("ifcfeatureelementaddition",&STEP::ObjectHelper<IfcFeatureElementAddition,0>::Construct )
+, SchemaEntry("ifcfillareastyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcfillareastylehatching",&STEP::ObjectHelper<IfcFillAreaStyleHatching,5>::Construct )
+, SchemaEntry("ifcfillareastyletilesymbolwithstyle",&STEP::ObjectHelper<IfcFillAreaStyleTileSymbolWithStyle,1>::Construct )
+, SchemaEntry("ifcfillareastyletiles",&STEP::ObjectHelper<IfcFillAreaStyleTiles,3>::Construct )
+, SchemaEntry("ifcfiltertype",&STEP::ObjectHelper<IfcFilterType,1>::Construct )
+, SchemaEntry("ifcfiresuppressionterminaltype",&STEP::ObjectHelper<IfcFireSuppressionTerminalType,1>::Construct )
+, SchemaEntry("ifcflowfitting",&STEP::ObjectHelper<IfcFlowFitting,0>::Construct )
+, SchemaEntry("ifcflowinstrumenttype",&STEP::ObjectHelper<IfcFlowInstrumentType,1>::Construct )
+, SchemaEntry("ifcflowmetertype",&STEP::ObjectHelper<IfcFlowMeterType,1>::Construct )
+, SchemaEntry("ifcflowmovingdevice",&STEP::ObjectHelper<IfcFlowMovingDevice,0>::Construct )
+, SchemaEntry("ifcflowsegment",&STEP::ObjectHelper<IfcFlowSegment,0>::Construct )
+, SchemaEntry("ifcflowstoragedevice",&STEP::ObjectHelper<IfcFlowStorageDevice,0>::Construct )
+, SchemaEntry("ifcflowterminal",&STEP::ObjectHelper<IfcFlowTerminal,0>::Construct )
+, SchemaEntry("ifcflowtreatmentdevice",&STEP::ObjectHelper<IfcFlowTreatmentDevice,0>::Construct )
+, SchemaEntry("ifcfluidflowproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcfooting",&STEP::ObjectHelper<IfcFooting,1>::Construct )
+, SchemaEntry("ifcfuelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcfurnishingelement",&STEP::ObjectHelper<IfcFurnishingElement,0>::Construct )
+, SchemaEntry("ifcfurnishingelementtype",&STEP::ObjectHelper<IfcFurnishingElementType,0>::Construct )
+, SchemaEntry("ifcfurniturestandard",&STEP::ObjectHelper<IfcFurnitureStandard,0>::Construct )
+, SchemaEntry("ifcfurnituretype",&STEP::ObjectHelper<IfcFurnitureType,1>::Construct )
+, SchemaEntry("ifcgasterminaltype",&STEP::ObjectHelper<IfcGasTerminalType,1>::Construct )
+, SchemaEntry("ifcgeneralmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcgeneralprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcgeometricset",&STEP::ObjectHelper<IfcGeometricSet,1>::Construct )
+, SchemaEntry("ifcgeometriccurveset",&STEP::ObjectHelper<IfcGeometricCurveSet,0>::Construct )
+, SchemaEntry("ifcrepresentationcontext",&STEP::ObjectHelper<IfcRepresentationContext,2>::Construct )
+, SchemaEntry("ifcgeometricrepresentationcontext",&STEP::ObjectHelper<IfcGeometricRepresentationContext,4>::Construct )
+, SchemaEntry("ifcgeometricrepresentationsubcontext",&STEP::ObjectHelper<IfcGeometricRepresentationSubContext,4>::Construct )
+, SchemaEntry("ifcgrid",&STEP::ObjectHelper<IfcGrid,3>::Construct )
+, SchemaEntry("ifcgridaxis",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcobjectplacement",&STEP::ObjectHelper<IfcObjectPlacement,0>::Construct )
+, SchemaEntry("ifcgridplacement",&STEP::ObjectHelper<IfcGridPlacement,2>::Construct )
+, SchemaEntry("ifcheatexchangertype",&STEP::ObjectHelper<IfcHeatExchangerType,1>::Construct )
+, SchemaEntry("ifchumidifiertype",&STEP::ObjectHelper<IfcHumidifierType,1>::Construct )
+, SchemaEntry("ifchygroscopicmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcimagetexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcinventory",&STEP::ObjectHelper<IfcInventory,6>::Construct )
+, SchemaEntry("ifctimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcirregulartimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcirregulartimeseriesvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcjunctionboxtype",&STEP::ObjectHelper<IfcJunctionBoxType,1>::Construct )
+, SchemaEntry("ifclshapeprofiledef",&STEP::ObjectHelper<IfcLShapeProfileDef,8>::Construct )
+, SchemaEntry("ifclaborresource",&STEP::ObjectHelper<IfcLaborResource,1>::Construct )
+, SchemaEntry("ifclamptype",&STEP::ObjectHelper<IfcLampType,1>::Construct )
+, SchemaEntry("ifclibraryinformation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifclibraryreference",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifclightdistributiondata",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifclightfixturetype",&STEP::ObjectHelper<IfcLightFixtureType,1>::Construct )
+, SchemaEntry("ifclightintensitydistribution",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifclightsource",&STEP::ObjectHelper<IfcLightSource,4>::Construct )
+, SchemaEntry("ifclightsourceambient",&STEP::ObjectHelper<IfcLightSourceAmbient,0>::Construct )
+, SchemaEntry("ifclightsourcedirectional",&STEP::ObjectHelper<IfcLightSourceDirectional,1>::Construct )
+, SchemaEntry("ifclightsourcegoniometric",&STEP::ObjectHelper<IfcLightSourceGoniometric,6>::Construct )
+, SchemaEntry("ifclightsourcepositional",&STEP::ObjectHelper<IfcLightSourcePositional,5>::Construct )
+, SchemaEntry("ifclightsourcespot",&STEP::ObjectHelper<IfcLightSourceSpot,4>::Construct )
+, SchemaEntry("ifcline",&STEP::ObjectHelper<IfcLine,2>::Construct )
+, SchemaEntry("ifclineardimension",&STEP::ObjectHelper<IfcLinearDimension,0>::Construct )
+, SchemaEntry("ifclocalplacement",&STEP::ObjectHelper<IfcLocalPlacement,2>::Construct )
+, SchemaEntry("ifclocaltime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmappeditem",&STEP::ObjectHelper<IfcMappedItem,2>::Construct )
+, SchemaEntry("ifcmaterial",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmaterialclassificationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcproductrepresentation",&STEP::ObjectHelper<IfcProductRepresentation,3>::Construct )
+, SchemaEntry("ifcmaterialdefinitionrepresentation",&STEP::ObjectHelper<IfcMaterialDefinitionRepresentation,1>::Construct )
+, SchemaEntry("ifcmateriallayer",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmateriallayerset",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmateriallayersetusage",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmateriallist",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmeasurewithunit",&STEP::ObjectHelper<IfcMeasureWithUnit,2>::Construct )
+, SchemaEntry("ifcmechanicalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmechanicalconcretematerialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmechanicalfastener",&STEP::ObjectHelper<IfcMechanicalFastener,2>::Construct )
+, SchemaEntry("ifcmechanicalfastenertype",&STEP::ObjectHelper<IfcMechanicalFastenerType,0>::Construct )
+, SchemaEntry("ifcmechanicalsteelmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmember",&STEP::ObjectHelper<IfcMember,0>::Construct )
+, SchemaEntry("ifcmembertype",&STEP::ObjectHelper<IfcMemberType,1>::Construct )
+, SchemaEntry("ifcmetric",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmonetaryunit",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcmotorconnectiontype",&STEP::ObjectHelper<IfcMotorConnectionType,1>::Construct )
+, SchemaEntry("ifcprocess",&STEP::ObjectHelper<IfcProcess,0>::Construct )
+, SchemaEntry("ifctask",&STEP::ObjectHelper<IfcTask,5>::Construct )
+, SchemaEntry("ifcmove",&STEP::ObjectHelper<IfcMove,3>::Construct )
+, SchemaEntry("ifcobjective",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcoccupant",&STEP::ObjectHelper<IfcOccupant,1>::Construct )
+, SchemaEntry("ifcoffsetcurve2d",&STEP::ObjectHelper<IfcOffsetCurve2D,3>::Construct )
+, SchemaEntry("ifcoffsetcurve3d",&STEP::ObjectHelper<IfcOffsetCurve3D,4>::Construct )
+, SchemaEntry("ifconedirectionrepeatfactor",&STEP::ObjectHelper<IfcOneDirectionRepeatFactor,1>::Construct )
+, SchemaEntry("ifcopenshell",&STEP::ObjectHelper<IfcOpenShell,0>::Construct )
+, SchemaEntry("ifcopeningelement",&STEP::ObjectHelper<IfcOpeningElement,0>::Construct )
+, SchemaEntry("ifcopticalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcorderaction",&STEP::ObjectHelper<IfcOrderAction,1>::Construct )
+, SchemaEntry("ifcorganization",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcorganizationrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcorientededge",&STEP::ObjectHelper<IfcOrientedEdge,2>::Construct )
+, SchemaEntry("ifcoutlettype",&STEP::ObjectHelper<IfcOutletType,1>::Construct )
+, SchemaEntry("ifcownerhistory",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpath",&STEP::ObjectHelper<IfcPath,1>::Construct )
+, SchemaEntry("ifcperformancehistory",&STEP::ObjectHelper<IfcPerformanceHistory,1>::Construct )
+, SchemaEntry("ifcpermeablecoveringproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpermit",&STEP::ObjectHelper<IfcPermit,1>::Construct )
+, SchemaEntry("ifcperson",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpersonandorganization",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcphysicalquantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcphysicalcomplexquantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcphysicalsimplequantity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpile",&STEP::ObjectHelper<IfcPile,2>::Construct )
+, SchemaEntry("ifcpipefittingtype",&STEP::ObjectHelper<IfcPipeFittingType,1>::Construct )
+, SchemaEntry("ifcpipesegmenttype",&STEP::ObjectHelper<IfcPipeSegmentType,1>::Construct )
+, SchemaEntry("ifcpixeltexture",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcplanarextent",&STEP::ObjectHelper<IfcPlanarExtent,2>::Construct )
+, SchemaEntry("ifcplanarbox",&STEP::ObjectHelper<IfcPlanarBox,1>::Construct )
+, SchemaEntry("ifcplane",&STEP::ObjectHelper<IfcPlane,0>::Construct )
+, SchemaEntry("ifcplate",&STEP::ObjectHelper<IfcPlate,0>::Construct )
+, SchemaEntry("ifcplatetype",&STEP::ObjectHelper<IfcPlateType,1>::Construct )
+, SchemaEntry("ifcpointoncurve",&STEP::ObjectHelper<IfcPointOnCurve,2>::Construct )
+, SchemaEntry("ifcpointonsurface",&STEP::ObjectHelper<IfcPointOnSurface,3>::Construct )
+, SchemaEntry("ifcpolyloop",&STEP::ObjectHelper<IfcPolyLoop,1>::Construct )
+, SchemaEntry("ifcpolygonalboundedhalfspace",&STEP::ObjectHelper<IfcPolygonalBoundedHalfSpace,2>::Construct )
+, SchemaEntry("ifcpolyline",&STEP::ObjectHelper<IfcPolyline,1>::Construct )
+, SchemaEntry("ifcpostaladdress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefineddimensionsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedpointmarkersymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpredefinedterminatorsymbol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpresentationlayerassignment",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpresentationlayerwithstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpresentationstyleassignment",&STEP::ObjectHelper<IfcPresentationStyleAssignment,1>::Construct )
+, SchemaEntry("ifcprocedure",&STEP::ObjectHelper<IfcProcedure,3>::Construct )
+, SchemaEntry("ifcproductdefinitionshape",&STEP::ObjectHelper<IfcProductDefinitionShape,0>::Construct )
+, SchemaEntry("ifcproductsofcombustionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcproject",&STEP::ObjectHelper<IfcProject,4>::Construct )
+, SchemaEntry("ifcprojectorder",&STEP::ObjectHelper<IfcProjectOrder,3>::Construct )
+, SchemaEntry("ifcprojectorderrecord",&STEP::ObjectHelper<IfcProjectOrderRecord,2>::Construct )
+, SchemaEntry("ifcprojectioncurve",&STEP::ObjectHelper<IfcProjectionCurve,0>::Construct )
+, SchemaEntry("ifcprojectionelement",&STEP::ObjectHelper<IfcProjectionElement,0>::Construct )
+, SchemaEntry("ifcsimpleproperty",&STEP::ObjectHelper<IfcSimpleProperty,0>::Construct )
+, SchemaEntry("ifcpropertyboundedvalue",&STEP::ObjectHelper<IfcPropertyBoundedValue,3>::Construct )
+, SchemaEntry("ifcpropertyconstraintrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpropertydependencyrelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpropertyenumeratedvalue",&STEP::ObjectHelper<IfcPropertyEnumeratedValue,2>::Construct )
+, SchemaEntry("ifcpropertyenumeration",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcpropertylistvalue",&STEP::ObjectHelper<IfcPropertyListValue,2>::Construct )
+, SchemaEntry("ifcpropertyreferencevalue",&STEP::ObjectHelper<IfcPropertyReferenceValue,2>::Construct )
+, SchemaEntry("ifcpropertyset",&STEP::ObjectHelper<IfcPropertySet,1>::Construct )
+, SchemaEntry("ifcpropertysinglevalue",&STEP::ObjectHelper<IfcPropertySingleValue,2>::Construct )
+, SchemaEntry("ifcpropertytablevalue",&STEP::ObjectHelper<IfcPropertyTableValue,5>::Construct )
+, SchemaEntry("ifcprotectivedevicetype",&STEP::ObjectHelper<IfcProtectiveDeviceType,1>::Construct )
+, SchemaEntry("ifcproxy",&STEP::ObjectHelper<IfcProxy,2>::Construct )
+, SchemaEntry("ifcpumptype",&STEP::ObjectHelper<IfcPumpType,1>::Construct )
+, SchemaEntry("ifcquantityarea",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcquantitycount",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcquantitylength",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcquantitytime",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcquantityvolume",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcquantityweight",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcradiusdimension",&STEP::ObjectHelper<IfcRadiusDimension,0>::Construct )
+, SchemaEntry("ifcrailing",&STEP::ObjectHelper<IfcRailing,1>::Construct )
+, SchemaEntry("ifcrailingtype",&STEP::ObjectHelper<IfcRailingType,1>::Construct )
+, SchemaEntry("ifcramp",&STEP::ObjectHelper<IfcRamp,1>::Construct )
+, SchemaEntry("ifcrampflight",&STEP::ObjectHelper<IfcRampFlight,0>::Construct )
+, SchemaEntry("ifcrampflighttype",&STEP::ObjectHelper<IfcRampFlightType,1>::Construct )
+, SchemaEntry("ifcrationalbeziercurve",&STEP::ObjectHelper<IfcRationalBezierCurve,1>::Construct )
+, SchemaEntry("ifcrectangleprofiledef",&STEP::ObjectHelper<IfcRectangleProfileDef,2>::Construct )
+, SchemaEntry("ifcrectanglehollowprofiledef",&STEP::ObjectHelper<IfcRectangleHollowProfileDef,3>::Construct )
+, SchemaEntry("ifcrectangularpyramid",&STEP::ObjectHelper<IfcRectangularPyramid,3>::Construct )
+, SchemaEntry("ifcrectangulartrimmedsurface",&STEP::ObjectHelper<IfcRectangularTrimmedSurface,7>::Construct )
+, SchemaEntry("ifcreferencesvaluedocument",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcregulartimeseries",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreinforcementbarproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreinforcementdefinitionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreinforcingelement",&STEP::ObjectHelper<IfcReinforcingElement,1>::Construct )
+, SchemaEntry("ifcreinforcingbar",&STEP::ObjectHelper<IfcReinforcingBar,5>::Construct )
+, SchemaEntry("ifcreinforcingmesh",&STEP::ObjectHelper<IfcReinforcingMesh,8>::Construct )
+, SchemaEntry("ifcrelationship",&STEP::ObjectHelper<IfcRelationship,0>::Construct )
+, SchemaEntry("ifcreldecomposes",&STEP::ObjectHelper<IfcRelDecomposes,2>::Construct )
+, SchemaEntry("ifcrelaggregates",&STEP::ObjectHelper<IfcRelAggregates,0>::Construct )
+, SchemaEntry("ifcrelassigns",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstocontrol",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstasks",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstoactor",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstogroup",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstoprocess",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstoproduct",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstoprojectorder",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassignstoresource",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociates",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesappliedvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesapproval",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesclassification",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesconstraint",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesdocument",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociateslibrary",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesmaterial",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelassociatesprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnects",&STEP::ObjectHelper<IfcRelConnects,0>::Construct )
+, SchemaEntry("ifcrelconnectselements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectspathelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectsporttoelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectsports",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectsstructuralactivity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectsstructuralelement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectsstructuralmember",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectswitheccentricity",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelconnectswithrealizingelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelcontainedinspatialstructure",&STEP::ObjectHelper<IfcRelContainedInSpatialStructure,2>::Construct )
+, SchemaEntry("ifcrelcoversbldgelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelcoversspaces",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreldefines",&STEP::ObjectHelper<IfcRelDefines,1>::Construct )
+, SchemaEntry("ifcreldefinesbyproperties",&STEP::ObjectHelper<IfcRelDefinesByProperties,1>::Construct )
+, SchemaEntry("ifcreldefinesbytype",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelfillselement",&STEP::ObjectHelper<IfcRelFillsElement,2>::Construct )
+, SchemaEntry("ifcrelflowcontrolelements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelinteractionrequirements",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelnests",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreloccupiesspaces",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcreloverridesproperties",&STEP::ObjectHelper<IfcRelOverridesProperties,1>::Construct )
+, SchemaEntry("ifcrelprojectselement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelreferencedinspatialstructure",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelschedulescostitems",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelsequence",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelservicesbuildings",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelspaceboundary",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrelvoidselement",&STEP::ObjectHelper<IfcRelVoidsElement,2>::Construct )
+, SchemaEntry("ifcrelaxation",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrepresentation",&STEP::ObjectHelper<IfcRepresentation,4>::Construct )
+, SchemaEntry("ifcrepresentationmap",&STEP::ObjectHelper<IfcRepresentationMap,2>::Construct )
+, SchemaEntry("ifcrevolvedareasolid",&STEP::ObjectHelper<IfcRevolvedAreaSolid,2>::Construct )
+, SchemaEntry("ifcribplateprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcrightcircularcone",&STEP::ObjectHelper<IfcRightCircularCone,2>::Construct )
+, SchemaEntry("ifcrightcircularcylinder",&STEP::ObjectHelper<IfcRightCircularCylinder,2>::Construct )
+, SchemaEntry("ifcroof",&STEP::ObjectHelper<IfcRoof,1>::Construct )
+, SchemaEntry("ifcroundededgefeature",&STEP::ObjectHelper<IfcRoundedEdgeFeature,1>::Construct )
+, SchemaEntry("ifcroundedrectangleprofiledef",&STEP::ObjectHelper<IfcRoundedRectangleProfileDef,1>::Construct )
+, SchemaEntry("ifcsiunit",&STEP::ObjectHelper<IfcSIUnit,2>::Construct )
+, SchemaEntry("ifcsanitaryterminaltype",&STEP::ObjectHelper<IfcSanitaryTerminalType,1>::Construct )
+, SchemaEntry("ifcscheduletimecontrol",&STEP::ObjectHelper<IfcScheduleTimeControl,18>::Construct )
+, SchemaEntry("ifcsectionproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsectionreinforcementproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsectionedspine",&STEP::ObjectHelper<IfcSectionedSpine,3>::Construct )
+, SchemaEntry("ifcsensortype",&STEP::ObjectHelper<IfcSensorType,1>::Construct )
+, SchemaEntry("ifcservicelife",&STEP::ObjectHelper<IfcServiceLife,2>::Construct )
+, SchemaEntry("ifcservicelifefactor",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcshapeaspect",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcshapemodel",&STEP::ObjectHelper<IfcShapeModel,0>::Construct )
+, SchemaEntry("ifcshaperepresentation",&STEP::ObjectHelper<IfcShapeRepresentation,0>::Construct )
+, SchemaEntry("ifcshellbasedsurfacemodel",&STEP::ObjectHelper<IfcShellBasedSurfaceModel,1>::Construct )
+, SchemaEntry("ifcsite",&STEP::ObjectHelper<IfcSite,5>::Construct )
+, SchemaEntry("ifcslab",&STEP::ObjectHelper<IfcSlab,1>::Construct )
+, SchemaEntry("ifcslabtype",&STEP::ObjectHelper<IfcSlabType,1>::Construct )
+, SchemaEntry("ifcslippageconnectioncondition",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsoundproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsoundvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcspace",&STEP::ObjectHelper<IfcSpace,2>::Construct )
+, SchemaEntry("ifcspaceheatertype",&STEP::ObjectHelper<IfcSpaceHeaterType,1>::Construct )
+, SchemaEntry("ifcspaceprogram",&STEP::ObjectHelper<IfcSpaceProgram,5>::Construct )
+, SchemaEntry("ifcspacethermalloadproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcspatialstructureelementtype",&STEP::ObjectHelper<IfcSpatialStructureElementType,0>::Construct )
+, SchemaEntry("ifcspacetype",&STEP::ObjectHelper<IfcSpaceType,1>::Construct )
+, SchemaEntry("ifcsphere",&STEP::ObjectHelper<IfcSphere,1>::Construct )
+, SchemaEntry("ifcstackterminaltype",&STEP::ObjectHelper<IfcStackTerminalType,1>::Construct )
+, SchemaEntry("ifcstair",&STEP::ObjectHelper<IfcStair,1>::Construct )
+, SchemaEntry("ifcstairflight",&STEP::ObjectHelper<IfcStairFlight,4>::Construct )
+, SchemaEntry("ifcstairflighttype",&STEP::ObjectHelper<IfcStairFlightType,1>::Construct )
+, SchemaEntry("ifcstructuralactivity",&STEP::ObjectHelper<IfcStructuralActivity,2>::Construct )
+, SchemaEntry("ifcstructuralaction",&STEP::ObjectHelper<IfcStructuralAction,2>::Construct )
+, SchemaEntry("ifcstructuralanalysismodel",&STEP::ObjectHelper<IfcStructuralAnalysisModel,4>::Construct )
+, SchemaEntry("ifcstructuralitem",&STEP::ObjectHelper<IfcStructuralItem,0>::Construct )
+, SchemaEntry("ifcstructuralconnection",&STEP::ObjectHelper<IfcStructuralConnection,1>::Construct )
+, SchemaEntry("ifcstructuralcurveconnection",&STEP::ObjectHelper<IfcStructuralCurveConnection,0>::Construct )
+, SchemaEntry("ifcstructuralmember",&STEP::ObjectHelper<IfcStructuralMember,0>::Construct )
+, SchemaEntry("ifcstructuralcurvemember",&STEP::ObjectHelper<IfcStructuralCurveMember,1>::Construct )
+, SchemaEntry("ifcstructuralcurvemembervarying",&STEP::ObjectHelper<IfcStructuralCurveMemberVarying,0>::Construct )
+, SchemaEntry("ifcstructurallinearaction",&STEP::ObjectHelper<IfcStructuralLinearAction,1>::Construct )
+, SchemaEntry("ifcstructurallinearactionvarying",&STEP::ObjectHelper<IfcStructuralLinearActionVarying,2>::Construct )
+, SchemaEntry("ifcstructuralload",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadgroup",&STEP::ObjectHelper<IfcStructuralLoadGroup,5>::Construct )
+, SchemaEntry("ifcstructuralloadstatic",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadlinearforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadplanarforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadsingledisplacement",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadsingledisplacementdistortion",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadsingleforce",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadsingleforcewarping",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralloadtemperature",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralplanaraction",&STEP::ObjectHelper<IfcStructuralPlanarAction,1>::Construct )
+, SchemaEntry("ifcstructuralplanaractionvarying",&STEP::ObjectHelper<IfcStructuralPlanarActionVarying,2>::Construct )
+, SchemaEntry("ifcstructuralpointaction",&STEP::ObjectHelper<IfcStructuralPointAction,0>::Construct )
+, SchemaEntry("ifcstructuralpointconnection",&STEP::ObjectHelper<IfcStructuralPointConnection,0>::Construct )
+, SchemaEntry("ifcstructuralreaction",&STEP::ObjectHelper<IfcStructuralReaction,0>::Construct )
+, SchemaEntry("ifcstructuralpointreaction",&STEP::ObjectHelper<IfcStructuralPointReaction,0>::Construct )
+, SchemaEntry("ifcstructuralprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralresultgroup",&STEP::ObjectHelper<IfcStructuralResultGroup,3>::Construct )
+, SchemaEntry("ifcstructuralsteelprofileproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcstructuralsurfaceconnection",&STEP::ObjectHelper<IfcStructuralSurfaceConnection,0>::Construct )
+, SchemaEntry("ifcstructuralsurfacemember",&STEP::ObjectHelper<IfcStructuralSurfaceMember,2>::Construct )
+, SchemaEntry("ifcstructuralsurfacemembervarying",&STEP::ObjectHelper<IfcStructuralSurfaceMemberVarying,2>::Construct )
+, SchemaEntry("ifcstructureddimensioncallout",&STEP::ObjectHelper<IfcStructuredDimensionCallout,0>::Construct )
+, SchemaEntry("ifcstylemodel",&STEP::ObjectHelper<IfcStyleModel,0>::Construct )
+, SchemaEntry("ifcstyledrepresentation",&STEP::ObjectHelper<IfcStyledRepresentation,0>::Construct )
+, SchemaEntry("ifcsubcontractresource",&STEP::ObjectHelper<IfcSubContractResource,2>::Construct )
+, SchemaEntry("ifcsubedge",&STEP::ObjectHelper<IfcSubedge,1>::Construct )
+, SchemaEntry("ifcsurfacecurvesweptareasolid",&STEP::ObjectHelper<IfcSurfaceCurveSweptAreaSolid,4>::Construct )
+, SchemaEntry("ifcsweptsurface",&STEP::ObjectHelper<IfcSweptSurface,2>::Construct )
+, SchemaEntry("ifcsurfaceoflinearextrusion",&STEP::ObjectHelper<IfcSurfaceOfLinearExtrusion,2>::Construct )
+, SchemaEntry("ifcsurfaceofrevolution",&STEP::ObjectHelper<IfcSurfaceOfRevolution,1>::Construct )
+, SchemaEntry("ifcsurfacestyle",&STEP::ObjectHelper<IfcSurfaceStyle,2>::Construct )
+, SchemaEntry("ifcsurfacestylelighting",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsurfacestylerefraction",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsurfacestyleshading",&STEP::ObjectHelper<IfcSurfaceStyleShading,1>::Construct )
+, SchemaEntry("ifcsurfacestylerendering",&STEP::ObjectHelper<IfcSurfaceStyleRendering,8>::Construct )
+, SchemaEntry("ifcsurfacestylewithtextures",&STEP::ObjectHelper<IfcSurfaceStyleWithTextures,1>::Construct )
+, SchemaEntry("ifcsweptdisksolid",&STEP::ObjectHelper<IfcSweptDiskSolid,5>::Construct )
+, SchemaEntry("ifcswitchingdevicetype",&STEP::ObjectHelper<IfcSwitchingDeviceType,1>::Construct )
+, SchemaEntry("ifcsymbolstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcsystemfurnitureelementtype",&STEP::ObjectHelper<IfcSystemFurnitureElementType,0>::Construct )
+, SchemaEntry("ifctshapeprofiledef",&STEP::ObjectHelper<IfcTShapeProfileDef,10>::Construct )
+, SchemaEntry("ifctable",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctablerow",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctanktype",&STEP::ObjectHelper<IfcTankType,1>::Construct )
+, SchemaEntry("ifctelecomaddress",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctendon",&STEP::ObjectHelper<IfcTendon,8>::Construct )
+, SchemaEntry("ifctendonanchor",&STEP::ObjectHelper<IfcTendonAnchor,0>::Construct )
+, SchemaEntry("ifctextliteral",&STEP::ObjectHelper<IfcTextLiteral,3>::Construct )
+, SchemaEntry("ifctextliteralwithextent",&STEP::ObjectHelper<IfcTextLiteralWithExtent,2>::Construct )
+, SchemaEntry("ifctextstyle",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctextstylefontmodel",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctextstylefordefinedfont",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctextstyletextmodel",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctextstylewithboxcharacteristics",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctexturecoordinate",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctexturecoordinategenerator",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctexturemap",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctexturevertex",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcthermalmaterialproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctimeseriesreferencerelationship",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctimeseriesschedule",&STEP::ObjectHelper<IfcTimeSeriesSchedule,3>::Construct )
+, SchemaEntry("ifctimeseriesvalue",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifctopologyrepresentation",&STEP::ObjectHelper<IfcTopologyRepresentation,0>::Construct )
+, SchemaEntry("ifctransformertype",&STEP::ObjectHelper<IfcTransformerType,1>::Construct )
+, SchemaEntry("ifctransportelement",&STEP::ObjectHelper<IfcTransportElement,3>::Construct )
+, SchemaEntry("ifctransportelementtype",&STEP::ObjectHelper<IfcTransportElementType,1>::Construct )
+, SchemaEntry("ifctrapeziumprofiledef",&STEP::ObjectHelper<IfcTrapeziumProfileDef,4>::Construct )
+, SchemaEntry("ifctrimmedcurve",&STEP::ObjectHelper<IfcTrimmedCurve,5>::Construct )
+, SchemaEntry("ifctubebundletype",&STEP::ObjectHelper<IfcTubeBundleType,1>::Construct )
+, SchemaEntry("ifctwodirectionrepeatfactor",&STEP::ObjectHelper<IfcTwoDirectionRepeatFactor,1>::Construct )
+, SchemaEntry("ifcushapeprofiledef",&STEP::ObjectHelper<IfcUShapeProfileDef,8>::Construct )
+, SchemaEntry("ifcunitassignment",&STEP::ObjectHelper<IfcUnitAssignment,1>::Construct )
+, SchemaEntry("ifcunitaryequipmenttype",&STEP::ObjectHelper<IfcUnitaryEquipmentType,1>::Construct )
+, SchemaEntry("ifcvalvetype",&STEP::ObjectHelper<IfcValveType,1>::Construct )
+, SchemaEntry("ifcvector",&STEP::ObjectHelper<IfcVector,2>::Construct )
+, SchemaEntry("ifcvertex",&STEP::ObjectHelper<IfcVertex,0>::Construct )
+, SchemaEntry("ifcvertexbasedtexturemap",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcvertexloop",&STEP::ObjectHelper<IfcVertexLoop,1>::Construct )
+, SchemaEntry("ifcvertexpoint",&STEP::ObjectHelper<IfcVertexPoint,1>::Construct )
+, SchemaEntry("ifcvibrationisolatortype",&STEP::ObjectHelper<IfcVibrationIsolatorType,1>::Construct )
+, SchemaEntry("ifcvirtualelement",&STEP::ObjectHelper<IfcVirtualElement,0>::Construct )
+, SchemaEntry("ifcvirtualgridintersection",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcwall",&STEP::ObjectHelper<IfcWall,0>::Construct )
+, SchemaEntry("ifcwallstandardcase",&STEP::ObjectHelper<IfcWallStandardCase,0>::Construct )
+, SchemaEntry("ifcwalltype",&STEP::ObjectHelper<IfcWallType,1>::Construct )
+, SchemaEntry("ifcwasteterminaltype",&STEP::ObjectHelper<IfcWasteTerminalType,1>::Construct )
+, SchemaEntry("ifcwaterproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcwindow",&STEP::ObjectHelper<IfcWindow,2>::Construct )
+, SchemaEntry("ifcwindowliningproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcwindowpanelproperties",&STEP::ObjectHelper<NotImplemented,0>::Construct )
+, SchemaEntry("ifcwindowstyle",&STEP::ObjectHelper<IfcWindowStyle,4>::Construct )
+, SchemaEntry("ifcworkcontrol",&STEP::ObjectHelper<IfcWorkControl,10>::Construct )
+, SchemaEntry("ifcworkplan",&STEP::ObjectHelper<IfcWorkPlan,0>::Construct )
+, SchemaEntry("ifcworkschedule",&STEP::ObjectHelper<IfcWorkSchedule,0>::Construct )
+, SchemaEntry("ifczshapeprofiledef",&STEP::ObjectHelper<IfcZShapeProfileDef,6>::Construct )
+, SchemaEntry("ifczone",&STEP::ObjectHelper<IfcZone,0>::Construct )
- };
+ };
}
// -----------------------------------------------------------------------------------------------------------
void IFC::GetSchema(EXPRESS::ConversionSchema& out)
{
- out = EXPRESS::ConversionSchema(schema_raw);
+ out = EXPRESS::ConversionSchema(schema_raw);
}
namespace STEP {
@@ -1047,2118 +1047,2236 @@ namespace STEP {
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
{
- return 0;
+ return 0;
}
// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
+{
+ size_t base = 0;
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcGeometricRepresentationItem>(const DB& db, const LIST& params, IfcGeometricRepresentationItem* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcCurve>(const DB& db, const LIST& params, IfcCurve* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcBoundedCurve>(const DB& db, const LIST& params, IfcBoundedCurve* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcCompositeCurve>(const DB& db, const LIST& params, IfcCompositeCurve* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCompositeCurve"); } do { // convert the 'Segments' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCompositeCurve,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Segments, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCompositeCurve to be a `LIST [1:?] OF IfcCompositeCurveSegment`")); }
+ } while(0);
+ do { // convert the 'SelfIntersect' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCompositeCurve,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->SelfIntersect, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCompositeCurve to be a `LOGICAL`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<Ifc2DCompositeCurve>(const DB& db, const LIST& params, Ifc2DCompositeCurve* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcCompositeCurve*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcRoot>(const DB& db, const LIST& params, IfcRoot* in)
{
- size_t base = 0;
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRoot"); } do { // convert the 'GlobalId' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ size_t base = 0;
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRoot"); } do { // convert the 'GlobalId' argument
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRoot,4>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->GlobalId, arg, db ); break; }
+ try { GenericConvert( in->GlobalId, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRoot to be a `IfcGloballyUniqueId`")); }
} while(0);
do { // convert the 'OwnerHistory' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRoot,4>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->OwnerHistory, arg, db ); break; }
+ try { GenericConvert( in->OwnerHistory, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRoot to be a `IfcOwnerHistory`")); }
} while(0);
do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRoot,4>::aux_is_derived[2]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Name, arg, db ); break; }
+ try { GenericConvert( in->Name, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRoot to be a `IfcLabel`")); }
} while(0);
do { // convert the 'Description' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRoot,4>::aux_is_derived[3]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Description, arg, db ); break; }
+ try { GenericConvert( in->Description, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRoot to be a `IfcText`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcObjectDefinition>(const DB& db, const LIST& params, IfcObjectDefinition* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcObjectDefinition"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcObjectDefinition"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTypeObject>(const DB& db, const LIST& params, IfcTypeObject* in)
+template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcObject* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObjectDefinition*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcObjectDefinition*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcObject"); } do { // convert the 'ObjectType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcObject,1>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->ObjectType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcObject to be a `IfcLabel`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTypeProduct>(const DB& db, const LIST& params, IfcTypeProduct* in)
+template <> size_t GenericFill<IfcControl>(const DB& db, const LIST& params, IfcControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeObject*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementType>(const DB& db, const LIST& params, IfcElementType* in)
+template <> size_t GenericFill<IfcActionRequest>(const DB& db, const LIST& params, IfcActionRequest* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionElementType>(const DB& db, const LIST& params, IfcDistributionElementType* in)
+template <> size_t GenericFill<IfcActor>(const DB& db, const LIST& params, IfcActor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionFlowElementType>(const DB& db, const LIST& params, IfcDistributionFlowElementType* in)
+template <> size_t GenericFill<IfcTypeObject>(const DB& db, const LIST& params, IfcTypeObject* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObjectDefinition*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowControllerType>(const DB& db, const LIST& params, IfcFlowControllerType* in)
+template <> size_t GenericFill<IfcTypeProduct>(const DB& db, const LIST& params, IfcTypeProduct* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTypeObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* in)
+template <> size_t GenericFill<IfcElementType>(const DB& db, const LIST& params, IfcElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentation>(const DB& db, const LIST& params, IfcRepresentation* in)
-{
- size_t base = 0;
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRepresentation"); } do { // convert the 'ContextOfItems' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->ContextOfItems, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentation to be a `IfcRepresentationContext`")); }
- } while(0);
- do { // convert the 'RepresentationIdentifier' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[1]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RepresentationIdentifier, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentation to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'RepresentationType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[2]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RepresentationType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRepresentation to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'Items' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[3]=true; break; }
- try { GenericConvert( in->Items, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRepresentation to be a `SET [1:?] OF IfcRepresentationItem`")); }
- } while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcShapeModel>(const DB& db, const LIST& params, IfcShapeModel* in)
+template <> size_t GenericFill<IfcDistributionElementType>(const DB& db, const LIST& params, IfcDistributionElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* in)
+template <> size_t GenericFill<IfcDistributionControlElementType>(const DB& db, const LIST& params, IfcDistributionControlElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcShapeModel*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* in)
+template <> size_t GenericFill<IfcActuatorType>(const DB& db, const LIST& params, IfcActuatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRelationship"); } return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelConnects>(const DB& db, const LIST& params, IfcRelConnects* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRelConnects"); } return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowFittingType>(const DB& db, const LIST& params, IfcFlowFittingType* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* in)
+template <> size_t GenericFill<IfcDistributionFlowElementType>(const DB& db, const LIST& params, IfcDistributionFlowElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, IfcEnergyConversionDeviceType* in)
+template <> size_t GenericFill<IfcFlowControllerType>(const DB& db, const LIST& params, IfcFlowControllerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* in)
+template <> size_t GenericFill<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcObject* in)
+template <> size_t GenericFill<IfcFlowTerminalType>(const DB& db, const LIST& params, IfcFlowTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObjectDefinition*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcObject"); } do { // convert the 'ObjectType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcObject,1>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ObjectType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcObject to be a `IfcLabel`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcControl>(const DB& db, const LIST& params, IfcControl* in)
+template <> size_t GenericFill<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* in)
+template <> size_t GenericFill<IfcEnergyConversionDeviceType>(const DB& db, const LIST& params, IfcEnergyConversionDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
+template <> size_t GenericFill<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* in)
{
- size_t base = 0;
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGeometricRepresentationItem>(const DB& db, const LIST& params, IfcGeometricRepresentationItem* in)
+template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* in)
+template <> size_t GenericFill<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTextLiteralWithExtent>(const DB& db, const LIST& params, IfcTextLiteralWithExtent* in)
+template <> size_t GenericFill<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTextLiteral*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* in)
+template <> size_t GenericFill<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* in)
{
- size_t base = 0;
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcProductRepresentation"); } do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProductRepresentation to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'Description' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[1]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Description, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProductRepresentation to be a `IfcText`")); }
- } while(0);
- do { // convert the 'Representations' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->Representations, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcProductRepresentation to be a `LIST [1:?] OF IfcRepresentation`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcProduct>(const DB& db, const LIST& params, IfcProduct* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
- if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcProduct"); } do { // convert the 'ObjectPlacement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
+ if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcProduct"); } do { // convert the 'ObjectPlacement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProduct,2>::aux_is_derived[0]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ObjectPlacement, arg, db ); break; }
+ try { GenericConvert( in->ObjectPlacement, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcProduct to be a `IfcObjectPlacement`")); }
} while(0);
do { // convert the 'Representation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProduct,2>::aux_is_derived[1]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Representation, arg, db ); break; }
+ try { GenericConvert( in->Representation, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProduct to be a `IfcProductRepresentation`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* in)
+template <> size_t GenericFill<IfcAnnotation>(const DB& db, const LIST& params, IfcAnnotation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcElement"); } do { // convert the 'Tag' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcElement,1>::aux_is_derived[0]=true; break; }
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcAnnotation"); } return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcStyledItem>(const DB& db, const LIST& params, IfcStyledItem* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcStyledItem"); } do { // convert the 'Item' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[0]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Tag, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcElement to be a `IfcIdentifier`")); }
+ try { GenericConvert( in->Item, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcStyledItem to be a `IfcRepresentationItem`")); }
+ } while(0);
+ do { // convert the 'Styles' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->Styles, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcStyledItem to be a `SET [1:?] OF IfcPresentationStyleAssignment`")); }
} while(0);
- return base;
+ do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[2]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcStyledItem to be a `IfcLabel`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* in)
+template <> size_t GenericFill<IfcAnnotationOccurrence>(const DB& db, const LIST& params, IfcAnnotationOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStyledItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* in)
+template <> size_t GenericFill<IfcAnnotationCurveOccurrence>(const DB& db, const LIST& params, IfcAnnotationCurveOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCurve>(const DB& db, const LIST& params, IfcCurve* in)
+template <> size_t GenericFill<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoundedCurve>(const DB& db, const LIST& params, IfcBoundedCurve* in)
+template <> size_t GenericFill<IfcAnnotationFillAreaOccurrence>(const DB& db, const LIST& params, IfcAnnotationFillAreaOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCompositeCurve>(const DB& db, const LIST& params, IfcCompositeCurve* in)
+template <> size_t GenericFill<IfcAnnotationSurface>(const DB& db, const LIST& params, IfcAnnotationSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCompositeCurve"); } do { // convert the 'Segments' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCompositeCurve,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Segments, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCompositeCurve to be a `LIST [1:?] OF IfcCompositeCurveSegment`")); }
- } while(0);
- do { // convert the 'SelfIntersect' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCompositeCurve,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->SelfIntersect, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCompositeCurve to be a `LOGICAL`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<Ifc2DCompositeCurve>(const DB& db, const LIST& params, Ifc2DCompositeCurve* in)
+template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCompositeCurve*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* in)
+template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCartesianTransformationOperator"); } do { // convert the 'Axis1' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Axis1, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
- } while(0);
- do { // convert the 'Axis2' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[1]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Axis2, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
- } while(0);
- do { // convert the 'LocalOrigin' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->LocalOrigin, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCartesianTransformationOperator to be a `IfcCartesianPoint`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcAnnotationTextOccurrence>(const DB& db, const LIST& params, IfcAnnotationTextOccurrence* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcProfileDef>(const DB& db, const LIST& params, IfcProfileDef* in)
+{
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProfileDef"); } do { // convert the 'ProfileType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProfileDef,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->ProfileType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProfileDef to be a `IfcProfileTypeEnum`")); }
} while(0);
- do { // convert the 'Scale' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[3]=true; break; }
+ do { // convert the 'ProfileName' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProfileDef,2>::aux_is_derived[1]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Scale, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCartesianTransformationOperator to be a `REAL`")); }
+ try { GenericConvert( in->ProfileName, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProfileDef to be a `IfcLabel`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianTransformationOperator3D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3D* in)
+template <> size_t GenericFill<IfcArbitraryClosedProfileDef>(const DB& db, const LIST& params, IfcArbitraryClosedProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCartesianTransformationOperator3D"); } do { // convert the 'Axis3' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator3D,1>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Axis3, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCartesianTransformationOperator3D to be a `IfcDirection`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryClosedProfileDef"); } do { // convert the 'OuterCurve' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcArbitraryClosedProfileDef,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->OuterCurve, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryClosedProfileDef to be a `IfcCurve`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, IfcProperty* in)
+template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProperty"); } do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProperty,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProperty to be a `IfcIdentifier`")); }
- } while(0);
- do { // convert the 'Description' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProperty,2>::aux_is_derived[1]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Description, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProperty to be a `IfcText`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryOpenProfileDef"); } do { // convert the 'Curve' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcArbitraryOpenProfileDef,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Curve, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryOpenProfileDef to be a `IfcBoundedCurve`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* in)
+template <> size_t GenericFill<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProperty*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSimpleProperty"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcArbitraryClosedProfileDef*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcArbitraryProfileDefWithVoids"); } do { // convert the 'InnerCurves' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->InnerCurves, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcArbitraryProfileDefWithVoids to be a `SET [1:?] OF IfcCurve`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* in)
+template <> size_t GenericFill<IfcGroup>(const DB& db, const LIST& params, IfcGroup* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementType>(const DB& db, const LIST& params, IfcBuildingElementType* in)
+template <> size_t GenericFill<IfcAsset>(const DB& db, const LIST& params, IfcAsset* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcParameterizedProfileDef>(const DB& db, const LIST& params, IfcParameterizedProfileDef* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcParameterizedProfileDef"); } do { // convert the 'Position' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcParameterizedProfileDef,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Position, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcParameterizedProfileDef to be a `IfcAxis2Placement2D`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcIShapeProfileDef>(const DB& db, const LIST& params, IfcIShapeProfileDef* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcIShapeProfileDef"); } do { // convert the 'OverallWidth' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->OverallWidth, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'OverallDepth' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->OverallDepth, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'WebThickness' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->WebThickness, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'FlangeThickness' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[3]=true; break; }
+ try { GenericConvert( in->FlangeThickness, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'FilletRadius' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[4]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->FilletRadius, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* in)
+template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcIShapeProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurface>(const DB& db, const LIST& params, IfcSurface* in)
+template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, IfcPlacement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPlacement"); } do { // convert the 'Location' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcPlacement,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Location, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPlacement to be a `IfcCartesianPoint`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* in)
+template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcElementarySurface"); } do { // convert the 'Position' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcElementarySurface,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Position, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcElementarySurface to be a `IfcAxis2Placement3D`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis1Placement"); } do { // convert the 'Axis' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Axis, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis1Placement to be a `IfcDirection`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* in)
+template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& params, IfcAxis2Placement2D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementarySurface*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPlane"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis2Placement2D"); } do { // convert the 'RefDirection' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RefDirection, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement2D to be a `IfcDirection`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBooleanResult>(const DB& db, const LIST& params, IfcBooleanResult* in)
+template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& params, IfcAxis2Placement3D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcBooleanResult"); } do { // convert the 'Operator' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Operator, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBooleanResult to be a `IfcBooleanOperator`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcAxis2Placement3D"); } do { // convert the 'Axis' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Axis, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement3D to be a `IfcDirection`")); }
} while(0);
- do { // convert the 'FirstOperand' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->FirstOperand, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
+ do { // convert the 'RefDirection' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RefDirection, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcAxis2Placement3D to be a `IfcDirection`")); }
} while(0);
- do { // convert the 'SecondOperand' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->SecondOperand, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcBSplineCurve>(const DB& db, const LIST& params, IfcBSplineCurve* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcBSplineCurve"); } do { // convert the 'Degree' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Degree, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBSplineCurve to be a `INTEGER`")); }
+ } while(0);
+ do { // convert the 'ControlPointsList' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->ControlPointsList, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBSplineCurve to be a `LIST [2:?] OF IfcCartesianPoint`")); }
+ } while(0);
+ do { // convert the 'CurveForm' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->CurveForm, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBSplineCurve to be a `IfcBSplineCurveForm`")); }
+ } while(0);
+ do { // convert the 'ClosedCurve' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[3]=true; break; }
+ try { GenericConvert( in->ClosedCurve, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBSplineCurve to be a `LOGICAL`")); }
} while(0);
- return base;
+ do { // convert the 'SelfIntersect' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[4]=true; break; }
+ try { GenericConvert( in->SelfIntersect, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcBSplineCurve to be a `LOGICAL`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBooleanClippingResult>(const DB& db, const LIST& params, IfcBooleanClippingResult* in)
+template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, IfcElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBooleanResult*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcBooleanClippingResult"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcElement"); } do { // convert the 'Tag' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcElement,1>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Tag, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcElement to be a `IfcIdentifier`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSolidModel>(const DB& db, const LIST& params, IfcSolidModel* in)
+template <> size_t GenericFill<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcBuildingElement"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcManifoldSolidBrep>(const DB& db, const LIST& params, IfcManifoldSolidBrep* in)
+template <> size_t GenericFill<IfcBeam>(const DB& db, const LIST& params, IfcBeam* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcManifoldSolidBrep"); } do { // convert the 'Outer' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcManifoldSolidBrep,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Outer, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcManifoldSolidBrep to be a `IfcClosedShell`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowTerminalType>(const DB& db, const LIST& params, IfcFlowTerminalType* in)
+template <> size_t GenericFill<IfcBuildingElementType>(const DB& db, const LIST& params, IfcBuildingElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* in)
+template <> size_t GenericFill<IfcBeamType>(const DB& db, const LIST& params, IfcBeamType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* in)
+template <> size_t GenericFill<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBSplineCurve*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* in)
+template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* in)
+template <> size_t GenericFill<IfcBlock>(const DB& db, const LIST& params, IfcBlock* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* in)
+template <> size_t GenericFill<IfcBoilerType>(const DB& db, const LIST& params, IfcBoilerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyDefinition>(const DB& db, const LIST& params, IfcPropertyDefinition* in)
+template <> size_t GenericFill<IfcBooleanResult>(const DB& db, const LIST& params, IfcBooleanResult* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertyDefinition"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcBooleanResult"); } do { // convert the 'Operator' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Operator, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBooleanResult to be a `IfcBooleanOperator`")); }
+ } while(0);
+ do { // convert the 'FirstOperand' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->FirstOperand, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
+ } while(0);
+ do { // convert the 'SecondOperand' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBooleanResult,3>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->SecondOperand, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertySetDefinition>(const DB& db, const LIST& params, IfcPropertySetDefinition* in)
+template <> size_t GenericFill<IfcBooleanClippingResult>(const DB& db, const LIST& params, IfcBooleanClippingResult* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPropertyDefinition*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertySetDefinition"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBooleanResult*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcBooleanClippingResult"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProcess>(const DB& db, const LIST& params, IfcProcess* in)
+template <> size_t GenericFill<IfcSurface>(const DB& db, const LIST& params, IfcSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTask>(const DB& db, const LIST& params, IfcTask* in)
+template <> size_t GenericFill<IfcBoundedSurface>(const DB& db, const LIST& params, IfcBoundedSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProcess*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelFillsElement>(const DB& db, const LIST& params, IfcRelFillsElement* in)
+template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelFillsElement"); } do { // convert the 'RelatingOpeningElement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatingOpeningElement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelFillsElement to be a `IfcOpeningElement`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcBoundingBox"); } do { // convert the 'Corner' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Corner, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBoundingBox to be a `IfcCartesianPoint`")); }
+ } while(0);
+ do { // convert the 'XDim' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->XDim, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
} while(0);
- do { // convert the 'RelatedBuildingElement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatedBuildingElement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelFillsElement to be a `IfcElement`")); }
+ do { // convert the 'YDim' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->YDim, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'ZDim' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ZDim, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* in)
+template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProcess*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcHalfSpaceSolid"); } do { // convert the 'BaseSurface' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcHalfSpaceSolid,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->BaseSurface, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcHalfSpaceSolid to be a `IfcSurface`")); }
+ } while(0);
+ do { // convert the 'AgreementFlag' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcHalfSpaceSolid,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->AgreementFlag, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcHalfSpaceSolid to be a `BOOLEAN`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProxy>(const DB& db, const LIST& params, IfcProxy* in)
+template <> size_t GenericFill<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcResource>(const DB& db, const LIST& params, IfcResource* in)
+template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcSpatialStructureElement"); } do { // convert the 'LongName' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSpatialStructureElement,2>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->LongName, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSpatialStructureElement to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'CompositionType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSpatialStructureElement,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->CompositionType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSpatialStructureElement to be a `IfcElementCompositionEnum`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* in)
+template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcResource*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
+ if (params.GetSize() < 12) { throw STEP::TypeError("expected 12 arguments to IfcBuilding"); } do { // convert the 'ElevationOfRefHeight' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->ElevationOfRefHeight, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcBuilding to be a `IfcLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'ElevationOfTerrain' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->ElevationOfTerrain, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcBuilding to be a `IfcLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'BuildingAddress' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->BuildingAddress, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcBuilding to be a `IfcPostalAddress`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* in)
+template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* in)
+template <> size_t GenericFill<IfcBuildingElementPart>(const DB& db, const LIST& params, IfcBuildingElementPart* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelContainedInSpatialStructure"); } do { // convert the 'RelatedElements' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatedElements, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelContainedInSpatialStructure to be a `SET [1:?] OF IfcProduct`")); }
- } while(0);
- do { // convert the 'RelatingStructure' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatingStructure, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelContainedInSpatialStructure to be a `IfcSpatialStructureElement`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* in)
+template <> size_t GenericFill<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEdge>(const DB& db, const LIST& params, IfcEdge* in)
+template <> size_t GenericFill<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* in)
+template <> size_t GenericFill<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* in)
+template <> size_t GenericFill<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
+template <> size_t GenericFill<IfcFlowFittingType>(const DB& db, const LIST& params, IfcFlowFittingType* in)
{
- size_t base = 0;
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGridPlacement>(const DB& db, const LIST& params, IfcGridPlacement* in)
+template <> size_t GenericFill<IfcCableCarrierFittingType>(const DB& db, const LIST& params, IfcCableCarrierFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObjectPlacement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* in)
+template <> size_t GenericFill<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* in)
+template <> size_t GenericFill<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* in)
+template <> size_t GenericFill<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* in)
+template <> size_t GenericFill<IfcPoint>(const DB& db, const LIST& params, IfcPoint* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* in)
+template <> size_t GenericFill<IfcCartesianPoint>(const DB& db, const LIST& params, IfcCartesianPoint* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcCartesianPoint"); } do { // convert the 'Coordinates' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Coordinates, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianPoint to be a `LIST [1:3] OF IfcLengthMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, IfcDirection* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator>(const DB& db, const LIST& params, IfcCartesianTransformationOperator* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcDirection"); } do { // convert the 'DirectionRatios' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->DirectionRatios, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcDirection to be a `LIST [2:3] OF REAL`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCartesianTransformationOperator"); } do { // convert the 'Axis1' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Axis1, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
+ } while(0);
+ do { // convert the 'Axis2' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[1]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Axis2, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
+ } while(0);
+ do { // convert the 'LocalOrigin' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->LocalOrigin, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCartesianTransformationOperator to be a `IfcCartesianPoint`")); }
} while(0);
- return base;
+ do { // convert the 'Scale' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator,4>::aux_is_derived[3]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Scale, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCartesianTransformationOperator to be a `REAL`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProfileDef>(const DB& db, const LIST& params, IfcProfileDef* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProfileDef"); } do { // convert the 'ProfileType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProfileDef,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->ProfileType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProfileDef to be a `IfcProfileTypeEnum`")); }
- } while(0);
- do { // convert the 'ProfileName' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProfileDef,2>::aux_is_derived[1]=true; break; }
+ size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcCartesianTransformationOperator2DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2DnonUniform* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator2D*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcCartesianTransformationOperator3D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3D* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCartesianTransformationOperator3D"); } do { // convert the 'Axis3' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCartesianTransformationOperator3D,1>::aux_is_derived[0]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ProfileName, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProfileDef to be a `IfcLabel`")); }
+ try { GenericConvert( in->Axis3, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCartesianTransformationOperator3D to be a `IfcDirection`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcParameterizedProfileDef>(const DB& db, const LIST& params, IfcParameterizedProfileDef* in)
+template <> size_t GenericFill<IfcCartesianTransformationOperator3DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3DnonUniform* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcParameterizedProfileDef"); } do { // convert the 'Position' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcParameterizedProfileDef,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Position, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcParameterizedProfileDef to be a `IfcAxis2Placement2D`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator3D*>(in));
+ if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcCartesianTransformationOperator3DnonUniform"); } do { // convert the 'Scale2' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Scale2, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
+ } while(0);
+ do { // convert the 'Scale3' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Scale3, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCShapeProfileDef>(const DB& db, const LIST& params, IfcCShapeProfileDef* in)
+template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcArbitraryOpenProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcFeatureElement>(const DB& db, const LIST& params, IfcFeatureElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcFeatureElement"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcFeatureElement"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcFeatureElementSubtraction>(const DB& db, const LIST& params, IfcFeatureElementSubtraction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElement*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcFeatureElementSubtraction"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFeatureElement*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcFeatureElementSubtraction"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcEdgeFeature>(const DB& db, const LIST& params, IfcEdgeFeature* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElementSubtraction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFeatureElementSubtraction*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcChamferEdgeFeature>(const DB& db, const LIST& params, IfcChamferEdgeFeature* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdgeFeature*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEdgeFeature*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElement>(const DB& db, const LIST& params, IfcBuildingElement* in)
+template <> size_t GenericFill<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcBuildingElement"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcColumn>(const DB& db, const LIST& params, IfcColumn* in)
+template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConic"); } do { // convert the 'Position' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcConic,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Position, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConic to be a `IfcAxis2Placement`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* in)
+template <> size_t GenericFill<IfcCircle>(const DB& db, const LIST& params, IfcCircle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCircle"); } do { // convert the 'Radius' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Radius, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCircle to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* in)
+template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCircleProfileDef"); } do { // convert the 'Radius' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCircleProfileDef,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Radius, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCircleProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* in)
+template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcCircleProfileDef*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCircleHollowProfileDef"); } do { // convert the 'WallThickness' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->WallThickness, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCircleHollowProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* in)
+template <> size_t GenericFill<IfcTopologicalRepresentationItem>(const DB& db, const LIST& params, IfcTopologicalRepresentationItem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElementType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* in)
+template <> size_t GenericFill<IfcConnectedFaceSet>(const DB& db, const LIST& params, IfcConnectedFaceSet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConnectedFaceSet"); } do { // convert the 'CfsFaces' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcConnectedFaceSet,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->CfsFaces, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConnectedFaceSet to be a `SET [1:?] OF IfcFace`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* in)
+template <> size_t GenericFill<IfcClosedShell>(const DB& db, const LIST& params, IfcClosedShell* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcConnectedFaceSet*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcClosedShell"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* in)
+template <> size_t GenericFill<IfcCoilType>(const DB& db, const LIST& params, IfcCoilType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& params, IfcCircleProfileDef* in)
+template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCircleProfileDef"); } do { // convert the 'Radius' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcCircleProfileDef,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Radius, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCircleProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcColourSpecification"); } do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcColourSpecification,1>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcColourSpecification to be a `IfcLabel`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LIST& params, IfcCircleHollowProfileDef* in)
+template <> size_t GenericFill<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCircleProfileDef*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCircleHollowProfileDef"); } do { // convert the 'WallThickness' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->WallThickness, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCircleHollowProfileDef to be a `IfcPositiveLengthMeasure`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcColourSpecification*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcColourRgb"); } do { // convert the 'Red' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Red, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
+ } while(0);
+ do { // convert the 'Green' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Green, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
} while(0);
- return base;
+ do { // convert the 'Blue' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Blue, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, IfcPlacement* in)
+template <> size_t GenericFill<IfcColumn>(const DB& db, const LIST& params, IfcColumn* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPlacement"); } do { // convert the 'Location' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcPlacement,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Location, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPlacement to be a `IfcCartesianPoint`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& params, IfcAxis2Placement3D* in)
+template <> size_t GenericFill<IfcColumnType>(const DB& db, const LIST& params, IfcColumnType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcAxis2Placement3D"); } do { // convert the 'Axis' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Axis, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement3D to be a `IfcDirection`")); }
- } while(0);
- do { // convert the 'RefDirection' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RefDirection, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcAxis2Placement3D to be a `IfcDirection`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* in)
+template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, IfcProperty* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyle"); } do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcPresentationStyle,1>::aux_is_derived[0]=true; break; }
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProperty"); } do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProperty,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProperty to be a `IfcIdentifier`")); }
+ } while(0);
+ do { // convert the 'Description' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProperty,2>::aux_is_derived[1]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyle to be a `IfcLabel`")); }
+ try { GenericConvert( in->Description, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProperty to be a `IfcText`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEquipmentElement>(const DB& db, const LIST& params, IfcEquipmentElement* in)
+template <> size_t GenericFill<IfcComplexProperty>(const DB& db, const LIST& params, IfcComplexProperty* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProperty*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcComplexProperty"); } do { // convert the 'UsageName' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->UsageName, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcComplexProperty to be a `IfcIdentifier`")); }
+ } while(0);
+ do { // convert the 'HasProperties' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->HasProperties, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcComplexProperty to be a `SET [1:?] OF IfcProperty`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcCompositeCurveSegment>(const DB& db, const LIST& params, IfcCompositeCurveSegment* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcCompositeCurveSegment"); } do { // convert the 'Transition' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Transition, arg, db ); break; }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcCompositeCurveSegment"); } do { // convert the 'Transition' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Transition, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCompositeCurveSegment to be a `IfcTransitionCode`")); }
} while(0);
do { // convert the 'SameSense' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SameSense, arg, db ); break; }
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->SameSense, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCompositeCurveSegment to be a `BOOLEAN`")); }
} while(0);
do { // convert the 'ParentCurve' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ParentCurve, arg, db ); break; }
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ParentCurve, arg, db ); break; }
catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCompositeCurveSegment to be a `IfcCurve`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* in)
+template <> size_t GenericFill<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRectangleProfileDef"); } do { // convert the 'XDim' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRectangleProfileDef,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->XDim, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'YDim' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRectangleProfileDef,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->YDim, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementProxy>(const DB& db, const LIST& params, IfcBuildingElementProxy* in)
+template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionControlElementType>(const DB& db, const LIST& params, IfcDistributionControlElementType* in)
+template <> size_t GenericFill<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* in)
+template <> size_t GenericFill<IfcCondenserType>(const DB& db, const LIST& params, IfcCondenserType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDraughtingCallout>(const DB& db, const LIST& params, IfcDraughtingCallout* in)
+template <> size_t GenericFill<IfcCondition>(const DB& db, const LIST& params, IfcCondition* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDimensionCurveDirectedCallout>(const DB& db, const LIST& params, IfcDimensionCurveDirectedCallout* in)
+template <> size_t GenericFill<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* in)
+template <> size_t GenericFill<IfcResource>(const DB& db, const LIST& params, IfcResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* in)
+template <> size_t GenericFill<IfcConstructionResource>(const DB& db, const LIST& params, IfcConstructionResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcResource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCsgPrimitive3D>(const DB& db, const LIST& params, IfcCsgPrimitive3D* in)
+template <> size_t GenericFill<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* in)
+template <> size_t GenericFill<IfcConstructionMaterialResource>(const DB& db, const LIST& params, IfcConstructionMaterialResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* in)
+template <> size_t GenericFill<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* in)
+template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, IfcNamedUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcNamedUnit"); } do { // convert the 'Dimensions' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcNamedUnit,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Dimensions, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcNamedUnit to be a `IfcDimensionalExponents`")); }
+ } while(0);
+ do { // convert the 'UnitType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcNamedUnit,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->UnitType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcNamedUnit to be a `IfcUnitEnum`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAngularDimension>(const DB& db, const LIST& params, IfcAngularDimension* in)
+template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* in)
+template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObjectPlacement*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLocalPlacement"); } do { // convert the 'PlacementRelTo' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->PlacementRelTo, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLocalPlacement to be a `IfcObjectPlacement`")); }
- } while(0);
- do { // convert the 'RelativePlacement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelativePlacement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLocalPlacement to be a `IfcAxis2Placement`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* in)
+template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSweptAreaSolid"); } do { // convert the 'SweptArea' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSweptAreaSolid,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->SweptArea, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptAreaSolid to be a `IfcProfileDef`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcConversionBasedUnit"); } do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcConversionBasedUnit to be a `IfcLabel`")); }
} while(0);
- do { // convert the 'Position' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSweptAreaSolid,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->Position, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptAreaSolid to be a `IfcAxis2Placement3D`")); }
+ do { // convert the 'ConversionFactor' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ConversionFactor, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcConversionBasedUnit to be a `IfcMeasureWithUnit`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* in)
+template <> size_t GenericFill<IfcCooledBeamType>(const DB& db, const LIST& params, IfcCooledBeamType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRevolvedAreaSolid"); } do { // convert the 'Axis' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Axis, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRevolvedAreaSolid to be a `IfcAxis1Placement`")); }
- } while(0);
- do { // convert the 'Angle' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Angle, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRevolvedAreaSolid to be a `IfcPlaneAngleMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* in)
+template <> size_t GenericFill<IfcCoolingTowerType>(const DB& db, const LIST& params, IfcCoolingTowerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* in)
+template <> size_t GenericFill<IfcCostItem>(const DB& db, const LIST& params, IfcCostItem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* in)
+template <> size_t GenericFill<IfcCostSchedule>(const DB& db, const LIST& params, IfcCostSchedule* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcSweptDiskSolid"); } do { // convert the 'Directrix' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Directrix, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptDiskSolid to be a `IfcCurve`")); }
- } while(0);
- do { // convert the 'Radius' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Radius, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'InnerRadius' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->InnerRadius, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'StartParam' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->StartParam, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
- } while(0);
- do { // convert the 'EndParam' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->EndParam, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& params, IfcHalfSpaceSolid* in)
+template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcHalfSpaceSolid"); } do { // convert the 'BaseSurface' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcHalfSpaceSolid,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->BaseSurface, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcHalfSpaceSolid to be a `IfcSurface`")); }
- } while(0);
- do { // convert the 'AgreementFlag' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcHalfSpaceSolid,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->AgreementFlag, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcHalfSpaceSolid to be a `BOOLEAN`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* in)
+template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPolygonalBoundedHalfSpace"); } do { // convert the 'Position' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Position, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPolygonalBoundedHalfSpace to be a `IfcAxis2Placement3D`")); }
- } while(0);
- do { // convert the 'PolygonalBoundary' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->PolygonalBoundary, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPolygonalBoundedHalfSpace to be a `IfcBoundedCurve`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* in)
+template <> size_t GenericFill<IfcCraneRailAShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailAShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCooledBeamType>(const DB& db, const LIST& params, IfcCooledBeamType* in)
+template <> size_t GenericFill<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, IfcProject* in)
+template <> size_t GenericFill<IfcCrewResource>(const DB& db, const LIST& params, IfcCrewResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
- if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcProject"); } do { // convert the 'LongName' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->LongName, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcProject to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'Phase' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Phase, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProject to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'RepresentationContexts' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RepresentationContexts, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcProject to be a `SET [1:?] OF IfcRepresentationContext`")); }
- } while(0);
- do { // convert the 'UnitsInContext' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->UnitsInContext, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcProject to be a `IfcUnitAssignment`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* in)
+template <> size_t GenericFill<IfcSolidModel>(const DB& db, const LIST& params, IfcSolidModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* in)
+template <> size_t GenericFill<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* in)
+template <> size_t GenericFill<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* in)
+template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMember>(const DB& db, const LIST& params, IfcMember* in)
+template <> size_t GenericFill<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* in)
+template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& params, IfcPresentationStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyle"); } do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcPresentationStyle,1>::aux_is_derived[0]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyle to be a `IfcLabel`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcValveType>(const DB& db, const LIST& params, IfcValveType* in)
+template <> size_t GenericFill<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* in)
+template <> size_t GenericFill<IfcDefinedSymbol>(const DB& db, const LIST& params, IfcDefinedSymbol* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcTrimmedCurve"); } do { // convert the 'BasisCurve' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->BasisCurve, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcTrimmedCurve to be a `IfcCurve`")); }
- } while(0);
- do { // convert the 'Trim1' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Trim1, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
- } while(0);
- do { // convert the 'Trim2' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Trim2, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
- } while(0);
- do { // convert the 'SenseAgreement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SenseAgreement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcTrimmedCurve to be a `BOOLEAN`")); }
- } while(0);
- do { // convert the 'MasterRepresentation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->MasterRepresentation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcTrimmedCurve to be a `IfcTrimmingPreference`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* in)
+template <> size_t GenericFill<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRelDefines"); } do { // convert the 'RelatedObjects' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDefines,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->RelatedObjects, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDefines to be a `SET [1:?] OF IfcObject`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* in)
+template <> size_t GenericFill<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelDefines*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDefinesByProperties"); } do { // convert the 'RelatingPropertyDefinition' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDefinesByProperties,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->RelatingPropertyDefinition, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDefinesByProperties to be a `IfcPropertySetDefinition`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcActor>(const DB& db, const LIST& params, IfcActor* in)
+template <> size_t GenericFill<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* in)
+template <> size_t GenericFill<IfcTerminatorSymbol>(const DB& db, const LIST& params, IfcTerminatorSymbol* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcActor*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationSymbolOccurrence*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* in)
+template <> size_t GenericFill<IfcDimensionCurveTerminator>(const DB& db, const LIST& params, IfcDimensionCurveTerminator* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTerminatorSymbol*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const LIST& params, IfcArbitraryOpenProfileDef* in)
+template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, IfcDirection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryOpenProfileDef"); } do { // convert the 'Curve' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcArbitraryOpenProfileDef,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Curve, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryOpenProfileDef to be a `IfcBoundedCurve`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcDirection"); } do { // convert the 'DirectionRatios' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->DirectionRatios, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcDirection to be a `LIST [2:3] OF REAL`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPermit>(const DB& db, const LIST& params, IfcPermit* in)
+template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* in)
+template <> size_t GenericFill<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementComponent*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, IfcLightSource* in)
+template <> size_t GenericFill<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* in)
+template <> size_t GenericFill<IfcDiscreteAccessoryType>(const DB& db, const LIST& params, IfcDiscreteAccessoryType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCompositeProfileDef>(const DB& db, const LIST& params, IfcCompositeProfileDef* in)
+template <> size_t GenericFill<IfcDistributionElement>(const DB& db, const LIST& params, IfcDistributionElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRamp>(const DB& db, const LIST& params, IfcRamp* in)
+template <> size_t GenericFill<IfcDistributionFlowElement>(const DB& db, const LIST& params, IfcDistributionFlowElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* in)
+template <> size_t GenericFill<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* in)
+template <> size_t GenericFill<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLampType>(const DB& db, const LIST& params, IfcLampType* in)
+template <> size_t GenericFill<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementComponent>(const DB& db, const LIST& params, IfcBuildingElementComponent* in)
+template <> size_t GenericFill<IfcPort>(const DB& db, const LIST& params, IfcPort* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* in)
+template <> size_t GenericFill<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcPort*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcDoor>(const DB& db, const LIST& params, IfcDoor* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ if (params.GetSize() < 10) { throw STEP::TypeError("expected 10 arguments to IfcDoor"); } do { // convert the 'OverallHeight' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->OverallHeight, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'OverallWidth' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->OverallWidth, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcPropertyDefinition>(const DB& db, const LIST& params, IfcPropertyDefinition* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertyDefinition"); } return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcPropertySetDefinition>(const DB& db, const LIST& params, IfcPropertySetDefinition* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcPropertyDefinition*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertySetDefinition"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* in)
+template <> size_t GenericFill<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* in)
+template <> size_t GenericFill<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* in)
+template <> size_t GenericFill<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralActivity>(const DB& db, const LIST& params, IfcStructuralActivity* in)
+template <> size_t GenericFill<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* in)
+template <> size_t GenericFill<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralActivity*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDuctFittingType>(const DB& db, const LIST& params, IfcDuctFittingType* in)
+template <> size_t GenericFill<IfcEdge>(const DB& db, const LIST& params, IfcEdge* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianTransformationOperator2D>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2D* in)
+template <> size_t GenericFill<IfcEdgeCurve>(const DB& db, const LIST& params, IfcEdgeCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianTransformationOperator2DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator2DnonUniform* in)
+template <> size_t GenericFill<IfcLoop>(const DB& db, const LIST& params, IfcLoop* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcEdgeLoop>(const DB& db, const LIST& params, IfcEdgeLoop* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator2D*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* in)
+template <> size_t GenericFill<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* in)
+template <> size_t GenericFill<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* in)
+template <> size_t GenericFill<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowController*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* in)
+template <> size_t GenericFill<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDecomposes"); } do { // convert the 'RelatingObject' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDecomposes,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->RelatingObject, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDecomposes to be a `IfcObjectDefinition`")); }
- } while(0);
- do { // convert the 'RelatedObjects' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDecomposes,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->RelatedObjects, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDecomposes to be a `SET [1:?] OF IfcObjectDefinition`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCovering>(const DB& db, const LIST& params, IfcCovering* in)
+template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* in)
+template <> size_t GenericFill<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyline"); } do { // convert the 'Points' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Points, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyline to be a `LIST [2:?] OF IfcCartesianPoint`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPath>(const DB& db, const LIST& params, IfcPath* in)
+template <> size_t GenericFill<IfcElectricHeaterType>(const DB& db, const LIST& params, IfcElectricHeaterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementComponent>(const DB& db, const LIST& params, IfcElementComponent* in)
+template <> size_t GenericFill<IfcElectricMotorType>(const DB& db, const LIST& params, IfcElectricMotorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFastener>(const DB& db, const LIST& params, IfcFastener* in)
+template <> size_t GenericFill<IfcElectricTimeControlType>(const DB& db, const LIST& params, IfcElectricTimeControlType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponent*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* in)
+template <> size_t GenericFill<IfcSystem>(const DB& db, const LIST& params, IfcSystem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMappedItem"); } do { // convert the 'MappingSource' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->MappingSource, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMappedItem to be a `IfcRepresentationMap`")); }
- } while(0);
- do { // convert the 'MappingTarget' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->MappingTarget, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMappedItem to be a `IfcCartesianTransformationOperator`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* in)
+template <> size_t GenericFill<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSystem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCrewResource>(const DB& db, const LIST& params, IfcCrewResource* in)
+template <> size_t GenericFill<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, IfcNamedUnit* in)
+template <> size_t GenericFill<IfcElementAssembly>(const DB& db, const LIST& params, IfcElementAssembly* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcNamedUnit"); } do { // convert the 'Dimensions' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcNamedUnit,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Dimensions, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcNamedUnit to be a `IfcDimensionalExponents`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcElementQuantity>(const DB& db, const LIST& params, IfcElementQuantity* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcElementQuantity"); } do { // convert the 'MethodOfMeasurement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->MethodOfMeasurement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcElementQuantity to be a `IfcLabel`")); }
} while(0);
- do { // convert the 'UnitType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcNamedUnit,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->UnitType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcNamedUnit to be a `IfcUnitEnum`")); }
+ do { // convert the 'Quantities' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Quantities, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcElementQuantity to be a `SET [1:?] OF IfcPhysicalQuantity`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcContextDependentUnit>(const DB& db, const LIST& params, IfcContextDependentUnit* in)
+template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& params, IfcElementarySurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcElementarySurface"); } do { // convert the 'Position' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcElementarySurface,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Position, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcElementarySurface to be a `IfcAxis2Placement3D`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcEllipse>(const DB& db, const LIST& params, IfcEllipse* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcEllipse"); } do { // convert the 'SemiAxis1' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->SemiAxis1, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'SemiAxis2' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->SemiAxis2, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcEllipseProfileDef>(const DB& db, const LIST& params, IfcEllipseProfileDef* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* in)
+template <> size_t GenericFill<IfcEnergyConversionDevice>(const DB& db, const LIST& params, IfcEnergyConversionDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRoof>(const DB& db, const LIST& params, IfcRoof* in)
+template <> size_t GenericFill<IfcEquipmentElement>(const DB& db, const LIST& params, IfcEquipmentElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* in)
+template <> size_t GenericFill<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* in)
+template <> size_t GenericFill<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* in)
+template <> size_t GenericFill<IfcEvaporatorType>(const DB& db, const LIST& params, IfcEvaporatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStyleModel*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const LIST& params, IfcSpatialStructureElement* in)
+template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& params, IfcSweptAreaSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
- if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcSpatialStructureElement"); } do { // convert the 'LongName' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSpatialStructureElement,2>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->LongName, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSpatialStructureElement to be a `IfcLabel`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSweptAreaSolid"); } do { // convert the 'SweptArea' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSweptAreaSolid,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->SweptArea, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptAreaSolid to be a `IfcProfileDef`")); }
} while(0);
- do { // convert the 'CompositionType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSpatialStructureElement,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->CompositionType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSpatialStructureElement to be a `IfcElementCompositionEnum`")); }
+ do { // convert the 'Position' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSweptAreaSolid,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->Position, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptAreaSolid to be a `IfcAxis2Placement3D`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, IfcBuilding* in)
+template <> size_t GenericFill<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
- if (params.GetSize() < 12) { throw STEP::TypeError("expected 12 arguments to IfcBuilding"); } do { // convert the 'ElevationOfRefHeight' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ElevationOfRefHeight, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcBuilding to be a `IfcLengthMeasure`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcExtrudedAreaSolid"); } do { // convert the 'ExtrudedDirection' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ExtrudedDirection, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcExtrudedAreaSolid to be a `IfcDirection`")); }
} while(0);
- do { // convert the 'ElevationOfTerrain' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ElevationOfTerrain, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcBuilding to be a `IfcLengthMeasure`")); }
+ do { // convert the 'Depth' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Depth, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcExtrudedAreaSolid to be a `IfcPositiveLengthMeasure`")); }
} while(0);
- do { // convert the 'BuildingAddress' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->BuildingAddress, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcBuilding to be a `IfcPostalAddress`")); }
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcFace>(const DB& db, const LIST& params, IfcFace* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFace"); } do { // convert the 'Bounds' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFace,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Bounds, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFace to be a `SET [1:?] OF IfcFaceBound`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConnectedFaceSet>(const DB& db, const LIST& params, IfcConnectedFaceSet* in)
+template <> size_t GenericFill<IfcFaceBasedSurfaceModel>(const DB& db, const LIST& params, IfcFaceBasedSurfaceModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConnectedFaceSet"); } do { // convert the 'CfsFaces' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcConnectedFaceSet,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->CfsFaces, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConnectedFaceSet to be a `SET [1:?] OF IfcFace`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFaceBasedSurfaceModel"); } do { // convert the 'FbsmFaces' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->FbsmFaces, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBasedSurfaceModel to be a `SET [1:?] OF IfcConnectedFaceSet`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* in)
+template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConnectedFaceSet*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceBound"); } do { // convert the 'Bound' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFaceBound,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Bound, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBound to be a `IfcLoop`")); }
+ } while(0);
+ do { // convert the 'Orientation' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFaceBound,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->Orientation, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcFaceBound to be a `BOOLEAN`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* in)
+template <> size_t GenericFill<IfcFaceOuterBound>(const DB& db, const LIST& params, IfcFaceOuterBound* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcFaceBound*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceOuterBound"); } return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcFaceSurface>(const DB& db, const LIST& params, IfcFaceSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFace*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcConic* in)
+template <> size_t GenericFill<IfcManifoldSolidBrep>(const DB& db, const LIST& params, IfcManifoldSolidBrep* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConic"); } do { // convert the 'Position' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcConic,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Position, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConic to be a `IfcAxis2Placement`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcManifoldSolidBrep"); } do { // convert the 'Outer' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcManifoldSolidBrep,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->Outer, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcManifoldSolidBrep to be a `IfcClosedShell`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCoveringType>(const DB& db, const LIST& params, IfcCoveringType* in)
+template <> size_t GenericFill<IfcFacetedBrep>(const DB& db, const LIST& params, IfcFacetedBrep* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* in)
+template <> size_t GenericFill<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRectangleProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAirTerminalType>(const DB& db, const LIST& params, IfcAirTerminalType* in)
+template <> size_t GenericFill<IfcFanType>(const DB& db, const LIST& params, IfcFanType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowMovingDeviceType>(const DB& db, const LIST& params, IfcFlowMovingDeviceType* in)
+template <> size_t GenericFill<IfcFastener>(const DB& db, const LIST& params, IfcFastener* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementComponent*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCompressorType>(const DB& db, const LIST& params, IfcCompressorType* in)
+template <> size_t GenericFill<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcIShapeProfileDef>(const DB& db, const LIST& params, IfcIShapeProfileDef* in)
+template <> size_t GenericFill<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcIShapeProfileDef"); } do { // convert the 'OverallWidth' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->OverallWidth, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'OverallDepth' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->OverallDepth, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'WebThickness' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->WebThickness, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'FlangeThickness' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[3]=true; break; }
- try { GenericConvert( in->FlangeThickness, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'FilletRadius' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcIShapeProfileDef,5>::aux_is_derived[4]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->FilletRadius, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFeatureElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAsymmetricIShapeProfileDef>(const DB& db, const LIST& params, IfcAsymmetricIShapeProfileDef* in)
+template <> size_t GenericFill<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcIShapeProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcControllerType>(const DB& db, const LIST& params, IfcControllerType* in)
+template <> size_t GenericFill<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* in)
+template <> size_t GenericFill<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGroup>(const DB& db, const LIST& params, IfcGroup* in)
+template <> size_t GenericFill<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAsset>(const DB& db, const LIST& params, IfcAsset* in)
+template <> size_t GenericFill<IfcFireSuppressionTerminalType>(const DB& db, const LIST& params, IfcFireSuppressionTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* in)
+template <> size_t GenericFill<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRailingType>(const DB& db, const LIST& params, IfcRailingType* in)
+template <> size_t GenericFill<IfcFlowInstrumentType>(const DB& db, const LIST& params, IfcFlowInstrumentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWall>(const DB& db, const LIST& params, IfcWall* in)
+template <> size_t GenericFill<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* in)
+template <> size_t GenericFill<IfcFlowMovingDevice>(const DB& db, const LIST& params, IfcFlowMovingDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* in)
+template <> size_t GenericFill<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertyListValue"); } do { // convert the 'ListValues' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ListValues, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertyListValue to be a `LIST [1:?] OF IfcValue`")); }
- } while(0);
- do { // convert the 'Unit' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Unit, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertyListValue to be a `IfcUnit`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* in)
+template <> size_t GenericFill<IfcFlowStorageDevice>(const DB& db, const LIST& params, IfcFlowStorageDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricGeneratorType>(const DB& db, const LIST& params, IfcElectricGeneratorType* in)
+template <> size_t GenericFill<IfcFlowTerminal>(const DB& db, const LIST& params, IfcFlowTerminal* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDoor>(const DB& db, const LIST& params, IfcDoor* in)
+template <> size_t GenericFill<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
- if (params.GetSize() < 10) { throw STEP::TypeError("expected 10 arguments to IfcDoor"); } do { // convert the 'OverallHeight' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->OverallHeight, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'OverallWidth' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->OverallWidth, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStyledItem>(const DB& db, const LIST& params, IfcStyledItem* in)
+template <> size_t GenericFill<IfcFooting>(const DB& db, const LIST& params, IfcFooting* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcStyledItem"); } do { // convert the 'Item' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Item, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcStyledItem to be a `IfcRepresentationItem`")); }
- } while(0);
- do { // convert the 'Styles' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->Styles, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcStyledItem to be a `SET [1:?] OF IfcPresentationStyleAssignment`")); }
- } while(0);
- do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcStyledItem,3>::aux_is_derived[2]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcStyledItem to be a `IfcLabel`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationOccurrence>(const DB& db, const LIST& params, IfcAnnotationOccurrence* in)
+template <> size_t GenericFill<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStyledItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationSymbolOccurrence>(const DB& db, const LIST& params, IfcAnnotationSymbolOccurrence* in)
+template <> size_t GenericFill<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcArbitraryClosedProfileDef>(const DB& db, const LIST& params, IfcArbitraryClosedProfileDef* in)
+template <> size_t GenericFill<IfcFurnitureStandard>(const DB& db, const LIST& params, IfcFurnitureStandard* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryClosedProfileDef"); } do { // convert the 'OuterCurve' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcArbitraryClosedProfileDef,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->OuterCurve, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryClosedProfileDef to be a `IfcCurve`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcArbitraryProfileDefWithVoids>(const DB& db, const LIST& params, IfcArbitraryProfileDefWithVoids* in)
+template <> size_t GenericFill<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcArbitraryClosedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLine* in)
+template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLine"); } do { // convert the 'Pnt' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Pnt, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLine to be a `IfcCartesianPoint`")); }
- } while(0);
- do { // convert the 'Dir' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Dir, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLine to be a `IfcVector`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowSegmentType>(const DB& db, const LIST& params, IfcFlowSegmentType* in)
+template <> size_t GenericFill<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAirTerminalBoxType>(const DB& db, const LIST& params, IfcAirTerminalBoxType* in)
+template <> size_t GenericFill<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricSet*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* in)
+template <> size_t GenericFill<IfcRepresentationContext>(const DB& db, const LIST& params, IfcRepresentationContext* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertySingleValue"); } do { // convert the 'NominalValue' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcRepresentationContext"); } do { // convert the 'ContextIdentifier' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentationContext,2>::aux_is_derived[0]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->NominalValue, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertySingleValue to be a `IfcValue`")); }
+ try { GenericConvert( in->ContextIdentifier, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationContext to be a `IfcLabel`")); }
} while(0);
- do { // convert the 'Unit' argument
- boost::shared_ptr<const DataType> arg = params[base++];
+ do { // convert the 'ContextType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentationContext,2>::aux_is_derived[1]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Unit, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertySingleValue to be a `IfcUnit`")); }
+ try { GenericConvert( in->ContextType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationContext to be a `IfcLabel`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAlarmType>(const DB& db, const LIST& params, IfcAlarmType* in)
+template <> size_t GenericFill<IfcGeometricRepresentationContext>(const DB& db, const LIST& params, IfcGeometricRepresentationContext* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationContext*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcGeometricRepresentationContext"); } do { // convert the 'CoordinateSpaceDimension' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->CoordinateSpaceDimension, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcGeometricRepresentationContext to be a `IfcDimensionCount`")); }
+ } while(0);
+ do { // convert the 'Precision' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[1]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Precision, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcGeometricRepresentationContext to be a `REAL`")); }
+ } while(0);
+ do { // convert the 'WorldCoordinateSystem' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->WorldCoordinateSystem, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcGeometricRepresentationContext to be a `IfcAxis2Placement`")); }
+ } while(0);
+ do { // convert the 'TrueNorth' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[3]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->TrueNorth, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcGeometricRepresentationContext to be a `IfcDirection`")); }
+ } while(0);
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcGeometricRepresentationSubContext>(const DB& db, const LIST& params, IfcGeometricRepresentationSubContext* in)
+{
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationContext*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEllipseProfileDef>(const DB& db, const LIST& params, IfcEllipseProfileDef* in)
+template <> size_t GenericFill<IfcGrid>(const DB& db, const LIST& params, IfcGrid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
+}
+// -----------------------------------------------------------------------------------------------------------
+template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
+{
+ size_t base = 0;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStair>(const DB& db, const LIST& params, IfcStair* in)
+template <> size_t GenericFill<IfcGridPlacement>(const DB& db, const LIST& params, IfcGridPlacement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObjectPlacement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* in)
+template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleShading"); } do { // convert the 'SurfaceColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSurfaceStyleShading,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->SurfaceColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleShading to be a `IfcColourRgb`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* in)
+template <> size_t GenericFill<IfcHumidifierType>(const DB& db, const LIST& params, IfcHumidifierType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDefinedSymbol>(const DB& db, const LIST& params, IfcDefinedSymbol* in)
+template <> size_t GenericFill<IfcInventory>(const DB& db, const LIST& params, IfcInventory* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementComponentType>(const DB& db, const LIST& params, IfcElementComponentType* in)
+template <> size_t GenericFill<IfcJunctionBoxType>(const DB& db, const LIST& params, IfcJunctionBoxType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFastenerType>(const DB& db, const LIST& params, IfcFastenerType* in)
+template <> size_t GenericFill<IfcLShapeProfileDef>(const DB& db, const LIST& params, IfcLShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* in)
+template <> size_t GenericFill<IfcLaborResource>(const DB& db, const LIST& params, IfcLaborResource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFastenerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowFitting>(const DB& db, const LIST& params, IfcFlowFitting* in)
+template <> size_t GenericFill<IfcLampType>(const DB& db, const LIST& params, IfcLampType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* in)
+template <> size_t GenericFill<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/IFCReaderGen2.cpp b/src/3rdparty/assimp/code/IFCReaderGen2.cpp
index 7a6fa50a9..8d67a4231 100644
--- a/src/3rdparty/assimp/code/IFCReaderGen2.cpp
+++ b/src/3rdparty/assimp/code/IFCReaderGen2.cpp
@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,22 +23,24 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+/** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */
+
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCReaderGen.h"
@@ -48,1867 +50,1753 @@ using namespace IFC;
namespace STEP {
-template <> size_t GenericFill<IfcSurfaceStyle>(const DB& db, const LIST& params, IfcSurfaceStyle* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcPresentationStyle*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcSurfaceStyle"); } do { // convert the 'Side' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Side, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyle to be a `IfcSurfaceSide`")); }
- } while(0);
- do { // convert the 'Styles' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Styles, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyle to be a `SET [1:5] OF IfcSurfaceStyleElementSelect`")); }
- } while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationSurface>(const DB& db, const LIST& params, IfcAnnotationSurface* in)
+template <> size_t GenericFill<IfcLightSource>(const DB& db, const LIST& params, IfcLightSource* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowController>(const DB& db, const LIST& params, IfcFlowController* in)
+template <> size_t GenericFill<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingStorey>(const DB& db, const LIST& params, IfcBuildingStorey* in)
+template <> size_t GenericFill<IfcLightSourceDirectional>(const DB& db, const LIST& params, IfcLightSourceDirectional* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* in)
+template <> size_t GenericFill<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* in)
+template <> size_t GenericFill<IfcLightSourcePositional>(const DB& db, const LIST& params, IfcLightSourcePositional* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDuctSegmentType>(const DB& db, const LIST& params, IfcDuctSegmentType* in)
+template <> size_t GenericFill<IfcLightSourceSpot>(const DB& db, const LIST& params, IfcLightSourceSpot* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLightSourcePositional*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFace>(const DB& db, const LIST& params, IfcFace* in)
+template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLine* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFace"); } do { // convert the 'Bounds' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFace,1>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Bounds, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFace to be a `SET [1:?] OF IfcFaceBound`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLine"); } do { // convert the 'Pnt' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Pnt, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLine to be a `IfcCartesianPoint`")); }
} while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralSurfaceMember>(const DB& db, const LIST& params, IfcStructuralSurfaceMember* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralSurfaceMemberVarying>(const DB& db, const LIST& params, IfcStructuralSurfaceMemberVarying* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralSurfaceMember*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceSurface>(const DB& db, const LIST& params, IfcFaceSurface* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcFace*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ do { // convert the 'Dir' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Dir, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLine to be a `IfcVector`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCostSchedule>(const DB& db, const LIST& params, IfcCostSchedule* in)
+template <> size_t GenericFill<IfcLinearDimension>(const DB& db, const LIST& params, IfcLinearDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlanarExtent>(const DB& db, const LIST& params, IfcPlanarExtent* in)
+template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& params, IfcLocalPlacement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcObjectPlacement*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLocalPlacement"); } do { // convert the 'PlacementRelTo' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->PlacementRelTo, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLocalPlacement to be a `IfcObjectPlacement`")); }
+ } while(0);
+ do { // convert the 'RelativePlacement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelativePlacement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLocalPlacement to be a `IfcAxis2Placement`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* in)
+template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params, IfcMappedItem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPlanarExtent*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMappedItem"); } do { // convert the 'MappingSource' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->MappingSource, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMappedItem to be a `IfcRepresentationMap`")); }
+ } while(0);
+ do { // convert the 'MappingTarget' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->MappingTarget, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMappedItem to be a `IfcCartesianTransformationOperator`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST& params, IfcColourSpecification* in)
+template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIST& params, IfcProductRepresentation* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcColourSpecification"); } do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcColourSpecification,1>::aux_is_derived[0]=true; break; }
+ size_t base = 0;
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcProductRepresentation"); } do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[0]=true; break; }
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcColourSpecification to be a `IfcLabel`")); }
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProductRepresentation to be a `IfcLabel`")); }
} while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVector>(const DB& db, const LIST& params, IfcVector* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcVector"); } do { // convert the 'Orientation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Orientation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcVector to be a `IfcDirection`")); }
+ do { // convert the 'Description' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[1]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Description, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProductRepresentation to be a `IfcText`")); }
} while(0);
- do { // convert the 'Magnitude' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Magnitude, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcVector to be a `IfcLengthMeasure`")); }
+ do { // convert the 'Representations' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcProductRepresentation,3>::aux_is_derived[2]=true; break; }
+ try { GenericConvert( in->Representations, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcProductRepresentation to be a `LIST [1:?] OF IfcRepresentation`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBeam>(const DB& db, const LIST& params, IfcBeam* in)
+template <> size_t GenericFill<IfcMaterialDefinitionRepresentation>(const DB& db, const LIST& params, IfcMaterialDefinitionRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcColourRgb>(const DB& db, const LIST& params, IfcColourRgb* in)
+template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcColourSpecification*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcColourRgb"); } do { // convert the 'Red' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Red, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
- } while(0);
- do { // convert the 'Green' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Green, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMeasureWithUnit"); } do { // convert the 'ValueComponent' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ValueComponent, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMeasureWithUnit to be a `IfcValue`")); }
} while(0);
- do { // convert the 'Blue' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Blue, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
+ do { // convert the 'UnitComponent' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->UnitComponent, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMeasureWithUnit to be a `IfcUnit`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* in)
+template <> size_t GenericFill<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFastener*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralPlanarActionVarying>(const DB& db, const LIST& params, IfcStructuralPlanarActionVarying* in)
+template <> size_t GenericFill<IfcMechanicalFastenerType>(const DB& db, const LIST& params, IfcMechanicalFastenerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralPlanarAction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFastenerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSite>(const DB& db, const LIST& params, IfcSite* in)
+template <> size_t GenericFill<IfcMember>(const DB& db, const LIST& params, IfcMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
- if (params.GetSize() < 14) { throw STEP::TypeError("expected 14 arguments to IfcSite"); } do { // convert the 'RefLatitude' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RefLatitude, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
- } while(0);
- do { // convert the 'RefLongitude' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RefLongitude, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
- } while(0);
- do { // convert the 'RefElevation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RefElevation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcSite to be a `IfcLengthMeasure`")); }
- } while(0);
- do { // convert the 'LandTitleNumber' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->LandTitleNumber, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 12 to IfcSite to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'SiteAddress' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->SiteAddress, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 13 to IfcSite to be a `IfcPostalAddress`")); }
- } while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDiscreteAccessoryType>(const DB& db, const LIST& params, IfcDiscreteAccessoryType* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponentType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* in)
+template <> size_t GenericFill<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDiscreteAccessoryType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEvaporativeCoolerType>(const DB& db, const LIST& params, IfcEvaporativeCoolerType* in)
+template <> size_t GenericFill<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionChamberElementType>(const DB& db, const LIST& params, IfcDistributionChamberElementType* in)
+template <> size_t GenericFill<IfcProcess>(const DB& db, const LIST& params, IfcProcess* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFeatureElementAddition>(const DB& db, const LIST& params, IfcFeatureElementAddition* in)
+template <> size_t GenericFill<IfcTask>(const DB& db, const LIST& params, IfcTask* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProcess*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* in)
+template <> size_t GenericFill<IfcMove>(const DB& db, const LIST& params, IfcMove* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTask*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCoolingTowerType>(const DB& db, const LIST& params, IfcCoolingTowerType* in)
+template <> size_t GenericFill<IfcOccupant>(const DB& db, const LIST& params, IfcOccupant* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcActor*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCenterLineProfileDef>(const DB& db, const LIST& params, IfcCenterLineProfileDef* in)
+template <> size_t GenericFill<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcArbitraryOpenProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* in)
+template <> size_t GenericFill<IfcOffsetCurve3D>(const DB& db, const LIST& params, IfcOffsetCurve3D* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourceGoniometric>(const DB& db, const LIST& params, IfcLightSourceGoniometric* in)
+template <> size_t GenericFill<IfcOneDirectionRepeatFactor>(const DB& db, const LIST& params, IfcOneDirectionRepeatFactor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* in)
+template <> size_t GenericFill<IfcOpenShell>(const DB& db, const LIST& params, IfcOpenShell* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcConnectedFaceSet*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMemberType>(const DB& db, const LIST& params, IfcMemberType* in)
+template <> size_t GenericFill<IfcOpeningElement>(const DB& db, const LIST& params, IfcOpeningElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFeatureElementSubtraction*>(in));
+ if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcOpeningElement"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* in)
+template <> size_t GenericFill<IfcOrderAction>(const DB& db, const LIST& params, IfcOrderAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTask*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMotorConnectionType>(const DB& db, const LIST& params, IfcMotorConnectionType* in)
+template <> size_t GenericFill<IfcOrientedEdge>(const DB& db, const LIST& params, IfcOrientedEdge* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowTreatmentDeviceType>(const DB& db, const LIST& params, IfcFlowTreatmentDeviceType* in)
+template <> size_t GenericFill<IfcOutletType>(const DB& db, const LIST& params, IfcOutletType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDuctSilencerType>(const DB& db, const LIST& params, IfcDuctSilencerType* in)
+template <> size_t GenericFill<IfcPath>(const DB& db, const LIST& params, IfcPath* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFurnishingElementType>(const DB& db, const LIST& params, IfcFurnishingElementType* in)
+template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST& params, IfcPerformanceHistory* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* in)
+template <> size_t GenericFill<IfcPermit>(const DB& db, const LIST& params, IfcPermit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* in)
+template <> size_t GenericFill<IfcPile>(const DB& db, const LIST& params, IfcPile* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBSplineCurve>(const DB& db, const LIST& params, IfcBSplineCurve* in)
+template <> size_t GenericFill<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcBSplineCurve"); } do { // convert the 'Degree' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Degree, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBSplineCurve to be a `INTEGER`")); }
- } while(0);
- do { // convert the 'ControlPointsList' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->ControlPointsList, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBSplineCurve to be a `LIST [2:?] OF IfcCartesianPoint`")); }
- } while(0);
- do { // convert the 'CurveForm' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->CurveForm, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBSplineCurve to be a `IfcBSplineCurveForm`")); }
- } while(0);
- do { // convert the 'ClosedCurve' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[3]=true; break; }
- try { GenericConvert( in->ClosedCurve, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBSplineCurve to be a `LOGICAL`")); }
- } while(0);
- do { // convert the 'SelfIntersect' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcBSplineCurve,5>::aux_is_derived[4]=true; break; }
- try { GenericConvert( in->SelfIntersect, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcBSplineCurve to be a `LOGICAL`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBezierCurve>(const DB& db, const LIST& params, IfcBezierCurve* in)
+template <> size_t GenericFill<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBSplineCurve*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcActuatorType>(const DB& db, const LIST& params, IfcActuatorType* in)
+template <> size_t GenericFill<IfcPlanarExtent>(const DB& db, const LIST& params, IfcPlanarExtent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionControlElement>(const DB& db, const LIST& params, IfcDistributionControlElement* in)
+template <> size_t GenericFill<IfcPlanarBox>(const DB& db, const LIST& params, IfcPlanarBox* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcPlanarExtent*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotation>(const DB& db, const LIST& params, IfcAnnotation* in)
+template <> size_t GenericFill<IfcPlane>(const DB& db, const LIST& params, IfcPlane* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
- if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcAnnotation"); } return base;
+ size_t base = GenericFill(db,params,static_cast<IfcElementarySurface*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPlane"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcShellBasedSurfaceModel>(const DB& db, const LIST& params, IfcShellBasedSurfaceModel* in)
+template <> size_t GenericFill<IfcPlate>(const DB& db, const LIST& params, IfcPlate* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcShellBasedSurfaceModel"); } do { // convert the 'SbsmBoundary' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SbsmBoundary, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcShellBasedSurfaceModel to be a `SET [1:?] OF IfcShell`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcActionRequest>(const DB& db, const LIST& params, IfcActionRequest* in)
+template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, IfcPlateType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcExtrudedAreaSolid>(const DB& db, const LIST& params, IfcExtrudedAreaSolid* in)
+template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcExtrudedAreaSolid"); } do { // convert the 'ExtrudedDirection' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ExtrudedDirection, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcExtrudedAreaSolid to be a `IfcDirection`")); }
- } while(0);
- do { // convert the 'Depth' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Depth, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcExtrudedAreaSolid to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSystem>(const DB& db, const LIST& params, IfcSystem* in)
+template <> size_t GenericFill<IfcPointOnSurface>(const DB& db, const LIST& params, IfcPointOnSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFillAreaStyleHatching>(const DB& db, const LIST& params, IfcFillAreaStyleHatching* in)
+template <> size_t GenericFill<IfcPolyLoop>(const DB& db, const LIST& params, IfcPolyLoop* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyLoop"); } do { // convert the 'Polygon' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Polygon, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyLoop to be a `LIST [3:?] OF IfcCartesianPoint`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* in)
+template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const LIST& params, IfcPolygonalBoundedHalfSpace* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelVoidsElement"); } do { // convert the 'RelatingBuildingElement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatingBuildingElement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelVoidsElement to be a `IfcElement`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPolygonalBoundedHalfSpace"); } do { // convert the 'Position' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Position, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPolygonalBoundedHalfSpace to be a `IfcAxis2Placement3D`")); }
} while(0);
- do { // convert the 'RelatedOpeningElement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->RelatedOpeningElement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelVoidsElement to be a `IfcFeatureElementSubtraction`")); }
+ do { // convert the 'PolygonalBoundary' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->PolygonalBoundary, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPolygonalBoundedHalfSpace to be a `IfcBoundedCurve`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* in)
+template <> size_t GenericFill<IfcPolyline>(const DB& db, const LIST& params, IfcPolyline* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyline"); } do { // convert the 'Points' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Points, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyline to be a `LIST [2:?] OF IfcCartesianPoint`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianTransformationOperator3DnonUniform>(const DB& db, const LIST& params, IfcCartesianTransformationOperator3DnonUniform* in)
+template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCartesianTransformationOperator3D*>(in));
- if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcCartesianTransformationOperator3DnonUniform"); } do { // convert the 'Scale2' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Scale2, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
- } while(0);
- do { // convert the 'Scale3' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Scale3, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyleAssignment"); } do { // convert the 'Styles' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Styles, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyleAssignment to be a `SET [1:?] OF IfcPresentationStyleSelect`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCurtainWallType>(const DB& db, const LIST& params, IfcCurtainWallType* in)
+template <> size_t GenericFill<IfcProcedure>(const DB& db, const LIST& params, IfcProcedure* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProcess*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEquipmentStandard>(const DB& db, const LIST& params, IfcEquipmentStandard* in)
+template <> size_t GenericFill<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowStorageDeviceType>(const DB& db, const LIST& params, IfcFlowStorageDeviceType* in)
+template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, IfcProject* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElementType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcObject*>(in));
+ if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcProject"); } do { // convert the 'LongName' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->LongName, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcProject to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'Phase' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Phase, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProject to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'RepresentationContexts' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RepresentationContexts, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcProject to be a `SET [1:?] OF IfcRepresentationContext`")); }
+ } while(0);
+ do { // convert the 'UnitsInContext' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->UnitsInContext, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcProject to be a `IfcUnitAssignment`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDiameterDimension>(const DB& db, const LIST& params, IfcDiameterDimension* in)
+template <> size_t GenericFill<IfcProjectOrder>(const DB& db, const LIST& params, IfcProjectOrder* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* in)
+template <> size_t GenericFill<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWindow>(const DB& db, const LIST& params, IfcWindow* in)
+template <> size_t GenericFill<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowTreatmentDevice>(const DB& db, const LIST& params, IfcFlowTreatmentDevice* in)
+template <> size_t GenericFill<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFeatureElementAddition*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcChillerType>(const DB& db, const LIST& params, IfcChillerType* in)
+template <> size_t GenericFill<IfcSimpleProperty>(const DB& db, const LIST& params, IfcSimpleProperty* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProperty*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSimpleProperty"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* in)
+template <> size_t GenericFill<IfcPropertyBoundedValue>(const DB& db, const LIST& params, IfcPropertyBoundedValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRectangleProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoxedHalfSpace>(const DB& db, const LIST& params, IfcBoxedHalfSpace* in)
+template <> size_t GenericFill<IfcPropertyEnumeratedValue>(const DB& db, const LIST& params, IfcPropertyEnumeratedValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& params, IfcAxis2Placement2D* in)
+template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& params, IfcPropertyListValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis2Placement2D"); } do { // convert the 'RefDirection' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->RefDirection, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement2D to be a `IfcDirection`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertyListValue"); } do { // convert the 'ListValues' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ListValues, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertyListValue to be a `LIST [1:?] OF IfcValue`")); }
} while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpaceProgram>(const DB& db, const LIST& params, IfcSpaceProgram* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPoint>(const DB& db, const LIST& params, IfcPoint* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCartesianPoint>(const DB& db, const LIST& params, IfcCartesianPoint* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcCartesianPoint"); } do { // convert the 'Coordinates' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Coordinates, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianPoint to be a `LIST [1:3] OF IfcLengthMeasure`")); }
+ do { // convert the 'Unit' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Unit, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertyListValue to be a `IfcUnit`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoundedSurface>(const DB& db, const LIST& params, IfcBoundedSurface* in)
+template <> size_t GenericFill<IfcPropertyReferenceValue>(const DB& db, const LIST& params, IfcPropertyReferenceValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLoop>(const DB& db, const LIST& params, IfcLoop* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPolyLoop>(const DB& db, const LIST& params, IfcPolyLoop* in)
+template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyLoop"); } do { // convert the 'Polygon' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Polygon, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyLoop to be a `LIST [3:?] OF IfcCartesianPoint`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcPropertySet"); } do { // convert the 'HasProperties' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->HasProperties, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcPropertySet to be a `SET [1:?] OF IfcProperty`")); }
} while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTerminatorSymbol>(const DB& db, const LIST& params, IfcTerminatorSymbol* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationSymbolOccurrence*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDimensionCurveTerminator>(const DB& db, const LIST& params, IfcDimensionCurveTerminator* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcTerminatorSymbol*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTrapeziumProfileDef>(const DB& db, const LIST& params, IfcTrapeziumProfileDef* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentationContext>(const DB& db, const LIST& params, IfcRepresentationContext* in)
+template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST& params, IfcPropertySingleValue* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcRepresentationContext"); } do { // convert the 'ContextIdentifier' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentationContext,2>::aux_is_derived[0]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ContextIdentifier, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationContext to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'ContextType' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentationContext,2>::aux_is_derived[1]=true; break; }
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertySingleValue"); } do { // convert the 'NominalValue' argument
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ContextType, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationContext to be a `IfcLabel`")); }
- } while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGeometricRepresentationContext>(const DB& db, const LIST& params, IfcGeometricRepresentationContext* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcRepresentationContext*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcGeometricRepresentationContext"); } do { // convert the 'CoordinateSpaceDimension' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->CoordinateSpaceDimension, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcGeometricRepresentationContext to be a `IfcDimensionCount`")); }
+ try { GenericConvert( in->NominalValue, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertySingleValue to be a `IfcValue`")); }
} while(0);
- do { // convert the 'Precision' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[1]=true; break; }
+ do { // convert the 'Unit' argument
+ std::shared_ptr<const DataType> arg = params[base++];
if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Precision, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcGeometricRepresentationContext to be a `REAL`")); }
- } while(0);
- do { // convert the 'WorldCoordinateSystem' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[2]=true; break; }
- try { GenericConvert( in->WorldCoordinateSystem, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcGeometricRepresentationContext to be a `IfcAxis2Placement`")); }
- } while(0);
- do { // convert the 'TrueNorth' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcGeometricRepresentationContext,4>::aux_is_derived[3]=true; break; }
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->TrueNorth, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcGeometricRepresentationContext to be a `IfcDirection`")); }
+ try { GenericConvert( in->Unit, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertySingleValue to be a `IfcUnit`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCurveBoundedPlane>(const DB& db, const LIST& params, IfcCurveBoundedPlane* in)
+template <> size_t GenericFill<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* in)
+template <> size_t GenericFill<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcSIUnit"); } do { // convert the 'Prefix' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Prefix, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSIUnit to be a `IfcSIPrefix`")); }
- } while(0);
- do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSIUnit to be a `IfcSIUnitName`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralReaction>(const DB& db, const LIST& params, IfcStructuralReaction* in)
+template <> size_t GenericFill<IfcProxy>(const DB& db, const LIST& params, IfcProxy* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralActivity*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
+template <> size_t GenericFill<IfcPumpType>(const DB& db, const LIST& params, IfcPumpType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralReaction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& params, IfcAxis1Placement* in)
+template <> size_t GenericFill<IfcRadiusDimension>(const DB& db, const LIST& params, IfcRadiusDimension* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPlacement*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis1Placement"); } do { // convert the 'Axis' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Axis, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis1Placement to be a `IfcDirection`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcDimensionCurveDirectedCallout*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricApplianceType>(const DB& db, const LIST& params, IfcElectricApplianceType* in)
+template <> size_t GenericFill<IfcRailing>(const DB& db, const LIST& params, IfcRailing* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* in)
+template <> size_t GenericFill<IfcRailingType>(const DB& db, const LIST& params, IfcRailingType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFurnishingElement>(const DB& db, const LIST& params, IfcFurnishingElement* in)
+template <> size_t GenericFill<IfcRamp>(const DB& db, const LIST& params, IfcRamp* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProtectiveDeviceType>(const DB& db, const LIST& params, IfcProtectiveDeviceType* in)
+template <> size_t GenericFill<IfcRampFlight>(const DB& db, const LIST& params, IfcRampFlight* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* in)
+template <> size_t GenericFill<IfcRampFlightType>(const DB& db, const LIST& params, IfcRampFlightType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* in)
+template <> size_t GenericFill<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBezierCurve*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* in)
+template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST& params, IfcRectangleProfileDef* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcRepresentationMap"); } do { // convert the 'MappingOrigin' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->MappingOrigin, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationMap to be a `IfcAxis2Placement`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRectangleProfileDef"); } do { // convert the 'XDim' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRectangleProfileDef,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->XDim, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
} while(0);
- do { // convert the 'MappedRepresentation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->MappedRepresentation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationMap to be a `IfcRepresentation`")); }
+ do { // convert the 'YDim' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRectangleProfileDef,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->YDim, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcClosedShell>(const DB& db, const LIST& params, IfcClosedShell* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcConnectedFaceSet*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcClosedShell"); } return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementPart>(const DB& db, const LIST& params, IfcBuildingElementPart* in)
+template <> size_t GenericFill<IfcRectangleHollowProfileDef>(const DB& db, const LIST& params, IfcRectangleHollowProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRectangleProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBlock>(const DB& db, const LIST& params, IfcBlock* in)
+template <> size_t GenericFill<IfcRectangularPyramid>(const DB& db, const LIST& params, IfcRectangularPyramid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightFixtureType>(const DB& db, const LIST& params, IfcLightFixtureType* in)
+template <> size_t GenericFill<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOpeningElement>(const DB& db, const LIST& params, IfcOpeningElement* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElementSubtraction*>(in));
- if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcOpeningElement"); } return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourceSpot>(const DB& db, const LIST& params, IfcLightSourceSpot* in)
+template <> size_t GenericFill<IfcReinforcingElement>(const DB& db, const LIST& params, IfcReinforcingElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSourcePositional*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementComponent*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* in)
+template <> size_t GenericFill<IfcReinforcingBar>(const DB& db, const LIST& params, IfcReinforcingBar* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricFlowStorageDeviceType>(const DB& db, const LIST& params, IfcElectricFlowStorageDeviceType* in)
+template <> size_t GenericFill<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSphere>(const DB& db, const LIST& params, IfcSphere* in)
+template <> size_t GenericFill<IfcRelationship>(const DB& db, const LIST& params, IfcRelationship* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRoot*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRelationship"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDamperType>(const DB& db, const LIST& params, IfcDamperType* in)
+template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& params, IfcRelDecomposes* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDecomposes"); } do { // convert the 'RelatingObject' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDecomposes,2>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->RelatingObject, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDecomposes to be a `IfcObjectDefinition`")); }
+ } while(0);
+ do { // convert the 'RelatedObjects' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDecomposes,2>::aux_is_derived[1]=true; break; }
+ try { GenericConvert( in->RelatedObjects, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDecomposes to be a `SET [1:?] OF IfcObjectDefinition`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProjectOrderRecord>(const DB& db, const LIST& params, IfcProjectOrderRecord* in)
+template <> size_t GenericFill<IfcRelAggregates>(const DB& db, const LIST& params, IfcRelAggregates* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelDecomposes*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelAggregates"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionChamberElement>(const DB& db, const LIST& params, IfcDistributionChamberElement* in)
+template <> size_t GenericFill<IfcRelConnects>(const DB& db, const LIST& params, IfcRelConnects* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRelConnects"); } return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMechanicalFastener>(const DB& db, const LIST& params, IfcMechanicalFastener* in)
+template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db, const LIST& params, IfcRelContainedInSpatialStructure* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFastener*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelContainedInSpatialStructure"); } do { // convert the 'RelatedElements' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatedElements, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelContainedInSpatialStructure to be a `SET [1:?] OF IfcProduct`")); }
+ } while(0);
+ do { // convert the 'RelatingStructure' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatingStructure, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelContainedInSpatialStructure to be a `IfcSpatialStructureElement`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRectangularTrimmedSurface>(const DB& db, const LIST& params, IfcRectangularTrimmedSurface* in)
+template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params, IfcRelDefines* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBoundedSurface*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelationship*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRelDefines"); } do { // convert the 'RelatedObjects' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDefines,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->RelatedObjects, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDefines to be a `SET [1:?] OF IfcObject`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcZone>(const DB& db, const LIST& params, IfcZone* in)
+template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LIST& params, IfcRelDefinesByProperties* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelDefines*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDefinesByProperties"); } do { // convert the 'RelatingPropertyDefinition' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRelDefinesByProperties,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->RelatingPropertyDefinition, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDefinesByProperties to be a `IfcPropertySetDefinition`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFanType>(const DB& db, const LIST& params, IfcFanType* in)
+template <> size_t GenericFill<IfcRelFillsElement>(const DB& db, const LIST& params, IfcRelFillsElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowMovingDeviceType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelFillsElement"); } do { // convert the 'RelatingOpeningElement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatingOpeningElement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelFillsElement to be a `IfcOpeningElement`")); }
+ } while(0);
+ do { // convert the 'RelatedBuildingElement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatedBuildingElement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelFillsElement to be a `IfcElement`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGeometricSet>(const DB& db, const LIST& params, IfcGeometricSet* in)
+template <> size_t GenericFill<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRelDefinesByProperties*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFillAreaStyleTiles>(const DB& db, const LIST& params, IfcFillAreaStyleTiles* in)
+template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& params, IfcRelVoidsElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
+ if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelVoidsElement"); } do { // convert the 'RelatingBuildingElement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatingBuildingElement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelVoidsElement to be a `IfcElement`")); }
+ } while(0);
+ do { // convert the 'RelatedOpeningElement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->RelatedOpeningElement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelVoidsElement to be a `IfcFeatureElementSubtraction`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCableSegmentType>(const DB& db, const LIST& params, IfcCableSegmentType* in)
+template <> size_t GenericFill<IfcRepresentation>(const DB& db, const LIST& params, IfcRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRepresentation"); } do { // convert the 'ContextOfItems' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->ContextOfItems, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentation to be a `IfcRepresentationContext`")); }
+ } while(0);
+ do { // convert the 'RepresentationIdentifier' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[1]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RepresentationIdentifier, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentation to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'RepresentationType' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[2]=true; break; }
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RepresentationType, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRepresentation to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'Items' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcRepresentation,4>::aux_is_derived[3]=true; break; }
+ try { GenericConvert( in->Items, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRepresentation to be a `SET [1:?] OF IfcRepresentationItem`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelOverridesProperties>(const DB& db, const LIST& params, IfcRelOverridesProperties* in)
+template <> size_t GenericFill<IfcRepresentationMap>(const DB& db, const LIST& params, IfcRepresentationMap* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcRelDefinesByProperties*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcRepresentationMap"); } do { // convert the 'MappingOrigin' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->MappingOrigin, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationMap to be a `IfcAxis2Placement`")); }
+ } while(0);
+ do { // convert the 'MappedRepresentation' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->MappedRepresentation, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationMap to be a `IfcRepresentation`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& params, IfcMeasureWithUnit* in)
+template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& params, IfcRevolvedAreaSolid* in)
{
- size_t base = 0;
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMeasureWithUnit"); } do { // convert the 'ValueComponent' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ValueComponent, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMeasureWithUnit to be a `IfcValue`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRevolvedAreaSolid"); } do { // convert the 'Axis' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Axis, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRevolvedAreaSolid to be a `IfcAxis1Placement`")); }
} while(0);
- do { // convert the 'UnitComponent' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->UnitComponent, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMeasureWithUnit to be a `IfcUnit`")); }
+ do { // convert the 'Angle' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Angle, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRevolvedAreaSolid to be a `IfcPlaneAngleMeasure`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* in)
+template <> size_t GenericFill<IfcRightCircularCone>(const DB& db, const LIST& params, IfcRightCircularCone* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* in)
+template <> size_t GenericFill<IfcRightCircularCylinder>(const DB& db, const LIST& params, IfcRightCircularCylinder* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFurnitureType>(const DB& db, const LIST& params, IfcFurnitureType* in)
+template <> size_t GenericFill<IfcRoof>(const DB& db, const LIST& params, IfcRoof* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCostItem>(const DB& db, const LIST& params, IfcCostItem* in)
+template <> size_t GenericFill<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEdgeFeature*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcReinforcingMesh>(const DB& db, const LIST& params, IfcReinforcingMesh* in)
+template <> size_t GenericFill<IfcRoundedRectangleProfileDef>(const DB& db, const LIST& params, IfcRoundedRectangleProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRectangleProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFacetedBrepWithVoids>(const DB& db, const LIST& params, IfcFacetedBrepWithVoids* in)
+template <> size_t GenericFill<IfcSIUnit>(const DB& db, const LIST& params, IfcSIUnit* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcManifoldSolidBrep*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
+ if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcSIUnit"); } do { // convert the 'Prefix' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Prefix, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSIUnit to be a `IfcSIPrefix`")); }
+ } while(0);
+ do { // convert the 'Name' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Name, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSIUnit to be a `IfcSIUnitName`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGasTerminalType>(const DB& db, const LIST& params, IfcGasTerminalType* in)
+template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPile>(const DB& db, const LIST& params, IfcPile* in)
+template <> size_t GenericFill<IfcScheduleTimeControl>(const DB& db, const LIST& params, IfcScheduleTimeControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFillAreaStyleTileSymbolWithStyle>(const DB& db, const LIST& params, IfcFillAreaStyleTileSymbolWithStyle* in)
+template <> size_t GenericFill<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConstructionMaterialResource>(const DB& db, const LIST& params, IfcConstructionMaterialResource* in)
+template <> size_t GenericFill<IfcSensorType>(const DB& db, const LIST& params, IfcSensorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDistributionControlElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationCurveOccurrence>(const DB& db, const LIST& params, IfcAnnotationCurveOccurrence* in)
+template <> size_t GenericFill<IfcServiceLife>(const DB& db, const LIST& params, IfcServiceLife* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDimensionCurve>(const DB& db, const LIST& params, IfcDimensionCurve* in)
+template <> size_t GenericFill<IfcShapeModel>(const DB& db, const LIST& params, IfcShapeModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGeometricCurveSet>(const DB& db, const LIST& params, IfcGeometricCurveSet* in)
+template <> size_t GenericFill<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricSet*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcShapeModel*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRelAggregates>(const DB& db, const LIST& params, IfcRelAggregates* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcRelDecomposes*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelAggregates"); } return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceBasedSurfaceModel>(const DB& db, const LIST& params, IfcFaceBasedSurfaceModel* in)
+template <> size_t GenericFill<IfcShellBasedSurfaceModel>(const DB& db, const LIST& params, IfcShellBasedSurfaceModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFaceBasedSurfaceModel"); } do { // convert the 'FbsmFaces' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->FbsmFaces, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBasedSurfaceModel to be a `SET [1:?] OF IfcConnectedFaceSet`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcShellBasedSurfaceModel"); } do { // convert the 'SbsmBoundary' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->SbsmBoundary, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcShellBasedSurfaceModel to be a `SET [1:?] OF IfcShell`")); }
} while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEnergyConversionDevice>(const DB& db, const LIST& params, IfcEnergyConversionDevice* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRampFlight>(const DB& db, const LIST& params, IfcRampFlight* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVertexLoop>(const DB& db, const LIST& params, IfcVertexLoop* in)
+template <> size_t GenericFill<IfcSite>(const DB& db, const LIST& params, IfcSite* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
+ if (params.GetSize() < 14) { throw STEP::TypeError("expected 14 arguments to IfcSite"); } do { // convert the 'RefLatitude' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RefLatitude, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
+ } while(0);
+ do { // convert the 'RefLongitude' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RefLongitude, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
+ } while(0);
+ do { // convert the 'RefElevation' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->RefElevation, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcSite to be a `IfcLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'LandTitleNumber' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->LandTitleNumber, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 12 to IfcSite to be a `IfcLabel`")); }
+ } while(0);
+ do { // convert the 'SiteAddress' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->SiteAddress, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 13 to IfcSite to be a `IfcPostalAddress`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPlate>(const DB& db, const LIST& params, IfcPlate* in)
+template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* in)
+template <> size_t GenericFill<IfcSlabType>(const DB& db, const LIST& params, IfcSlabType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, IfcFaceBound* in)
+template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSpace* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceBound"); } do { // convert the 'Bound' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFaceBound,2>::aux_is_derived[0]=true; break; }
- try { GenericConvert( in->Bound, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBound to be a `IfcLoop`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
+ if (params.GetSize() < 11) { throw STEP::TypeError("expected 11 arguments to IfcSpace"); } do { // convert the 'InteriorOrExteriorSpace' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->InteriorOrExteriorSpace, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSpace to be a `IfcInternalOrExternalEnum`")); }
} while(0);
- do { // convert the 'Orientation' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcFaceBound,2>::aux_is_derived[1]=true; break; }
- try { GenericConvert( in->Orientation, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcFaceBound to be a `BOOLEAN`")); }
+ do { // convert the 'ElevationWithFlooring' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->ElevationWithFlooring, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSpace to be a `IfcLengthMeasure`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFaceOuterBound>(const DB& db, const LIST& params, IfcFaceOuterBound* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcFaceBound*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceOuterBound"); } return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOneDirectionRepeatFactor>(const DB& db, const LIST& params, IfcOneDirectionRepeatFactor* in)
+template <> size_t GenericFill<IfcSpaceHeaterType>(const DB& db, const LIST& params, IfcSpaceHeaterType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoilerType>(const DB& db, const LIST& params, IfcBoilerType* in)
+template <> size_t GenericFill<IfcSpaceProgram>(const DB& db, const LIST& params, IfcSpaceProgram* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConstructionEquipmentResource>(const DB& db, const LIST& params, IfcConstructionEquipmentResource* in)
+template <> size_t GenericFill<IfcSpatialStructureElementType>(const DB& db, const LIST& params, IfcSpatialStructureElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcComplexProperty>(const DB& db, const LIST& params, IfcComplexProperty* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcProperty*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcComplexProperty"); } do { // convert the 'UsageName' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->UsageName, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcComplexProperty to be a `IfcIdentifier`")); }
- } while(0);
- do { // convert the 'HasProperties' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->HasProperties, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcComplexProperty to be a `SET [1:?] OF IfcProperty`")); }
- } while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFooting>(const DB& db, const LIST& params, IfcFooting* in)
+template <> size_t GenericFill<IfcSpaceType>(const DB& db, const LIST& params, IfcSpaceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConstructionProductResource>(const DB& db, const LIST& params, IfcConstructionProductResource* in)
+template <> size_t GenericFill<IfcSphere>(const DB& db, const LIST& params, IfcSphere* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcCsgPrimitive3D*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDerivedProfileDef>(const DB& db, const LIST& params, IfcDerivedProfileDef* in)
+template <> size_t GenericFill<IfcStackTerminalType>(const DB& db, const LIST& params, IfcStackTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertyTableValue>(const DB& db, const LIST& params, IfcPropertyTableValue* in)
+template <> size_t GenericFill<IfcStair>(const DB& db, const LIST& params, IfcStair* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowMeterType>(const DB& db, const LIST& params, IfcFlowMeterType* in)
+template <> size_t GenericFill<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDoorStyle>(const DB& db, const LIST& params, IfcDoorStyle* in)
+template <> size_t GenericFill<IfcStairFlightType>(const DB& db, const LIST& params, IfcStairFlightType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* in)
+template <> size_t GenericFill<IfcStructuralActivity>(const DB& db, const LIST& params, IfcStructuralActivity* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcUnitAssignment"); } do { // convert the 'Units' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Units, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcUnitAssignment to be a `SET [1:?] OF IfcUnit`")); }
- } while(0);
- return base;
-}
-// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowTerminal>(const DB& db, const LIST& params, IfcFlowTerminal* in)
-{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCraneRailFShapeProfileDef>(const DB& db, const LIST& params, IfcCraneRailFShapeProfileDef* in)
+template <> size_t GenericFill<IfcStructuralAction>(const DB& db, const LIST& params, IfcStructuralAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralActivity*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFlowSegment>(const DB& db, const LIST& params, IfcFlowSegment* in)
+template <> size_t GenericFill<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcDistributionFlowElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSystem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElementQuantity>(const DB& db, const LIST& params, IfcElementQuantity* in)
+template <> size_t GenericFill<IfcStructuralItem>(const DB& db, const LIST& params, IfcStructuralItem* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
- if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcElementQuantity"); } do { // convert the 'MethodOfMeasurement' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->MethodOfMeasurement, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcElementQuantity to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'Quantities' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Quantities, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcElementQuantity to be a `SET [1:?] OF IfcPhysicalQuantity`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCurtainWall>(const DB& db, const LIST& params, IfcCurtainWall* in)
+template <> size_t GenericFill<IfcStructuralConnection>(const DB& db, const LIST& params, IfcStructuralConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDiscreteAccessory>(const DB& db, const LIST& params, IfcDiscreteAccessory* in)
+template <> size_t GenericFill<IfcStructuralCurveConnection>(const DB& db, const LIST& params, IfcStructuralCurveConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementComponent*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGrid>(const DB& db, const LIST& params, IfcGrid* in)
+template <> size_t GenericFill<IfcStructuralMember>(const DB& db, const LIST& params, IfcStructuralMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSanitaryTerminalType>(const DB& db, const LIST& params, IfcSanitaryTerminalType* in)
+template <> size_t GenericFill<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* in)
+template <> size_t GenericFill<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralCurveMember*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcFilterType>(const DB& db, const LIST& params, IfcFilterType* in)
+template <> size_t GenericFill<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowTreatmentDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTendon>(const DB& db, const LIST& params, IfcTendon* in)
+template <> size_t GenericFill<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralLinearAction*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcStructuralLoadGroup>(const DB& db, const LIST& params, IfcStructuralLoadGroup* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, const LIST& params, IfcPresentationStyleAssignment* in)
+template <> size_t GenericFill<IfcStructuralPlanarAction>(const DB& db, const LIST& params, IfcStructuralPlanarAction* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyleAssignment"); } do { // convert the 'Styles' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Styles, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyleAssignment to be a `SET [1:?] OF IfcPresentationStyleSelect`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralCurveMember>(const DB& db, const LIST& params, IfcStructuralCurveMember* in)
+template <> size_t GenericFill<IfcStructuralPlanarActionVarying>(const DB& db, const LIST& params, IfcStructuralPlanarActionVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralPlanarAction*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcLightSourceAmbient>(const DB& db, const LIST& params, IfcLightSourceAmbient* in)
+template <> size_t GenericFill<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLightSource*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCondition>(const DB& db, const LIST& params, IfcCondition* in)
+template <> size_t GenericFill<IfcStructuralPointConnection>(const DB& db, const LIST& params, IfcStructuralPointConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPort>(const DB& db, const LIST& params, IfcPort* in)
+template <> size_t GenericFill<IfcStructuralReaction>(const DB& db, const LIST& params, IfcStructuralReaction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProduct*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralActivity*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSpace* in)
+template <> size_t GenericFill<IfcStructuralPointReaction>(const DB& db, const LIST& params, IfcStructuralPointReaction* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
- if (params.GetSize() < 11) { throw STEP::TypeError("expected 11 arguments to IfcSpace"); } do { // convert the 'InteriorOrExteriorSpace' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->InteriorOrExteriorSpace, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSpace to be a `IfcInternalOrExternalEnum`")); }
- } while(0);
- do { // convert the 'ElevationWithFlooring' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ElevationWithFlooring, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSpace to be a `IfcLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralReaction*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcHeatExchangerType>(const DB& db, const LIST& params, IfcHeatExchangerType* in)
+template <> size_t GenericFill<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTankType>(const DB& db, const LIST& params, IfcTankType* in)
+template <> size_t GenericFill<IfcStructuralSurfaceConnection>(const DB& db, const LIST& params, IfcStructuralSurfaceConnection* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralConnection*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcInventory>(const DB& db, const LIST& params, IfcInventory* in)
+template <> size_t GenericFill<IfcStructuralSurfaceMember>(const DB& db, const LIST& params, IfcStructuralSurfaceMember* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralMember*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* in)
+template <> size_t GenericFill<IfcStructuralSurfaceMemberVarying>(const DB& db, const LIST& params, IfcStructuralSurfaceMemberVarying* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStructuralSurfaceMember*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAirToAirHeatRecoveryType>(const DB& db, const LIST& params, IfcAirToAirHeatRecoveryType* in)
+template <> size_t GenericFill<IfcStructuredDimensionCallout>(const DB& db, const LIST& params, IfcStructuredDimensionCallout* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDraughtingCallout*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStairFlight>(const DB& db, const LIST& params, IfcStairFlight* in)
+template <> size_t GenericFill<IfcStyleModel>(const DB& db, const LIST& params, IfcStyleModel* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcRepresentation*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricalElement>(const DB& db, const LIST& params, IfcElectricalElement* in)
+template <> size_t GenericFill<IfcStyledRepresentation>(const DB& db, const LIST& params, IfcStyledRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcStyleModel*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const LIST& params, IfcSurfaceStyleWithTextures* in)
+template <> size_t GenericFill<IfcSubContractResource>(const DB& db, const LIST& params, IfcSubContractResource* in)
{
- size_t base = 0;
- if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleWithTextures"); } do { // convert the 'Textures' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Textures, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleWithTextures to be a `LIST [1:?] OF IfcSurfaceTexture`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcConstructionResource*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params, IfcBoundingBox* in)
+template <> size_t GenericFill<IfcSubedge>(const DB& db, const LIST& params, IfcSubedge* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcBoundingBox"); } do { // convert the 'Corner' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Corner, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBoundingBox to be a `IfcCartesianPoint`")); }
- } while(0);
- do { // convert the 'XDim' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->XDim, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'YDim' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->YDim, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- do { // convert the 'ZDim' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ZDim, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcEdge*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWallType>(const DB& db, const LIST& params, IfcWallType* in)
+template <> size_t GenericFill<IfcSurfaceCurveSweptAreaSolid>(const DB& db, const LIST& params, IfcSurfaceCurveSweptAreaSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcMove>(const DB& db, const LIST& params, IfcMove* in)
+template <> size_t GenericFill<IfcSweptSurface>(const DB& db, const LIST& params, IfcSweptSurface* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTask*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSurface*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCircle>(const DB& db, const LIST& params, IfcCircle* in)
+template <> size_t GenericFill<IfcSurfaceOfLinearExtrusion>(const DB& db, const LIST& params, IfcSurfaceOfLinearExtrusion* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
- if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCircle"); } do { // convert the 'Radius' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Radius, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCircle to be a `IfcPositiveLengthMeasure`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOffsetCurve2D>(const DB& db, const LIST& params, IfcOffsetCurve2D* in)
+template <> size_t GenericFill<IfcSurfaceOfRevolution>(const DB& db, const LIST& params, IfcSurfaceOfRevolution* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcSweptSurface*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPointOnCurve>(const DB& db, const LIST& params, IfcPointOnCurve* in)
+template <> size_t GenericFill<IfcSurfaceStyle>(const DB& db, const LIST& params, IfcSurfaceStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcPresentationStyle*>(in));
+ if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcSurfaceStyle"); } do { // convert the 'Side' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Side, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyle to be a `IfcSurfaceSide`")); }
+ } while(0);
+ do { // convert the 'Styles' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Styles, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyle to be a `SET [1:5] OF IfcSurfaceStyleElementSelect`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralResultGroup>(const DB& db, const LIST& params, IfcStructuralResultGroup* in)
+template <> size_t GenericFill<IfcSurfaceStyleShading>(const DB& db, const LIST& params, IfcSurfaceStyleShading* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleShading"); } do { // convert the 'SurfaceColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::IfcSurfaceStyleShading,1>::aux_is_derived[0]=true; break; }
+ try { GenericConvert( in->SurfaceColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleShading to be a `IfcColourRgb`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSectionedSpine>(const DB& db, const LIST& params, IfcSectionedSpine* in)
+template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcSurfaceStyleShading*>(in));
+ if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcSurfaceStyleRendering"); } do { // convert the 'Transparency' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->Transparency, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyleRendering to be a `IfcNormalisedRatioMeasure`")); }
+ } while(0);
+ do { // convert the 'DiffuseColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->DiffuseColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
+ } while(0);
+ do { // convert the 'TransmissionColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->TransmissionColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
+ } while(0);
+ do { // convert the 'DiffuseTransmissionColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->DiffuseTransmissionColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
+ } while(0);
+ do { // convert the 'ReflectionColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->ReflectionColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
+ } while(0);
+ do { // convert the 'SpecularColour' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->SpecularColour, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
+ } while(0);
+ do { // convert the 'SpecularHighlight' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->SpecularHighlight, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSurfaceStyleRendering to be a `IfcSpecularHighlightSelect`")); }
+ } while(0);
+ do { // convert the 'ReflectanceMethod' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->ReflectanceMethod, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSurfaceStyleRendering to be a `IfcReflectanceMethodEnum`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSlab>(const DB& db, const LIST& params, IfcSlab* in)
+template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const LIST& params, IfcSurfaceStyleWithTextures* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleWithTextures"); } do { // convert the 'Textures' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Textures, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleWithTextures to be a `LIST [1:?] OF IfcSurfaceTexture`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVertex>(const DB& db, const LIST& params, IfcVertex* in)
+template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& params, IfcSweptDiskSolid* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcSweptDiskSolid"); } do { // convert the 'Directrix' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Directrix, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptDiskSolid to be a `IfcCurve`")); }
+ } while(0);
+ do { // convert the 'Radius' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Radius, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'InnerRadius' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ if (dynamic_cast<const UNSET*>(&*arg)) break;
+ try { GenericConvert( in->InnerRadius, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
+ } while(0);
+ do { // convert the 'StartParam' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->StartParam, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
+ } while(0);
+ do { // convert the 'EndParam' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->EndParam, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* in)
+template <> size_t GenericFill<IfcSwitchingDeviceType>(const DB& db, const LIST& params, IfcSwitchingDeviceType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcVertex*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralLinearAction>(const DB& db, const LIST& params, IfcStructuralLinearAction* in)
+template <> size_t GenericFill<IfcSystemFurnitureElementType>(const DB& db, const LIST& params, IfcSystemFurnitureElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFurnishingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralLinearActionVarying>(const DB& db, const LIST& params, IfcStructuralLinearActionVarying* in)
+template <> size_t GenericFill<IfcTShapeProfileDef>(const DB& db, const LIST& params, IfcTShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralLinearAction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBuildingElementProxyType>(const DB& db, const LIST& params, IfcBuildingElementProxyType* in)
+template <> size_t GenericFill<IfcTankType>(const DB& db, const LIST& params, IfcTankType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowStorageDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProjectionElement>(const DB& db, const LIST& params, IfcProjectionElement* in)
+template <> size_t GenericFill<IfcTendon>(const DB& db, const LIST& params, IfcTendon* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFeatureElementAddition*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST& params, IfcConversionBasedUnit* in)
+template <> size_t GenericFill<IfcTendonAnchor>(const DB& db, const LIST& params, IfcTendonAnchor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
- if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcConversionBasedUnit"); } do { // convert the 'Name' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->Name, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcConversionBasedUnit to be a `IfcLabel`")); }
- } while(0);
- do { // convert the 'ConversionFactor' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ConversionFactor, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcConversionBasedUnit to be a `IfcMeasureWithUnit`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcReinforcingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcGeometricRepresentationSubContext>(const DB& db, const LIST& params, IfcGeometricRepresentationSubContext* in)
+template <> size_t GenericFill<IfcTextLiteral>(const DB& db, const LIST& params, IfcTextLiteral* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationContext*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationSurfaceOccurrence>(const DB& db, const LIST& params, IfcAnnotationSurfaceOccurrence* in)
+template <> size_t GenericFill<IfcTextLiteralWithExtent>(const DB& db, const LIST& params, IfcTextLiteralWithExtent* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTextLiteral*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRoundedEdgeFeature>(const DB& db, const LIST& params, IfcRoundedEdgeFeature* in)
+template <> size_t GenericFill<IfcTimeSeriesSchedule>(const DB& db, const LIST& params, IfcTimeSeriesSchedule* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcEdgeFeature*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricDistributionPoint>(const DB& db, const LIST& params, IfcElectricDistributionPoint* in)
+template <> size_t GenericFill<IfcTopologyRepresentation>(const DB& db, const LIST& params, IfcTopologyRepresentation* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowController*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcShapeModel*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCableCarrierSegmentType>(const DB& db, const LIST& params, IfcCableCarrierSegmentType* in)
+template <> size_t GenericFill<IfcTransformerType>(const DB& db, const LIST& params, IfcTransformerType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWallStandardCase>(const DB& db, const LIST& params, IfcWallStandardCase* in)
+template <> size_t GenericFill<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWall*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcCsgSolid>(const DB& db, const LIST& params, IfcCsgSolid* in)
+template <> size_t GenericFill<IfcTransportElementType>(const DB& db, const LIST& params, IfcTransportElementType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcBeamType>(const DB& db, const LIST& params, IfcBeamType* in)
+template <> size_t GenericFill<IfcTrapeziumProfileDef>(const DB& db, const LIST& params, IfcTrapeziumProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationFillArea>(const DB& db, const LIST& params, IfcAnnotationFillArea* in)
+template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params, IfcTrimmedCurve* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
+ if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcTrimmedCurve"); } do { // convert the 'BasisCurve' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->BasisCurve, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcTrimmedCurve to be a `IfcCurve`")); }
+ } while(0);
+ do { // convert the 'Trim1' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Trim1, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
+ } while(0);
+ do { // convert the 'Trim2' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Trim2, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
+ } while(0);
+ do { // convert the 'SenseAgreement' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->SenseAgreement, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcTrimmedCurve to be a `BOOLEAN`")); }
+ } while(0);
+ do { // convert the 'MasterRepresentation' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->MasterRepresentation, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcTrimmedCurve to be a `IfcTrimmingPreference`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralCurveMemberVarying>(const DB& db, const LIST& params, IfcStructuralCurveMemberVarying* in)
+template <> size_t GenericFill<IfcTubeBundleType>(const DB& db, const LIST& params, IfcTubeBundleType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralCurveMember*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPointOnSurface>(const DB& db, const LIST& params, IfcPointOnSurface* in)
+template <> size_t GenericFill<IfcTwoDirectionRepeatFactor>(const DB& db, const LIST& params, IfcTwoDirectionRepeatFactor* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcOneDirectionRepeatFactor*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcOrderAction>(const DB& db, const LIST& params, IfcOrderAction* in)
+template <> size_t GenericFill<IfcUShapeProfileDef>(const DB& db, const LIST& params, IfcUShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcTask*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEdgeLoop>(const DB& db, const LIST& params, IfcEdgeLoop* in)
+template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& params, IfcUnitAssignment* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
-// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ size_t base = 0;
+ if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcUnitAssignment"); } do { // convert the 'Units' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Units, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcUnitAssignment to be a `SET [1:?] OF IfcUnit`")); }
+ } while(0);
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationFillAreaOccurrence>(const DB& db, const LIST& params, IfcAnnotationFillAreaOccurrence* in)
+template <> size_t GenericFill<IfcUnitaryEquipmentType>(const DB& db, const LIST& params, IfcUnitaryEquipmentType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcEnergyConversionDeviceType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcWorkPlan>(const DB& db, const LIST& params, IfcWorkPlan* in)
+template <> size_t GenericFill<IfcValveType>(const DB& db, const LIST& params, IfcValveType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcFlowControllerType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcEllipse>(const DB& db, const LIST& params, IfcEllipse* in)
+template <> size_t GenericFill<IfcVector>(const DB& db, const LIST& params, IfcVector* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
- if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcEllipse"); } do { // convert the 'SemiAxis1' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SemiAxis1, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
+ size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
+ if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcVector"); } do { // convert the 'Orientation' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Orientation, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcVector to be a `IfcDirection`")); }
} while(0);
- do { // convert the 'SemiAxis2' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->SemiAxis2, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
+ do { // convert the 'Magnitude' argument
+ std::shared_ptr<const DataType> arg = params[base++];
+ try { GenericConvert( in->Magnitude, arg, db ); break; }
+ catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcVector to be a `IfcLengthMeasure`")); }
} while(0);
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProductDefinitionShape>(const DB& db, const LIST& params, IfcProductDefinitionShape* in)
+template <> size_t GenericFill<IfcVertex>(const DB& db, const LIST& params, IfcVertex* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcProductRepresentation*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTopologicalRepresentationItem*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcProjectionCurve>(const DB& db, const LIST& params, IfcProjectionCurve* in)
+template <> size_t GenericFill<IfcVertexLoop>(const DB& db, const LIST& params, IfcVertexLoop* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationCurveOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcElectricalCircuit>(const DB& db, const LIST& params, IfcElectricalCircuit* in)
+template <> size_t GenericFill<IfcVertexPoint>(const DB& db, const LIST& params, IfcVertexPoint* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSystem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcVertex*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcRationalBezierCurve>(const DB& db, const LIST& params, IfcRationalBezierCurve* in)
+template <> size_t GenericFill<IfcVibrationIsolatorType>(const DB& db, const LIST& params, IfcVibrationIsolatorType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcBezierCurve*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcDiscreteAccessoryType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralPointAction>(const DB& db, const LIST& params, IfcStructuralPointAction* in)
+template <> size_t GenericFill<IfcVirtualElement>(const DB& db, const LIST& params, IfcVirtualElement* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcStructuralAction*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPipeSegmentType>(const DB& db, const LIST& params, IfcPipeSegmentType* in)
+template <> size_t GenericFill<IfcWall>(const DB& db, const LIST& params, IfcWall* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowSegmentType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTwoDirectionRepeatFactor>(const DB& db, const LIST& params, IfcTwoDirectionRepeatFactor* in)
+template <> size_t GenericFill<IfcWallStandardCase>(const DB& db, const LIST& params, IfcWallStandardCase* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcOneDirectionRepeatFactor*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcWall*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcShapeRepresentation>(const DB& db, const LIST& params, IfcShapeRepresentation* in)
+template <> size_t GenericFill<IfcWallType>(const DB& db, const LIST& params, IfcWallType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcShapeModel*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElementType*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params, IfcPropertySet* in)
+template <> size_t GenericFill<IfcWasteTerminalType>(const DB& db, const LIST& params, IfcWasteTerminalType* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
- if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcPropertySet"); } do { // convert the 'HasProperties' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->HasProperties, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcPropertySet to be a `SET [1:?] OF IfcProperty`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcFlowTerminalType*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIST& params, IfcSurfaceStyleRendering* in)
+template <> size_t GenericFill<IfcWindow>(const DB& db, const LIST& params, IfcWindow* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSurfaceStyleShading*>(in));
- if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcSurfaceStyleRendering"); } do { // convert the 'Transparency' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->Transparency, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyleRendering to be a `IfcNormalisedRatioMeasure`")); }
- } while(0);
- do { // convert the 'DiffuseColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->DiffuseColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
- } while(0);
- do { // convert the 'TransmissionColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->TransmissionColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
- } while(0);
- do { // convert the 'DiffuseTransmissionColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->DiffuseTransmissionColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
- } while(0);
- do { // convert the 'ReflectionColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->ReflectionColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
- } while(0);
- do { // convert the 'SpecularColour' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->SpecularColour, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
- } while(0);
- do { // convert the 'SpecularHighlight' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- if (dynamic_cast<const UNSET*>(&*arg)) break;
- try { GenericConvert( in->SpecularHighlight, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSurfaceStyleRendering to be a `IfcSpecularHighlightSelect`")); }
- } while(0);
- do { // convert the 'ReflectanceMethod' argument
- boost::shared_ptr<const DataType> arg = params[base++];
- try { GenericConvert( in->ReflectanceMethod, arg, db ); break; }
- catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSurfaceStyleRendering to be a `IfcReflectanceMethodEnum`")); }
- } while(0);
- return base;
+ size_t base = GenericFill(db,params,static_cast<IfcBuildingElement*>(in));
+// this data structure is not used yet, so there is no code generated to fill its members
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcDistributionPort>(const DB& db, const LIST& params, IfcDistributionPort* in)
+template <> size_t GenericFill<IfcWindowStyle>(const DB& db, const LIST& params, IfcWindowStyle* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcPort*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcTypeProduct*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcPipeFittingType>(const DB& db, const LIST& params, IfcPipeFittingType* in)
+template <> size_t GenericFill<IfcWorkControl>(const DB& db, const LIST& params, IfcWorkControl* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcFlowFittingType*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcTransportElement>(const DB& db, const LIST& params, IfcTransportElement* in)
+template <> size_t GenericFill<IfcWorkPlan>(const DB& db, const LIST& params, IfcWorkPlan* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcElement*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcAnnotationTextOccurrence>(const DB& db, const LIST& params, IfcAnnotationTextOccurrence* in)
+template <> size_t GenericFill<IfcWorkSchedule>(const DB& db, const LIST& params, IfcWorkSchedule* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcAnnotationOccurrence*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcWorkControl*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcStructuralAnalysisModel>(const DB& db, const LIST& params, IfcStructuralAnalysisModel* in)
+template <> size_t GenericFill<IfcZShapeProfileDef>(const DB& db, const LIST& params, IfcZShapeProfileDef* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcSystem*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcParameterizedProfileDef*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
// -----------------------------------------------------------------------------------------------------------
-template <> size_t GenericFill<IfcConditionCriterion>(const DB& db, const LIST& params, IfcConditionCriterion* in)
+template <> size_t GenericFill<IfcZone>(const DB& db, const LIST& params, IfcZone* in)
{
- size_t base = GenericFill(db,params,static_cast<IfcControl*>(in));
+ size_t base = GenericFill(db,params,static_cast<IfcGroup*>(in));
// this data structure is not used yet, so there is no code generated to fill its members
- return base;
+ return base;
}
} // ! STEP
diff --git a/src/3rdparty/assimp/code/IFCUtil.cpp b/src/3rdparty/assimp/code/IFCUtil.cpp
index d28f91a10..89a6c78c5 100644
--- a/src/3rdparty/assimp/code/IFCUtil.cpp
+++ b/src/3rdparty/assimp/code/IFCUtil.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,532 +42,661 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of conversion routines for some common Ifc helper entities.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
#include "IFCUtil.h"
#include "PolyTools.h"
#include "ProcessHelper.h"
+#include "Defines.h"
namespace Assimp {
- namespace IFC {
+ namespace IFC {
// ------------------------------------------------------------------------------------------------
-void TempOpening::Transform(const IfcMatrix4& mat)
+void TempOpening::Transform(const IfcMatrix4& mat)
{
- if(profileMesh) {
- profileMesh->Transform(mat);
- }
- if(profileMesh2D) {
- profileMesh2D->Transform(mat);
- }
- extrusionDir *= IfcMatrix3(mat);
+ if(profileMesh) {
+ profileMesh->Transform(mat);
+ }
+ if(profileMesh2D) {
+ profileMesh2D->Transform(mat);
+ }
+ extrusionDir *= IfcMatrix3(mat);
}
// ------------------------------------------------------------------------------------------------
-aiMesh* TempMesh::ToMesh()
+aiMesh* TempMesh::ToMesh()
{
- ai_assert(verts.size() == std::accumulate(vertcnt.begin(),vertcnt.end(),size_t(0)));
+ ai_assert(verts.size() == std::accumulate(vertcnt.begin(),vertcnt.end(),size_t(0)));
- if (verts.empty()) {
- return NULL;
- }
+ if (verts.empty()) {
+ return NULL;
+ }
- std::auto_ptr<aiMesh> mesh(new aiMesh());
+ std::unique_ptr<aiMesh> mesh(new aiMesh());
- // copy vertices
- mesh->mNumVertices = static_cast<unsigned int>(verts.size());
- mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- std::copy(verts.begin(),verts.end(),mesh->mVertices);
+ // copy vertices
+ mesh->mNumVertices = static_cast<unsigned int>(verts.size());
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ std::copy(verts.begin(),verts.end(),mesh->mVertices);
- // and build up faces
- mesh->mNumFaces = static_cast<unsigned int>(vertcnt.size());
- mesh->mFaces = new aiFace[mesh->mNumFaces];
+ // and build up faces
+ mesh->mNumFaces = static_cast<unsigned int>(vertcnt.size());
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
- for(unsigned int i = 0,n=0, acc = 0; i < mesh->mNumFaces; ++n) {
- aiFace& f = mesh->mFaces[i];
- if (!vertcnt[n]) {
- --mesh->mNumFaces;
- continue;
- }
+ for(unsigned int i = 0,n=0, acc = 0; i < mesh->mNumFaces; ++n) {
+ aiFace& f = mesh->mFaces[i];
+ if (!vertcnt[n]) {
+ --mesh->mNumFaces;
+ continue;
+ }
- f.mNumIndices = vertcnt[n];
- f.mIndices = new unsigned int[f.mNumIndices];
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- f.mIndices[a] = acc++;
- }
+ f.mNumIndices = vertcnt[n];
+ f.mIndices = new unsigned int[f.mNumIndices];
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ f.mIndices[a] = acc++;
+ }
- ++i;
- }
+ ++i;
+ }
- return mesh.release();
+ return mesh.release();
}
// ------------------------------------------------------------------------------------------------
void TempMesh::Clear()
{
- verts.clear();
- vertcnt.clear();
+ verts.clear();
+ vertcnt.clear();
}
// ------------------------------------------------------------------------------------------------
-void TempMesh::Transform(const IfcMatrix4& mat)
+void TempMesh::Transform(const IfcMatrix4& mat)
{
- BOOST_FOREACH(IfcVector3& v, verts) {
- v *= mat;
- }
+ for(IfcVector3& v : verts) {
+ v *= mat;
+ }
}
// ------------------------------------------------------------------------------
IfcVector3 TempMesh::Center() const
{
- return std::accumulate(verts.begin(),verts.end(),IfcVector3()) / static_cast<IfcFloat>(verts.size());
+ return (verts.size() == 0) ? IfcVector3(0.0f, 0.0f, 0.0f) : (std::accumulate(verts.begin(),verts.end(),IfcVector3()) / static_cast<IfcFloat>(verts.size()));
}
// ------------------------------------------------------------------------------------------------
void TempMesh::Append(const TempMesh& other)
{
- verts.insert(verts.end(),other.verts.begin(),other.verts.end());
- vertcnt.insert(vertcnt.end(),other.vertcnt.begin(),other.vertcnt.end());
+ verts.insert(verts.end(),other.verts.begin(),other.verts.end());
+ vertcnt.insert(vertcnt.end(),other.vertcnt.begin(),other.vertcnt.end());
}
// ------------------------------------------------------------------------------------------------
void TempMesh::RemoveDegenerates()
{
- // The strategy is simple: walk the mesh and compute normals using
- // Newell's algorithm. The length of the normals gives the area
- // of the polygons, which is close to zero for lines.
-
- std::vector<IfcVector3> normals;
- ComputePolygonNormals(normals, false);
-
- bool drop = false;
- size_t inor = 0;
-
- std::vector<IfcVector3>::iterator vit = verts.begin();
- for (std::vector<unsigned int>::iterator it = vertcnt.begin(); it != vertcnt.end(); ++inor) {
- const unsigned int pcount = *it;
-
- if (normals[inor].SquareLength() < 1e-5f) {
- it = vertcnt.erase(it);
- vit = verts.erase(vit, vit + pcount);
-
- drop = true;
- continue;
- }
-
- vit += pcount;
- ++it;
- }
-
- if(drop) {
- IFCImporter::LogDebug("removing degenerate faces");
- }
+ // The strategy is simple: walk the mesh and compute normals using
+ // Newell's algorithm. The length of the normals gives the area
+ // of the polygons, which is close to zero for lines.
+
+ std::vector<IfcVector3> normals;
+ ComputePolygonNormals(normals, false);
+
+ bool drop = false;
+ size_t inor = 0;
+
+ std::vector<IfcVector3>::iterator vit = verts.begin();
+ for (std::vector<unsigned int>::iterator it = vertcnt.begin(); it != vertcnt.end(); ++inor) {
+ const unsigned int pcount = *it;
+
+ if (normals[inor].SquareLength() < 1e-10f) {
+ it = vertcnt.erase(it);
+ vit = verts.erase(vit, vit + pcount);
+
+ drop = true;
+ continue;
+ }
+
+ vit += pcount;
+ ++it;
+ }
+
+ if(drop) {
+ IFCImporter::LogDebug("removing degenerate faces");
+ }
}
// ------------------------------------------------------------------------------------------------
-void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
- bool normalize,
- size_t ofs) const
+IfcVector3 TempMesh::ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize)
{
- size_t max_vcount = 0;
- std::vector<unsigned int>::const_iterator begin = vertcnt.begin()+ofs, end = vertcnt.end(), iit;
- for(iit = begin; iit != end; ++iit) {
- max_vcount = std::max(max_vcount,static_cast<size_t>(*iit));
- }
-
- std::vector<IfcFloat> temp((max_vcount+2)*4);
- normals.reserve( normals.size() + vertcnt.size()-ofs );
-
- // `NewellNormal()` currently has a relatively strange interface and need to
- // re-structure things a bit to meet them.
- size_t vidx = std::accumulate(vertcnt.begin(),begin,0);
- for(iit = begin; iit != end; vidx += *iit++) {
- if (!*iit) {
- normals.push_back(IfcVector3());
- continue;
- }
- for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
- const IfcVector3& v = verts[vidx+vofs];
- temp[cnt++] = v.x;
- temp[cnt++] = v.y;
- temp[cnt++] = v.z;
+ std::vector<IfcFloat> temp((cnt+2)*3);
+ for( size_t vofs = 0, i = 0; vofs < cnt; ++vofs )
+ {
+ const IfcVector3& v = vtcs[vofs];
+ temp[i++] = v.x;
+ temp[i++] = v.y;
+ temp[i++] = v.z;
+ }
+
+ IfcVector3 nor;
+ NewellNormal<3, 3, 3>(nor, cnt, &temp[0], &temp[1], &temp[2]);
+ return normalize ? nor.Normalize() : nor;
+}
+
+// ------------------------------------------------------------------------------------------------
+void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
+ bool normalize,
+ size_t ofs) const
+{
+ size_t max_vcount = 0;
+ std::vector<unsigned int>::const_iterator begin = vertcnt.begin()+ofs, end = vertcnt.end(), iit;
+ for(iit = begin; iit != end; ++iit) {
+ max_vcount = std::max(max_vcount,static_cast<size_t>(*iit));
+ }
+
+ std::vector<IfcFloat> temp((max_vcount+2)*4);
+ normals.reserve( normals.size() + vertcnt.size()-ofs );
+
+ // `NewellNormal()` currently has a relatively strange interface and need to
+ // re-structure things a bit to meet them.
+ size_t vidx = std::accumulate(vertcnt.begin(),begin,0);
+ for(iit = begin; iit != end; vidx += *iit++) {
+ if (!*iit) {
+ normals.push_back(IfcVector3());
+ continue;
+ }
+ for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
+ const IfcVector3& v = verts[vidx+vofs];
+ temp[cnt++] = v.x;
+ temp[cnt++] = v.y;
+ temp[cnt++] = v.z;
#ifdef ASSIMP_BUILD_DEBUG
- temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN();
+ temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN();
#endif
- ++cnt;
- }
-
- normals.push_back(IfcVector3());
- NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
- }
-
- if(normalize) {
- BOOST_FOREACH(IfcVector3& n, normals) {
- n.Normalize();
- }
- }
+ ++cnt;
+ }
+
+ normals.push_back(IfcVector3());
+ NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
+ }
+
+ if(normalize) {
+ for(IfcVector3& n : normals) {
+ n.Normalize();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Compute the normal of the last polygon in the given mesh
IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const
{
- size_t total = vertcnt.back(), vidx = verts.size() - total;
- std::vector<IfcFloat> temp((total+2)*3);
- for(size_t vofs = 0, cnt = 0; vofs < total; ++vofs) {
- const IfcVector3& v = verts[vidx+vofs];
- temp[cnt++] = v.x;
- temp[cnt++] = v.y;
- temp[cnt++] = v.z;
- }
- IfcVector3 nor;
- NewellNormal<3,3,3>(nor,total,&temp[0],&temp[1],&temp[2]);
- return normalize ? nor.Normalize() : nor;
+ return ComputePolygonNormal(&verts[verts.size() - vertcnt.back()], vertcnt.back(), normalize);
}
+struct CompareVector
+{
+ bool operator () (const IfcVector3& a, const IfcVector3& b) const
+ {
+ IfcVector3 d = a - b;
+ IfcFloat eps = 1e-6;
+ return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
+ }
+};
+struct FindVector
+{
+ IfcVector3 v;
+ FindVector(const IfcVector3& p) : v(p) { }
+ bool operator () (const IfcVector3& p) { return FuzzyVectorCompare(1e-6)(p, v); }
+};
+
// ------------------------------------------------------------------------------------------------
void TempMesh::FixupFaceOrientation()
{
- const IfcVector3 vavg = Center();
-
- std::vector<IfcVector3> normals;
- ComputePolygonNormals(normals);
-
- size_t c = 0, ofs = 0;
- BOOST_FOREACH(unsigned int cnt, vertcnt) {
- if (cnt>2){
- const IfcVector3& thisvert = verts[c];
- if (normals[ofs]*(thisvert-vavg) < 0) {
- std::reverse(verts.begin()+c,verts.begin()+cnt+c);
- }
- }
- c += cnt;
- ++ofs;
- }
+ const IfcVector3 vavg = Center();
+
+ // create a list of start indices for all faces to allow random access to faces
+ std::vector<size_t> faceStartIndices(vertcnt.size());
+ for( size_t i = 0, a = 0; a < vertcnt.size(); i += vertcnt[a], ++a )
+ faceStartIndices[a] = i;
+
+ // list all faces on a vertex
+ std::map<IfcVector3, std::vector<size_t>, CompareVector> facesByVertex;
+ for( size_t a = 0; a < vertcnt.size(); ++a )
+ {
+ for( size_t b = 0; b < vertcnt[a]; ++b )
+ facesByVertex[verts[faceStartIndices[a] + b]].push_back(a);
+ }
+ // determine neighbourhood for all polys
+ std::vector<size_t> neighbour(verts.size(), SIZE_MAX);
+ std::vector<size_t> tempIntersect(10);
+ for( size_t a = 0; a < vertcnt.size(); ++a )
+ {
+ for( size_t b = 0; b < vertcnt[a]; ++b )
+ {
+ size_t ib = faceStartIndices[a] + b, nib = faceStartIndices[a] + (b + 1) % vertcnt[a];
+ const std::vector<size_t>& facesOnB = facesByVertex[verts[ib]];
+ const std::vector<size_t>& facesOnNB = facesByVertex[verts[nib]];
+ // there should be exactly one or two faces which appear in both lists. Our face and the other side
+ std::vector<size_t>::iterator sectstart = tempIntersect.begin();
+ std::vector<size_t>::iterator sectend = std::set_intersection(
+ facesOnB.begin(), facesOnB.end(), facesOnNB.begin(), facesOnNB.end(), sectstart);
+
+ if( std::distance(sectstart, sectend) != 2 )
+ continue;
+ if( *sectstart == a )
+ ++sectstart;
+ neighbour[ib] = *sectstart;
+ }
+ }
+
+ // now we're getting started. We take the face which is the farthest away from the center. This face is most probably
+ // facing outwards. So we reverse this face to point outwards in relation to the center. Then we adapt neighbouring
+ // faces to have the same winding until all faces have been tested.
+ std::vector<bool> faceDone(vertcnt.size(), false);
+ while( std::count(faceDone.begin(), faceDone.end(), false) != 0 )
+ {
+ // find the farthest of the remaining faces
+ size_t farthestIndex = SIZE_MAX;
+ IfcFloat farthestDistance = -1.0;
+ for( size_t a = 0; a < vertcnt.size(); ++a )
+ {
+ if( faceDone[a] )
+ continue;
+ IfcVector3 faceCenter = std::accumulate(verts.begin() + faceStartIndices[a],
+ verts.begin() + faceStartIndices[a] + vertcnt[a], IfcVector3(0.0)) / IfcFloat(vertcnt[a]);
+ IfcFloat dst = (faceCenter - vavg).SquareLength();
+ if( dst > farthestDistance ) { farthestDistance = dst; farthestIndex = a; }
+ }
+
+ // calculate its normal and reverse the poly if its facing towards the mesh center
+ IfcVector3 farthestNormal = ComputePolygonNormal(verts.data() + faceStartIndices[farthestIndex], vertcnt[farthestIndex]);
+ IfcVector3 farthestCenter = std::accumulate(verts.begin() + faceStartIndices[farthestIndex],
+ verts.begin() + faceStartIndices[farthestIndex] + vertcnt[farthestIndex], IfcVector3(0.0))
+ / IfcFloat(vertcnt[farthestIndex]);
+ // We accapt a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
+ // the file.
+ if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
+ {
+ size_t fsi = faceStartIndices[farthestIndex], fvc = vertcnt[farthestIndex];
+ std::reverse(verts.begin() + fsi, verts.begin() + fsi + fvc);
+ std::reverse(neighbour.begin() + fsi, neighbour.begin() + fsi + fvc);
+ // because of the neighbour index belonging to the edge starting with the point at the same index, we need to
+ // cycle the neighbours through to match the edges again.
+ // Before: points A - B - C - D with edge neighbour p - q - r - s
+ // After: points D - C - B - A, reversed neighbours are s - r - q - p, but the should be
+ // r q p s
+ for( size_t a = 0; a < fvc - 1; ++a )
+ std::swap(neighbour[fsi + a], neighbour[fsi + a + 1]);
+ }
+ faceDone[farthestIndex] = true;
+ std::vector<size_t> todo;
+ todo.push_back(farthestIndex);
+
+ // go over its neighbour faces recursively and adapt their winding order to match the farthest face
+ while( !todo.empty() )
+ {
+ size_t tdf = todo.back();
+ size_t vsi = faceStartIndices[tdf], vc = vertcnt[tdf];
+ todo.pop_back();
+
+ // check its neighbours
+ for( size_t a = 0; a < vc; ++a )
+ {
+ // ignore neighbours if we already checked them
+ size_t nbi = neighbour[vsi + a];
+ if( nbi == SIZE_MAX || faceDone[nbi] )
+ continue;
+
+ const IfcVector3& vp = verts[vsi + a];
+ size_t nbvsi = faceStartIndices[nbi], nbvc = vertcnt[nbi];
+ std::vector<IfcVector3>::iterator it = std::find_if(verts.begin() + nbvsi, verts.begin() + nbvsi + nbvc, FindVector(vp));
+ ai_assert(it != verts.begin() + nbvsi + nbvc);
+ size_t nb_vidx = std::distance(verts.begin() + nbvsi, it);
+ // two faces winded in the same direction should have a crossed edge, where one face has p0->p1 and the other
+ // has p1'->p0'. If the next point on the neighbouring face is also the next on the current face, we need
+ // to reverse the neighbour
+ nb_vidx = (nb_vidx + 1) % nbvc;
+ size_t oursideidx = (a + 1) % vc;
+ if( FuzzyVectorCompare(1e-6)(verts[vsi + oursideidx], verts[nbvsi + nb_vidx]) )
+ {
+ std::reverse(verts.begin() + nbvsi, verts.begin() + nbvsi + nbvc);
+ std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc);
+ for( size_t a = 0; a < nbvc - 1; ++a )
+ std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]);
+ }
+
+ // either way we're done with the neighbour. Mark it as done and continue checking from there recursively
+ faceDone[nbi] = true;
+ todo.push_back(nbi);
+ }
+ }
+
+ // no more faces reachable from this part of the surface, start over with a disjunct part and its farthest face
+ }
}
// ------------------------------------------------------------------------------------------------
-void TempMesh::RemoveAdjacentDuplicates()
+void TempMesh::RemoveAdjacentDuplicates()
{
- bool drop = false;
- std::vector<IfcVector3>::iterator base = verts.begin();
- BOOST_FOREACH(unsigned int& cnt, vertcnt) {
- if (cnt < 2){
- base += cnt;
- continue;
- }
-
- IfcVector3 vmin,vmax;
- ArrayBounds(&*base, cnt ,vmin,vmax);
-
-
- const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
- //const IfcFloat dotepsilon = 1e-9;
-
- //// look for vertices that lie directly on the line between their predecessor and their
- //// successor and replace them with either of them.
-
- //for(size_t i = 0; i < cnt; ++i) {
- // IfcVector3& v1 = *(base+i), &v0 = *(base+(i?i-1:cnt-1)), &v2 = *(base+(i+1)%cnt);
- // const IfcVector3& d0 = (v1-v0), &d1 = (v2-v1);
- // const IfcFloat l0 = d0.SquareLength(), l1 = d1.SquareLength();
- // if (!l0 || !l1) {
- // continue;
- // }
-
- // const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
-
- // if ( d >= 1.f-dotepsilon ) {
- // v1 = v0;
- // }
- // else if ( d < -1.f+dotepsilon ) {
- // v2 = v1;
- // continue;
- // }
- //}
-
- // drop any identical, adjacent vertices. this pass will collect the dropouts
- // of the previous pass as a side-effect.
- FuzzyVectorCompare fz(epsilon);
- std::vector<IfcVector3>::iterator end = base+cnt, e = std::unique( base, end, fz );
- if (e != end) {
- cnt -= static_cast<unsigned int>(std::distance(e, end));
- verts.erase(e,end);
- drop = true;
- }
-
- // check front and back vertices for this polygon
- if (cnt > 1 && fz(*base,*(base+cnt-1))) {
- verts.erase(base+ --cnt);
- drop = true;
- }
-
- // removing adjacent duplicates shouldn't erase everything :-)
- ai_assert(cnt>0);
- base += cnt;
- }
- if(drop) {
- IFCImporter::LogDebug("removing duplicate vertices");
- }
+ bool drop = false;
+ std::vector<IfcVector3>::iterator base = verts.begin();
+ for(unsigned int& cnt : vertcnt) {
+ if (cnt < 2){
+ base += cnt;
+ continue;
+ }
+
+ IfcVector3 vmin,vmax;
+ ArrayBounds(&*base, cnt ,vmin,vmax);
+
+
+ const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9);
+ //const IfcFloat dotepsilon = 1e-9;
+
+ //// look for vertices that lie directly on the line between their predecessor and their
+ //// successor and replace them with either of them.
+
+ //for(size_t i = 0; i < cnt; ++i) {
+ // IfcVector3& v1 = *(base+i), &v0 = *(base+(i?i-1:cnt-1)), &v2 = *(base+(i+1)%cnt);
+ // const IfcVector3& d0 = (v1-v0), &d1 = (v2-v1);
+ // const IfcFloat l0 = d0.SquareLength(), l1 = d1.SquareLength();
+ // if (!l0 || !l1) {
+ // continue;
+ // }
+
+ // const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
+
+ // if ( d >= 1.f-dotepsilon ) {
+ // v1 = v0;
+ // }
+ // else if ( d < -1.f+dotepsilon ) {
+ // v2 = v1;
+ // continue;
+ // }
+ //}
+
+ // drop any identical, adjacent vertices. this pass will collect the dropouts
+ // of the previous pass as a side-effect.
+ FuzzyVectorCompare fz(epsilon);
+ std::vector<IfcVector3>::iterator end = base+cnt, e = std::unique( base, end, fz );
+ if (e != end) {
+ cnt -= static_cast<unsigned int>(std::distance(e, end));
+ verts.erase(e,end);
+ drop = true;
+ }
+
+ // check front and back vertices for this polygon
+ if (cnt > 1 && fz(*base,*(base+cnt-1))) {
+ verts.erase(base+ --cnt);
+ drop = true;
+ }
+
+ // removing adjacent duplicates shouldn't erase everything :-)
+ ai_assert(cnt>0);
+ base += cnt;
+ }
+ if(drop) {
+ IFCImporter::LogDebug("removing duplicate vertices");
+ }
}
// ------------------------------------------------------------------------------------------------
void TempMesh::Swap(TempMesh& other)
{
- vertcnt.swap(other.vertcnt);
- verts.swap(other.verts);
+ vertcnt.swap(other.vertcnt);
+ verts.swap(other.verts);
}
// ------------------------------------------------------------------------------------------------
bool IsTrue(const EXPRESS::BOOLEAN& in)
{
- return (std::string)in == "TRUE" || (std::string)in == "T";
+ return (std::string)in == "TRUE" || (std::string)in == "T";
}
// ------------------------------------------------------------------------------------------------
IfcFloat ConvertSIPrefix(const std::string& prefix)
{
- if (prefix == "EXA") {
- return 1e18f;
- }
- else if (prefix == "PETA") {
- return 1e15f;
- }
- else if (prefix == "TERA") {
- return 1e12f;
- }
- else if (prefix == "GIGA") {
- return 1e9f;
- }
- else if (prefix == "MEGA") {
- return 1e6f;
- }
- else if (prefix == "KILO") {
- return 1e3f;
- }
- else if (prefix == "HECTO") {
- return 1e2f;
- }
- else if (prefix == "DECA") {
- return 1e-0f;
- }
- else if (prefix == "DECI") {
- return 1e-1f;
- }
- else if (prefix == "CENTI") {
- return 1e-2f;
- }
- else if (prefix == "MILLI") {
- return 1e-3f;
- }
- else if (prefix == "MICRO") {
- return 1e-6f;
- }
- else if (prefix == "NANO") {
- return 1e-9f;
- }
- else if (prefix == "PICO") {
- return 1e-12f;
- }
- else if (prefix == "FEMTO") {
- return 1e-15f;
- }
- else if (prefix == "ATTO") {
- return 1e-18f;
- }
- else {
- IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
- return 1;
- }
+ if (prefix == "EXA") {
+ return 1e18f;
+ }
+ else if (prefix == "PETA") {
+ return 1e15f;
+ }
+ else if (prefix == "TERA") {
+ return 1e12f;
+ }
+ else if (prefix == "GIGA") {
+ return 1e9f;
+ }
+ else if (prefix == "MEGA") {
+ return 1e6f;
+ }
+ else if (prefix == "KILO") {
+ return 1e3f;
+ }
+ else if (prefix == "HECTO") {
+ return 1e2f;
+ }
+ else if (prefix == "DECA") {
+ return 1e-0f;
+ }
+ else if (prefix == "DECI") {
+ return 1e-1f;
+ }
+ else if (prefix == "CENTI") {
+ return 1e-2f;
+ }
+ else if (prefix == "MILLI") {
+ return 1e-3f;
+ }
+ else if (prefix == "MICRO") {
+ return 1e-6f;
+ }
+ else if (prefix == "NANO") {
+ return 1e-9f;
+ }
+ else if (prefix == "PICO") {
+ return 1e-12f;
+ }
+ else if (prefix == "FEMTO") {
+ return 1e-15f;
+ }
+ else if (prefix == "ATTO") {
+ return 1e-18f;
+ }
+ else {
+ IFCImporter::LogError("Unrecognized SI prefix: " + prefix);
+ return 1;
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const IfcColourRgb& in)
{
- out.r = static_cast<float>( in.Red );
- out.g = static_cast<float>( in.Green );
- out.b = static_cast<float>( in.Blue );
- out.a = static_cast<float>( 1.f );
+ out.r = static_cast<float>( in.Red );
+ out.g = static_cast<float>( in.Green );
+ out.b = static_cast<float>( in.Blue );
+ out.a = static_cast<float>( 1.f );
}
// ------------------------------------------------------------------------------------------------
void ConvertColor(aiColor4D& out, const IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base)
{
- if (const EXPRESS::REAL* const r = in.ToPtr<EXPRESS::REAL>()) {
- out.r = out.g = out.b = static_cast<float>(*r);
- if(base) {
- out.r *= static_cast<float>( base->r );
- out.g *= static_cast<float>( base->g );
- out.b *= static_cast<float>( base->b );
- out.a = static_cast<float>( base->a );
- }
- else out.a = 1.0;
- }
- else if (const IfcColourRgb* const rgb = in.ResolveSelectPtr<IfcColourRgb>(conv.db)) {
- ConvertColor(out,*rgb);
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
- }
+ if (const EXPRESS::REAL* const r = in.ToPtr<EXPRESS::REAL>()) {
+ out.r = out.g = out.b = static_cast<float>(*r);
+ if(base) {
+ out.r *= static_cast<float>( base->r );
+ out.g *= static_cast<float>( base->g );
+ out.b *= static_cast<float>( base->b );
+ out.a = static_cast<float>( base->a );
+ }
+ else out.a = 1.0;
+ }
+ else if (const IfcColourRgb* const rgb = in.ResolveSelectPtr<IfcColourRgb>(conv.db)) {
+ ConvertColor(out,*rgb);
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity");
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertCartesianPoint(IfcVector3& out, const IfcCartesianPoint& in)
{
- out = IfcVector3();
- for(size_t i = 0; i < in.Coordinates.size(); ++i) {
- out[i] = in.Coordinates[i];
- }
+ out = IfcVector3();
+ for(size_t i = 0; i < in.Coordinates.size(); ++i) {
+ out[i] = in.Coordinates[i];
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertVector(IfcVector3& out, const IfcVector& in)
{
- ConvertDirection(out,in.Orientation);
- out *= in.Magnitude;
+ ConvertDirection(out,in.Orientation);
+ out *= in.Magnitude;
}
// ------------------------------------------------------------------------------------------------
void ConvertDirection(IfcVector3& out, const IfcDirection& in)
{
- out = IfcVector3();
- for(size_t i = 0; i < in.DirectionRatios.size(); ++i) {
- out[i] = in.DirectionRatios[i];
- }
- const IfcFloat len = out.Length();
- if (len<1e-6) {
- IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
- return;
- }
- out /= len;
+ out = IfcVector3();
+ for(size_t i = 0; i < in.DirectionRatios.size(); ++i) {
+ out[i] = in.DirectionRatios[i];
+ }
+ const IfcFloat len = out.Length();
+ if (len<1e-6) {
+ IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero");
+ return;
+ }
+ out /= len;
}
// ------------------------------------------------------------------------------------------------
void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z)
{
- out.a1 = x.x;
- out.b1 = x.y;
- out.c1 = x.z;
+ out.a1 = x.x;
+ out.b1 = x.y;
+ out.c1 = x.z;
- out.a2 = y.x;
- out.b2 = y.y;
- out.c2 = y.z;
+ out.a2 = y.x;
+ out.b2 = y.y;
+ out.c2 = y.z;
- out.a3 = z.x;
- out.b3 = z.y;
- out.c3 = z.z;
+ out.a3 = z.x;
+ out.b3 = z.y;
+ out.c3 = z.z;
}
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement3D& in)
{
- IfcVector3 loc;
- ConvertCartesianPoint(loc,in.Location);
+ IfcVector3 loc;
+ ConvertCartesianPoint(loc,in.Location);
- IfcVector3 z(0.f,0.f,1.f),r(1.f,0.f,0.f),x;
+ IfcVector3 z(0.f,0.f,1.f),r(1.f,0.f,0.f),x;
- if (in.Axis) {
- ConvertDirection(z,*in.Axis.Get());
- }
- if (in.RefDirection) {
- ConvertDirection(r,*in.RefDirection.Get());
- }
+ if (in.Axis) {
+ ConvertDirection(z,*in.Axis.Get());
+ }
+ if (in.RefDirection) {
+ ConvertDirection(r,*in.RefDirection.Get());
+ }
- IfcVector3 v = r.Normalize();
- IfcVector3 tmpx = z * (v*z);
+ IfcVector3 v = r.Normalize();
+ IfcVector3 tmpx = z * (v*z);
- x = (v-tmpx).Normalize();
- IfcVector3 y = (z^x);
+ x = (v-tmpx).Normalize();
+ IfcVector3 y = (z^x);
- IfcMatrix4::Translation(loc,out);
- AssignMatrixAxes(out,x,y,z);
+ IfcMatrix4::Translation(loc,out);
+ AssignMatrixAxes(out,x,y,z);
}
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement2D& in)
{
- IfcVector3 loc;
- ConvertCartesianPoint(loc,in.Location);
+ IfcVector3 loc;
+ ConvertCartesianPoint(loc,in.Location);
- IfcVector3 x(1.f,0.f,0.f);
- if (in.RefDirection) {
- ConvertDirection(x,*in.RefDirection.Get());
- }
+ IfcVector3 x(1.f,0.f,0.f);
+ if (in.RefDirection) {
+ ConvertDirection(x,*in.RefDirection.Get());
+ }
- const IfcVector3 y = IfcVector3(x.y,-x.x,0.f);
+ const IfcVector3 y = IfcVector3(x.y,-x.x,0.f);
- IfcMatrix4::Translation(loc,out);
- AssignMatrixAxes(out,x,y,IfcVector3(0.f,0.f,1.f));
+ IfcMatrix4::Translation(loc,out);
+ AssignMatrixAxes(out,x,y,IfcVector3(0.f,0.f,1.f));
}
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const IfcAxis1Placement& in)
{
- ConvertCartesianPoint(pos,in.Location);
- if (in.Axis) {
- ConvertDirection(axis,in.Axis.Get());
- }
- else {
- axis = IfcVector3(0.f,0.f,1.f);
- }
+ ConvertCartesianPoint(pos,in.Location);
+ if (in.Axis) {
+ ConvertDirection(axis,in.Axis.Get());
+ }
+ else {
+ axis = IfcVector3(0.f,0.f,1.f);
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement& in, ConversionData& conv)
{
- if(const IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<IfcAxis2Placement3D>(conv.db)) {
- ConvertAxisPlacement(out,*pl3);
- }
- else if(const IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<IfcAxis2Placement2D>(conv.db)) {
- ConvertAxisPlacement(out,*pl2);
- }
- else {
- IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
- }
+ if(const IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<IfcAxis2Placement3D>(conv.db)) {
+ ConvertAxisPlacement(out,*pl3);
+ }
+ else if(const IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<IfcAxis2Placement2D>(conv.db)) {
+ ConvertAxisPlacement(out,*pl2);
+ }
+ else {
+ IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity");
+ }
}
// ------------------------------------------------------------------------------------------------
void ConvertTransformOperator(IfcMatrix4& out, const IfcCartesianTransformationOperator& op)
{
- IfcVector3 loc;
- ConvertCartesianPoint(loc,op.LocalOrigin);
-
- IfcVector3 x(1.f,0.f,0.f),y(0.f,1.f,0.f),z(0.f,0.f,1.f);
- if (op.Axis1) {
- ConvertDirection(x,*op.Axis1.Get());
- }
- if (op.Axis2) {
- ConvertDirection(y,*op.Axis2.Get());
- }
- if (const IfcCartesianTransformationOperator3D* op2 = op.ToPtr<IfcCartesianTransformationOperator3D>()) {
- if(op2->Axis3) {
- ConvertDirection(z,*op2->Axis3.Get());
- }
- }
-
- IfcMatrix4 locm;
- IfcMatrix4::Translation(loc,locm);
- AssignMatrixAxes(out,x,y,z);
-
-
- IfcVector3 vscale;
- if (const IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<IfcCartesianTransformationOperator3DnonUniform>()) {
- vscale.x = nuni->Scale?op.Scale.Get():1.f;
- vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f;
- vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f;
- }
- else {
- const IfcFloat sc = op.Scale?op.Scale.Get():1.f;
- vscale = IfcVector3(sc,sc,sc);
- }
-
- IfcMatrix4 s;
- IfcMatrix4::Scaling(vscale,s);
-
- out = locm * out * s;
+ IfcVector3 loc;
+ ConvertCartesianPoint(loc,op.LocalOrigin);
+
+ IfcVector3 x(1.f,0.f,0.f),y(0.f,1.f,0.f),z(0.f,0.f,1.f);
+ if (op.Axis1) {
+ ConvertDirection(x,*op.Axis1.Get());
+ }
+ if (op.Axis2) {
+ ConvertDirection(y,*op.Axis2.Get());
+ }
+ if (const IfcCartesianTransformationOperator3D* op2 = op.ToPtr<IfcCartesianTransformationOperator3D>()) {
+ if(op2->Axis3) {
+ ConvertDirection(z,*op2->Axis3.Get());
+ }
+ }
+
+ IfcMatrix4 locm;
+ IfcMatrix4::Translation(loc,locm);
+ AssignMatrixAxes(out,x,y,z);
+
+
+ IfcVector3 vscale;
+ if (const IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<IfcCartesianTransformationOperator3DnonUniform>()) {
+ vscale.x = nuni->Scale?op.Scale.Get():1.f;
+ vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f;
+ vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f;
+ }
+ else {
+ const IfcFloat sc = op.Scale?op.Scale.Get():1.f;
+ vscale = IfcVector3(sc,sc,sc);
+ }
+
+ IfcMatrix4 s;
+ IfcMatrix4::Scaling(vscale,s);
+
+ out = locm * out * s;
}
diff --git a/src/3rdparty/assimp/code/IFCUtil.h b/src/3rdparty/assimp/code/IFCUtil.h
index 81b8f1187..43d20a434 100644
--- a/src/3rdparty/assimp/code/IFCUtil.h
+++ b/src/3rdparty/assimp/code/IFCUtil.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,18 +47,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IFCReaderGen.h"
#include "IFCLoader.h"
+#include "STEPFile.h"
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+
+struct aiNode;
namespace Assimp {
namespace IFC {
- typedef double IfcFloat;
+ typedef double IfcFloat;
- // IfcFloat-precision math data types
- typedef aiVector2t<IfcFloat> IfcVector2;
- typedef aiVector3t<IfcFloat> IfcVector3;
- typedef aiMatrix4x4t<IfcFloat> IfcMatrix4;
- typedef aiMatrix3x3t<IfcFloat> IfcMatrix3;
- typedef aiColor4t<IfcFloat> IfcColor4;
+ // IfcFloat-precision math data types
+ typedef aiVector2t<IfcFloat> IfcVector2;
+ typedef aiVector3t<IfcFloat> IfcVector3;
+ typedef aiMatrix4x4t<IfcFloat> IfcMatrix4;
+ typedef aiMatrix3x3t<IfcFloat> IfcMatrix3;
+ typedef aiColor4t<IfcFloat> IfcColor4;
// ------------------------------------------------------------------------------------------------
@@ -67,9 +72,9 @@ namespace IFC {
template<typename T>
struct delete_fun
{
- void operator()(T* del) {
- delete del;
- }
+ void operator()(T* del) {
+ delete del;
+ }
};
@@ -79,137 +84,147 @@ struct delete_fun
// ------------------------------------------------------------------------------------------------
struct TempMesh
{
- std::vector<IfcVector3> verts;
- std::vector<unsigned int> vertcnt;
-
- // utilities
- aiMesh* ToMesh();
- void Clear();
- void Transform(const IfcMatrix4& mat);
- IfcVector3 Center() const;
- void Append(const TempMesh& other);
-
- bool IsEmpty() const {
- return verts.empty() && vertcnt.empty();
- }
-
- void RemoveAdjacentDuplicates();
- void RemoveDegenerates();
-
- void FixupFaceOrientation();
- IfcVector3 ComputeLastPolygonNormal(bool normalize = true) const;
- void ComputePolygonNormals(std::vector<IfcVector3>& normals,
- bool normalize = true,
- size_t ofs = 0) const;
-
- void Swap(TempMesh& other);
+ std::vector<IfcVector3> verts;
+ std::vector<unsigned int> vertcnt;
+
+ // utilities
+ aiMesh* ToMesh();
+ void Clear();
+ void Transform(const IfcMatrix4& mat);
+ IfcVector3 Center() const;
+ void Append(const TempMesh& other);
+
+ bool IsEmpty() const {
+ return verts.empty() && vertcnt.empty();
+ }
+
+ void RemoveAdjacentDuplicates();
+ void RemoveDegenerates();
+
+ void FixupFaceOrientation();
+
+ static IfcVector3 ComputePolygonNormal(const IfcVector3* vtcs, size_t cnt, bool normalize = true);
+ IfcVector3 ComputeLastPolygonNormal(bool normalize = true) const;
+ void ComputePolygonNormals(std::vector<IfcVector3>& normals, bool normalize = true, size_t ofs = 0) const;
+
+ void Swap(TempMesh& other);
};
// ------------------------------------------------------------------------------------------------
// Temporary representation of an opening in a wall or a floor
// ------------------------------------------------------------------------------------------------
-struct TempOpening
+struct TempOpening
{
- const IFC::IfcSolidModel* solid;
- IfcVector3 extrusionDir;
-
- boost::shared_ptr<TempMesh> profileMesh;
- boost::shared_ptr<TempMesh> profileMesh2D;
-
- // list of points generated for this opening. This is used to
- // create connections between two opposing holes created
- // from a single opening instance (two because walls tend to
- // have two sides). If !empty(), the other side of the wall
- // has already been processed.
- std::vector<IfcVector3> wallPoints;
-
- // ------------------------------------------------------------------------------
- TempOpening()
- : solid()
- , extrusionDir()
- , profileMesh()
- {
- }
-
- // ------------------------------------------------------------------------------
- TempOpening(const IFC::IfcSolidModel* solid,IfcVector3 extrusionDir,
- boost::shared_ptr<TempMesh> profileMesh,
- boost::shared_ptr<TempMesh> profileMesh2D)
- : solid(solid)
- , extrusionDir(extrusionDir)
- , profileMesh(profileMesh)
- , profileMesh2D(profileMesh2D)
- {
- }
-
- // ------------------------------------------------------------------------------
- void Transform(const IfcMatrix4& mat); // defined later since TempMesh is not complete yet
-
-
-
- // ------------------------------------------------------------------------------
- // Helper to sort openings by distance from a given base point
- struct DistanceSorter {
-
- DistanceSorter(const IfcVector3& base) : base(base) {}
-
- bool operator () (const TempOpening& a, const TempOpening& b) const {
- return (a.profileMesh->Center()-base).SquareLength() < (b.profileMesh->Center()-base).SquareLength();
- }
-
- IfcVector3 base;
- };
+ const IFC::IfcSolidModel* solid;
+ IfcVector3 extrusionDir;
+
+ std::shared_ptr<TempMesh> profileMesh;
+ std::shared_ptr<TempMesh> profileMesh2D;
+
+ // list of points generated for this opening. This is used to
+ // create connections between two opposing holes created
+ // from a single opening instance (two because walls tend to
+ // have two sides). If !empty(), the other side of the wall
+ // has already been processed.
+ std::vector<IfcVector3> wallPoints;
+
+ // ------------------------------------------------------------------------------
+ TempOpening()
+ : solid()
+ , extrusionDir()
+ , profileMesh()
+ {
+ }
+
+ // ------------------------------------------------------------------------------
+ TempOpening(const IFC::IfcSolidModel* solid,IfcVector3 extrusionDir,
+ std::shared_ptr<TempMesh> profileMesh,
+ std::shared_ptr<TempMesh> profileMesh2D)
+ : solid(solid)
+ , extrusionDir(extrusionDir)
+ , profileMesh(profileMesh)
+ , profileMesh2D(profileMesh2D)
+ {
+ }
+
+ // ------------------------------------------------------------------------------
+ void Transform(const IfcMatrix4& mat); // defined later since TempMesh is not complete yet
+
+
+
+ // ------------------------------------------------------------------------------
+ // Helper to sort openings by distance from a given base point
+ struct DistanceSorter {
+
+ DistanceSorter(const IfcVector3& base) : base(base) {}
+
+ bool operator () (const TempOpening& a, const TempOpening& b) const {
+ return (a.profileMesh->Center()-base).SquareLength() < (b.profileMesh->Center()-base).SquareLength();
+ }
+
+ IfcVector3 base;
+ };
};
// ------------------------------------------------------------------------------------------------
// Intermediate data storage during conversion. Keeps everything and a bit more.
// ------------------------------------------------------------------------------------------------
-struct ConversionData
+struct ConversionData
{
- ConversionData(const STEP::DB& db, const IFC::IfcProject& proj, aiScene* out,const IFCImporter::Settings& settings)
- : len_scale(1.0)
- , angle_scale(-1.0)
- , db(db)
- , proj(proj)
- , out(out)
- , settings(settings)
- , apply_openings()
- , collect_openings()
- {}
-
- ~ConversionData() {
- std::for_each(meshes.begin(),meshes.end(),delete_fun<aiMesh>());
- std::for_each(materials.begin(),materials.end(),delete_fun<aiMaterial>());
- }
-
- IfcFloat len_scale, angle_scale;
- bool plane_angle_in_radians;
-
- const STEP::DB& db;
- const IFC::IfcProject& proj;
- aiScene* out;
-
- IfcMatrix4 wcs;
- std::vector<aiMesh*> meshes;
- std::vector<aiMaterial*> materials;
-
- typedef std::map<const IFC::IfcRepresentationItem*, std::vector<unsigned int> > MeshCache;
- MeshCache cached_meshes;
-
- const IFCImporter::Settings& settings;
-
- // Intermediate arrays used to resolve openings in walls: only one of them
- // can be given at a time. apply_openings if present if the current element
- // is a wall and needs its openings to be poured into its geometry while
- // collect_openings is present only if the current element is an
- // IfcOpeningElement, for which all the geometry needs to be preserved
- // for later processing by a parent, which is a wall.
- std::vector<TempOpening>* apply_openings;
- std::vector<TempOpening>* collect_openings;
-
- std::set<uint64_t> already_processed;
+ ConversionData(const STEP::DB& db, const IFC::IfcProject& proj, aiScene* out,const IFCImporter::Settings& settings)
+ : len_scale(1.0)
+ , angle_scale(-1.0)
+ , db(db)
+ , proj(proj)
+ , out(out)
+ , settings(settings)
+ , apply_openings()
+ , collect_openings()
+ {}
+
+ ~ConversionData() {
+ std::for_each(meshes.begin(),meshes.end(),delete_fun<aiMesh>());
+ std::for_each(materials.begin(),materials.end(),delete_fun<aiMaterial>());
+ }
+
+ IfcFloat len_scale, angle_scale;
+ bool plane_angle_in_radians;
+
+ const STEP::DB& db;
+ const IFC::IfcProject& proj;
+ aiScene* out;
+
+ IfcMatrix4 wcs;
+ std::vector<aiMesh*> meshes;
+ std::vector<aiMaterial*> materials;
+
+ struct MeshCacheIndex {
+ const IFC::IfcRepresentationItem* item; unsigned int matindex;
+ MeshCacheIndex() : item(NULL), matindex(0) { }
+ MeshCacheIndex(const IFC::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { }
+ bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; }
+ bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); }
+ };
+ typedef std::map<MeshCacheIndex, std::vector<unsigned int> > MeshCache;
+ MeshCache cached_meshes;
+
+ typedef std::map<const IFC::IfcSurfaceStyle*, unsigned int> MaterialCache;
+ MaterialCache cached_materials;
+
+ const IFCImporter::Settings& settings;
+
+ // Intermediate arrays used to resolve openings in walls: only one of them
+ // can be given at a time. apply_openings if present if the current element
+ // is a wall and needs its openings to be poured into its geometry while
+ // collect_openings is present only if the current element is an
+ // IfcOpeningElement, for which all the geometry needs to be preserved
+ // for later processing by a parent, which is a wall.
+ std::vector<TempOpening>* apply_openings;
+ std::vector<TempOpening>* collect_openings;
+
+ std::set<uint64_t> already_processed;
};
@@ -218,12 +233,12 @@ struct ConversionData
// ------------------------------------------------------------------------------------------------
struct FuzzyVectorCompare {
- FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
- bool operator()(const IfcVector3& a, const IfcVector3& b) {
- return std::fabs((a-b).SquareLength()) < epsilon;
- }
+ FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
+ bool operator()(const IfcVector3& a, const IfcVector3& b) {
+ return std::abs((a-b).SquareLength()) < epsilon;
+ }
- const IfcFloat epsilon;
+ const IfcFloat epsilon;
};
@@ -232,13 +247,13 @@ struct FuzzyVectorCompare {
// ------------------------------------------------------------------------------------------------
struct XYSorter {
- // sort first by X coordinates, then by Y coordinates
- bool operator () (const IfcVector2&a, const IfcVector2& b) const {
- if (a.x == b.x) {
- return a.y < b.y;
- }
- return a.x < b.x;
- }
+ // sort first by X coordinates, then by Y coordinates
+ bool operator () (const IfcVector2&a, const IfcVector2& b) const {
+ if (a.x == b.x) {
+ return a.y < b.y;
+ }
+ return a.x < b.x;
+ }
};
@@ -261,44 +276,45 @@ IfcFloat ConvertSIPrefix(const std::string& prefix);
// IFCProfile.cpp
bool ProcessProfile(const IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv);
+bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& conv);
// IFCMaterial.cpp
-unsigned int ProcessMaterials(const IFC::IfcRepresentationItem& item, ConversionData& conv);
+unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat);
// IFCGeometry.cpp
IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVector3& norOut);
-bool ProcessRepresentationItem(const IfcRepresentationItem& item, std::vector<unsigned int>& mesh_indices, ConversionData& conv);
+bool ProcessRepresentationItem(const IfcRepresentationItem& item, unsigned int matid, std::vector<unsigned int>& mesh_indices, ConversionData& conv);
void AssignAddedMeshes(std::vector<unsigned int>& mesh_indices,aiNode* nd,ConversionData& /*conv*/);
-void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
- ConversionData& conv);
+void ProcessSweptAreaSolid(const IfcSweptAreaSolid& swept, TempMesh& meshout,
+ ConversionData& conv);
-void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
- ConversionData& conv, bool collect_openings);
+void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& result,
+ ConversionData& conv, bool collect_openings);
// IFCBoolean.cpp
void ProcessBoolean(const IfcBooleanResult& boolean, TempMesh& result, ConversionData& conv);
-void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv);
+void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& conv);
-void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBoundedHalfSpace* hs, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv);
-void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, TempMesh& result,
- const TempMesh& first_operand,
- ConversionData& conv);
+void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBoundedHalfSpace* hs, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& conv);
+void ProcessBooleanExtrudedAreaSolidDifference(const IfcExtrudedAreaSolid* as, TempMesh& result,
+ const TempMesh& first_operand,
+ ConversionData& conv);
// IFCOpenings.cpp
bool GenerateOpenings(std::vector<TempOpening>& openings,
- const std::vector<IfcVector3>& nors,
- TempMesh& curmesh,
- bool check_intersection,
- bool generate_connection_geometry,
- const IfcVector3& wall_extrusion_axis = IfcVector3(0,1,0));
+ const std::vector<IfcVector3>& nors,
+ TempMesh& curmesh,
+ bool check_intersection,
+ bool generate_connection_geometry,
+ const IfcVector3& wall_extrusion_axis = IfcVector3(0,1,0));
@@ -307,15 +323,15 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
// ------------------------------------------------------------------------------------------------
// Custom exception for use by members of the Curve class
// ------------------------------------------------------------------------------------------------
-class CurveError
+class CurveError
{
public:
- CurveError(const std::string& s)
- : s(s)
- {
- }
+ CurveError(const std::string& s)
+ : s(s)
+ {
+ }
- std::string s;
+ std::string s;
};
@@ -327,57 +343,57 @@ class Curve
{
protected:
- Curve(const IfcCurve& base_entity, ConversionData& conv)
- : base_entity(base_entity)
- , conv(conv)
- {}
+ Curve(const IfcCurve& base_entity, ConversionData& conv)
+ : base_entity(base_entity)
+ , conv(conv)
+ {}
public:
- typedef std::pair<IfcFloat, IfcFloat> ParamRange;
+ typedef std::pair<IfcFloat, IfcFloat> ParamRange;
public:
- virtual ~Curve() {}
+ virtual ~Curve() {}
- // check if a curve is closed
- virtual bool IsClosed() const = 0;
+ // check if a curve is closed
+ virtual bool IsClosed() const = 0;
- // evaluate the curve at the given parametric position
- virtual IfcVector3 Eval(IfcFloat p) const = 0;
+ // evaluate the curve at the given parametric position
+ virtual IfcVector3 Eval(IfcFloat p) const = 0;
- // try to match a point on the curve to a given parameter
- // for self-intersecting curves, the result is not ambiguous and
- // it is undefined which parameter is returned.
- virtual bool ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const;
+ // try to match a point on the curve to a given parameter
+ // for self-intersecting curves, the result is not ambiguous and
+ // it is undefined which parameter is returned.
+ virtual bool ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const;
- // get the range of the curve (both inclusive).
- // +inf and -inf are valid return values, the curve is not bounded in such a case.
- virtual std::pair<IfcFloat,IfcFloat> GetParametricRange() const = 0;
- IfcFloat GetParametricRangeDelta() const;
+ // get the range of the curve (both inclusive).
+ // +inf and -inf are valid return values, the curve is not bounded in such a case.
+ virtual std::pair<IfcFloat,IfcFloat> GetParametricRange() const = 0;
+ IfcFloat GetParametricRangeDelta() const;
- // estimate the number of sample points that this curve will require
- virtual size_t EstimateSampleCount(IfcFloat start,IfcFloat end) const;
+ // estimate the number of sample points that this curve will require
+ virtual size_t EstimateSampleCount(IfcFloat start,IfcFloat end) const;
- // intelligently sample the curve based on the current settings
- // and append the result to the mesh
- virtual void SampleDiscrete(TempMesh& out,IfcFloat start,IfcFloat end) const;
+ // intelligently sample the curve based on the current settings
+ // and append the result to the mesh
+ virtual void SampleDiscrete(TempMesh& out,IfcFloat start,IfcFloat end) const;
#ifdef ASSIMP_BUILD_DEBUG
- // check if a particular parameter value lies within the well-defined range
- bool InRange(IfcFloat) const;
-#endif
+ // check if a particular parameter value lies within the well-defined range
+ bool InRange(IfcFloat) const;
+#endif
public:
- static Curve* Convert(const IFC::IfcCurve&,ConversionData& conv);
+ static Curve* Convert(const IFC::IfcCurve&,ConversionData& conv);
protected:
- const IfcCurve& base_entity;
- ConversionData& conv;
+ const IfcCurve& base_entity;
+ ConversionData& conv;
};
@@ -385,23 +401,23 @@ protected:
// A BoundedCurve always holds the invariant that GetParametricRange()
// never returns infinite values.
// --------------------------------------------------------------------------------
-class BoundedCurve : public Curve
+class BoundedCurve : public Curve
{
public:
- BoundedCurve(const IfcBoundedCurve& entity, ConversionData& conv)
- : Curve(entity,conv)
- {}
+ BoundedCurve(const IfcBoundedCurve& entity, ConversionData& conv)
+ : Curve(entity,conv)
+ {}
public:
- bool IsClosed() const;
+ bool IsClosed() const;
public:
- // sample the entire curve
- void SampleDiscrete(TempMesh& out) const;
- using Curve::SampleDiscrete;
+ // sample the entire curve
+ void SampleDiscrete(TempMesh& out) const;
+ using Curve::SampleDiscrete;
};
// IfcProfile.cpp
@@ -409,4 +425,4 @@ bool ProcessCurve(const IfcCurve& curve, TempMesh& meshout, ConversionData& con
}
}
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/IFF.h b/src/3rdparty/assimp/code/IFF.h
index a1b2dc9c5..2b42b554b 100644
--- a/src/3rdparty/assimp/code/IFF.h
+++ b/src/3rdparty/assimp/code/IFF.h
@@ -1,5 +1,3 @@
-
-
// Definitions for the Interchange File Format (IFF)
// Alexander Gessler, 2006
// Adapted to Assimp August 2008
@@ -7,24 +5,22 @@
#ifndef AI_IFF_H_INCLUDED
#define AI_IFF_H_INCLUDED
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
-namespace Assimp {
-namespace IFF {
-
-#include "./../include/assimp/Compiler/pushpack1.h"
+namespace Assimp {
+namespace IFF {
/////////////////////////////////////////////////////////////////////////////////
//! Describes an IFF chunk header
/////////////////////////////////////////////////////////////////////////////////
struct ChunkHeader
{
- //! Type of the chunk header - FourCC
- uint32_t type;
+ //! Type of the chunk header - FourCC
+ uint32_t type;
- //! Length of the chunk data, in bytes
- uint32_t length;
-} PACK_STRUCT;
+ //! Length of the chunk data, in bytes
+ uint32_t length;
+};
/////////////////////////////////////////////////////////////////////////////////
@@ -32,18 +28,16 @@ struct ChunkHeader
/////////////////////////////////////////////////////////////////////////////////
struct SubChunkHeader
{
- //! Type of the chunk header - FourCC
- uint32_t type;
-
- //! Length of the chunk data, in bytes
- uint16_t length;
-} PACK_STRUCT;
+ //! Type of the chunk header - FourCC
+ uint32_t type;
-#include "./../include/assimp/Compiler/poppack1.h"
+ //! 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)))
+ ((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d)))
#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M')
@@ -52,48 +46,54 @@ struct SubChunkHeader
/////////////////////////////////////////////////////////////////////////////////
//! Load a chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards
-//! @return Pointer to the chunk header
+//! @return Copy of the chunk header
/////////////////////////////////////////////////////////////////////////////////
-inline ChunkHeader* LoadChunk(uint8_t*& outFile)
+inline ChunkHeader LoadChunk(uint8_t*& outFile)
{
- ChunkHeader* head = (ChunkHeader*) outFile;
- AI_LSWAP4(head->length);
- AI_LSWAP4(head->type);
- outFile += sizeof(ChunkHeader);
- return head;
+ 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 Pointer to the sub chunk header
+//! @return Copy of the sub chunk header
/////////////////////////////////////////////////////////////////////////////////
-inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
+inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
{
- SubChunkHeader* head = (SubChunkHeader*) outFile;
- AI_LSWAP2(head->length);
- AI_LSWAP4(head->type);
- outFile += sizeof(SubChunkHeader);
- return head;
+ 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
+//! @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)
+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";
- }
- fileType = *((uint32_t*)(head+1));
- AI_LSWAP4(fileType);
- return 0;
+ 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;
}
diff --git a/src/3rdparty/assimp/code/IRRLoader.cpp b/src/3rdparty/assimp/code/IRRLoader.cpp
index 03393f4cb..2d702523d 100644
--- a/src/3rdparty/assimp/code/IRRLoader.cpp
+++ b/src/3rdparty/assimp/code/IRRLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,25 +25,25 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file IRRLoader.cpp
- * @brief Implementation of the Irr importer class
+ * @brief Implementation of the Irr importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
@@ -56,1422 +56,1431 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StandardShapes.h"
#include "Importer.h"
-// We need boost::common_factor to compute the lcm/gcd of a number
-#include <boost/math/common_factor_rt.hpp>
+// We need MathFunctions.h to compute the lcm/gcd of a number
+#include "MathFunctions.h"
+#include <memory>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/postprocess.h>
+
using namespace Assimp;
using namespace irr;
using namespace irr::io;
static const aiImporterDesc desc = {
- "Irrlicht Scene Reader",
- "",
- "",
- "http://irrlicht.sourceforge.net/",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "irr xml"
+ "Irrlicht Scene Reader",
+ "",
+ "",
+ "http://irrlicht.sourceforge.net/",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "irr xml"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IRRImporter::IRRImporter()
+ : fps(),
+ configSpeedFlag()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
IRRImporter::~IRRImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- /* NOTE: A simple check for the file extension is not enough
- * here. Irrmesh and irr are easy, but xml is too generic
- * and could be collada, too. So we need to open the file and
- * search for typical tokens.
- */
- const std::string extension = GetExtension(pFile);
-
- if (extension == "irr")return true;
- else if (extension == "xml" || checkSig)
- {
- /* If CanRead() is called in order to check whether we
- * support a specific file extension in general pIOHandler
- * might be NULL and it's our duty to return true here.
- */
- if (!pIOHandler)return true;
- const char* tokens[] = {"irr_scene"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ /* NOTE: A simple check for the file extension is not enough
+ * here. Irrmesh and irr are easy, but xml is too generic
+ * and could be collada, too. So we need to open the file and
+ * search for typical tokens.
+ */
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "irr")return true;
+ else if (extension == "xml" || checkSig)
+ {
+ /* If CanRead() is called in order to check whether we
+ * support a specific file extension in general pIOHandler
+ * might be NULL and it's our duty to return true here.
+ */
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"irr_scene"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* IRRImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::SetupProperties(const Importer* pImp)
{
- // read the output frame rate of all node animation channels
- fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100);
- if (fps < 10.) {
- DefaultLogger::get()->error("IRR: Invalid FPS configuration");
- fps = 100;
- }
-
- // AI_CONFIG_FAVOUR_SPEED
- configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+ // read the output frame rate of all node animation channels
+ fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100);
+ if (fps < 10.) {
+ DefaultLogger::get()->error("IRR: Invalid FPS configuration");
+ fps = 100;
+ }
+
+ // AI_CONFIG_FAVOUR_SPEED
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
}
// ------------------------------------------------------------------------------------------------
// Build a mesh tha consists of a single squad (a side of a skybox)
aiMesh* IRRImporter::BuildSingleQuadMesh(const SkyboxVertex& v1,
- const SkyboxVertex& v2,
- const SkyboxVertex& v3,
- const SkyboxVertex& v4)
+ const SkyboxVertex& v2,
+ const SkyboxVertex& v3,
+ const SkyboxVertex& v4)
{
- // allocate and prepare the mesh
- aiMesh* out = new aiMesh();
-
- out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
- out->mNumFaces = 1;
-
- // build the face
- out->mFaces = new aiFace[1];
- aiFace& face = out->mFaces[0];
-
- face.mNumIndices = 4;
- face.mIndices = new unsigned int[4];
- for (unsigned int i = 0; i < 4;++i)
- face.mIndices[i] = i;
-
- out->mNumVertices = 4;
-
- // copy vertex positions
- aiVector3D* vec = out->mVertices = new aiVector3D[4];
- *vec++ = v1.position;
- *vec++ = v2.position;
- *vec++ = v3.position;
- *vec = v4.position;
-
- // copy vertex normals
- vec = out->mNormals = new aiVector3D[4];
- *vec++ = v1.normal;
- *vec++ = v2.normal;
- *vec++ = v3.normal;
- *vec = v4.normal;
-
- // copy texture coordinates
- vec = out->mTextureCoords[0] = new aiVector3D[4];
- *vec++ = v1.uv;
- *vec++ = v2.uv;
- *vec++ = v3.uv;
- *vec = v4.uv;
- return out;
+ // allocate and prepare the mesh
+ aiMesh* out = new aiMesh();
+
+ out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
+ out->mNumFaces = 1;
+
+ // build the face
+ out->mFaces = new aiFace[1];
+ aiFace& face = out->mFaces[0];
+
+ face.mNumIndices = 4;
+ face.mIndices = new unsigned int[4];
+ for (unsigned int i = 0; i < 4;++i)
+ face.mIndices[i] = i;
+
+ out->mNumVertices = 4;
+
+ // copy vertex positions
+ aiVector3D* vec = out->mVertices = new aiVector3D[4];
+ *vec++ = v1.position;
+ *vec++ = v2.position;
+ *vec++ = v3.position;
+ *vec = v4.position;
+
+ // copy vertex normals
+ vec = out->mNormals = new aiVector3D[4];
+ *vec++ = v1.normal;
+ *vec++ = v2.normal;
+ *vec++ = v3.normal;
+ *vec = v4.normal;
+
+ // copy texture coordinates
+ vec = out->mTextureCoords[0] = new aiVector3D[4];
+ *vec++ = v1.uv;
+ *vec++ = v2.uv;
+ *vec++ = v3.uv;
+ *vec = v4.uv;
+ return out;
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMaterial*> materials)
{
- // Update the material of the skybox - replace the name and disable shading for skyboxes.
- for (unsigned int i = 0; i < 6;++i) {
- aiMaterial* out = ( aiMaterial* ) (*(materials.end()-(6-i)));
-
- aiString s;
- s.length = ::sprintf( s.data, "SkyboxSide_%i",i );
- out->AddProperty(&s,AI_MATKEY_NAME);
-
- int shading = aiShadingMode_NoShading;
- out->AddProperty(&shading,1,AI_MATKEY_SHADING_MODEL);
- }
-
- // Skyboxes are much more difficult. They are represented
- // by six single planes with different textures, so we'll
- // need to build six meshes.
-
- const float l = 10.f; // the size used by Irrlicht
-
- // FRONT SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex(-l,-l,-l, 0, 0, 1, 1.f,1.f),
- SkyboxVertex( l,-l,-l, 0, 0, 1, 0.f,1.f),
- SkyboxVertex( l, l,-l, 0, 0, 1, 0.f,0.f),
- SkyboxVertex(-l, l,-l, 0, 0, 1, 1.f,0.f)) );
- meshes.back()->mMaterialIndex = materials.size()-6u;
-
- // LEFT SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex( l,-l,-l, -1, 0, 0, 1.f,1.f),
- SkyboxVertex( l,-l, l, -1, 0, 0, 0.f,1.f),
- SkyboxVertex( l, l, l, -1, 0, 0, 0.f,0.f),
- SkyboxVertex( l, l,-l, -1, 0, 0, 1.f,0.f)) );
- meshes.back()->mMaterialIndex = materials.size()-5u;
-
- // BACK SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex( l,-l, l, 0, 0, -1, 1.f,1.f),
- SkyboxVertex(-l,-l, l, 0, 0, -1, 0.f,1.f),
- SkyboxVertex(-l, l, l, 0, 0, -1, 0.f,0.f),
- SkyboxVertex( l, l, l, 0, 0, -1, 1.f,0.f)) );
- meshes.back()->mMaterialIndex = materials.size()-4u;
-
- // RIGHT SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex(-l,-l, l, 1, 0, 0, 1.f,1.f),
- SkyboxVertex(-l,-l,-l, 1, 0, 0, 0.f,1.f),
- SkyboxVertex(-l, l,-l, 1, 0, 0, 0.f,0.f),
- SkyboxVertex(-l, l, l, 1, 0, 0, 1.f,0.f)) );
- meshes.back()->mMaterialIndex = materials.size()-3u;
-
- // TOP SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex( l, l,-l, 0, -1, 0, 1.f,1.f),
- SkyboxVertex( l, l, l, 0, -1, 0, 0.f,1.f),
- SkyboxVertex(-l, l, l, 0, -1, 0, 0.f,0.f),
- SkyboxVertex(-l, l,-l, 0, -1, 0, 1.f,0.f)) );
- meshes.back()->mMaterialIndex = materials.size()-2u;
-
- // BOTTOM SIDE
- meshes.push_back( BuildSingleQuadMesh(
- SkyboxVertex( l,-l, l, 0, 1, 0, 0.f,0.f),
- SkyboxVertex( l,-l,-l, 0, 1, 0, 1.f,0.f),
- SkyboxVertex(-l,-l,-l, 0, 1, 0, 1.f,1.f),
- SkyboxVertex(-l,-l, l, 0, 1, 0, 0.f,1.f)) );
- meshes.back()->mMaterialIndex = materials.size()-1u;
+ // Update the material of the skybox - replace the name and disable shading for skyboxes.
+ for (unsigned int i = 0; i < 6;++i) {
+ aiMaterial* out = ( aiMaterial* ) (*(materials.end()-(6-i)));
+
+ aiString s;
+ s.length = ::ai_snprintf( s.data, MAXLEN, "SkyboxSide_%u",i );
+ out->AddProperty(&s,AI_MATKEY_NAME);
+
+ int shading = aiShadingMode_NoShading;
+ out->AddProperty(&shading,1,AI_MATKEY_SHADING_MODEL);
+ }
+
+ // Skyboxes are much more difficult. They are represented
+ // by six single planes with different textures, so we'll
+ // need to build six meshes.
+
+ const float l = 10.f; // the size used by Irrlicht
+
+ // FRONT SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex(-l,-l,-l, 0, 0, 1, 1.f,1.f),
+ SkyboxVertex( l,-l,-l, 0, 0, 1, 0.f,1.f),
+ SkyboxVertex( l, l,-l, 0, 0, 1, 0.f,0.f),
+ SkyboxVertex(-l, l,-l, 0, 0, 1, 1.f,0.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-6u;
+
+ // LEFT SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex( l,-l,-l, -1, 0, 0, 1.f,1.f),
+ SkyboxVertex( l,-l, l, -1, 0, 0, 0.f,1.f),
+ SkyboxVertex( l, l, l, -1, 0, 0, 0.f,0.f),
+ SkyboxVertex( l, l,-l, -1, 0, 0, 1.f,0.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-5u;
+
+ // BACK SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex( l,-l, l, 0, 0, -1, 1.f,1.f),
+ SkyboxVertex(-l,-l, l, 0, 0, -1, 0.f,1.f),
+ SkyboxVertex(-l, l, l, 0, 0, -1, 0.f,0.f),
+ SkyboxVertex( l, l, l, 0, 0, -1, 1.f,0.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-4u;
+
+ // RIGHT SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex(-l,-l, l, 1, 0, 0, 1.f,1.f),
+ SkyboxVertex(-l,-l,-l, 1, 0, 0, 0.f,1.f),
+ SkyboxVertex(-l, l,-l, 1, 0, 0, 0.f,0.f),
+ SkyboxVertex(-l, l, l, 1, 0, 0, 1.f,0.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-3u;
+
+ // TOP SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex( l, l,-l, 0, -1, 0, 1.f,1.f),
+ SkyboxVertex( l, l, l, 0, -1, 0, 0.f,1.f),
+ SkyboxVertex(-l, l, l, 0, -1, 0, 0.f,0.f),
+ SkyboxVertex(-l, l,-l, 0, -1, 0, 1.f,0.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-2u;
+
+ // BOTTOM SIDE
+ meshes.push_back( BuildSingleQuadMesh(
+ SkyboxVertex( l,-l, l, 0, 1, 0, 0.f,0.f),
+ SkyboxVertex( l,-l,-l, 0, 1, 0, 1.f,0.f),
+ SkyboxVertex(-l,-l,-l, 0, 1, 0, 1.f,1.f),
+ SkyboxVertex(-l,-l, l, 0, 1, 0, 0.f,1.f)) );
+ meshes.back()->mMaterialIndex = materials.size()-1u;
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
- std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
- unsigned int& defMatIdx,
- aiMesh* mesh)
+ std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
+ unsigned int& defMatIdx,
+ aiMesh* mesh)
{
- if (inmaterials.empty()) {
- // Do we have a default material? If not we need to create one
- if (UINT_MAX == defMatIdx)
- {
- defMatIdx = (unsigned int)materials.size();
- aiMaterial* mat = new aiMaterial();
-
- aiString s;
- s.Set(AI_DEFAULT_MATERIAL_NAME);
- mat->AddProperty(&s,AI_MATKEY_NAME);
-
- aiColor3D c(0.6f,0.6f,0.6f);
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
- }
- mesh->mMaterialIndex = defMatIdx;
- return;
- }
- else if (inmaterials.size() > 1) {
- DefaultLogger::get()->info("IRR: Skipping additional materials");
- }
-
- mesh->mMaterialIndex = (unsigned int)materials.size();
- materials.push_back(inmaterials[0].first);
+ if (inmaterials.empty()) {
+ // Do we have a default material? If not we need to create one
+ if (UINT_MAX == defMatIdx)
+ {
+ defMatIdx = (unsigned int)materials.size();
+ aiMaterial* mat = new aiMaterial();
+
+ aiString s;
+ s.Set(AI_DEFAULT_MATERIAL_NAME);
+ mat->AddProperty(&s,AI_MATKEY_NAME);
+
+ aiColor3D c(0.6f,0.6f,0.6f);
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
+ }
+ mesh->mMaterialIndex = defMatIdx;
+ return;
+ }
+ else if (inmaterials.size() > 1) {
+ DefaultLogger::get()->info("IRR: Skipping additional materials");
+ }
+
+ mesh->mMaterialIndex = (unsigned int)materials.size();
+ materials.push_back(inmaterials[0].first);
}
// ------------------------------------------------------------------------------------------------
inline int ClampSpline(int idx, int size)
{
- return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) );
+ return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) );
}
// ------------------------------------------------------------------------------------------------
inline void FindSuitableMultiple(int& angle)
{
- if (angle < 3)angle = 3;
- else if (angle < 10) angle = 10;
- else if (angle < 20) angle = 20;
- else if (angle < 30) angle = 30;
- else
- {
- }
+ if (angle < 3)angle = 3;
+ else if (angle < 10) angle = 10;
+ else if (angle < 20) angle = 20;
+ else if (angle < 30) angle = 30;
+ else
+ {
+ }
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNodeAnim*>& anims)
{
- ai_assert(NULL != root && NULL != real);
-
- // XXX totally WIP - doesn't produce proper results, need to evaluate
- // whether there's any use for Irrlicht's proprietary scene format
- // outside Irrlicht ...
-
- if (root->animators.empty()) {
- return;
- }
- unsigned int total = 0;
- for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it) {
- if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) {
- DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator");
- continue;
- }
- ++total;
- }
- if (!total)return;
- else if (1 == total) {
- DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators");
- }
-
- // NOTE: 1 tick == i millisecond
-
- unsigned int cur = 0;
- for (std::list<Animator>::iterator it = root->animators.begin();
- it != root->animators.end(); ++it)
- {
- if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)continue;
-
- Animator& in = *it ;
- aiNodeAnim* anim = new aiNodeAnim();
-
- if (cur != total-1) {
- // Build a new name - a prefix instead of a suffix because it is
- // easier to check against
- anim->mNodeName.length = ::sprintf(anim->mNodeName.data,
- "$INST_DUMMY_%i_%s",total-1,
- (root->name.length() ? root->name.c_str() : ""));
-
- // we'll also need to insert a dummy in the node hierarchy.
- aiNode* dummy = new aiNode();
-
- for (unsigned int i = 0; i < real->mParent->mNumChildren;++i)
- if (real->mParent->mChildren[i] == real)
- real->mParent->mChildren[i] = dummy;
-
- dummy->mParent = real->mParent;
- dummy->mName = anim->mNodeName;
-
- dummy->mNumChildren = 1;
- dummy->mChildren = new aiNode*[dummy->mNumChildren];
- dummy->mChildren[0] = real;
-
- // the transformation matrix of the dummy node is the identity
-
- real->mParent = dummy;
- }
- else anim->mNodeName.Set(root->name);
- ++cur;
-
- switch (in.type) {
- case Animator::ROTATION:
- {
- // -----------------------------------------------------
- // find out how long a full rotation will take
- // This is the least common multiple of 360.f and all
- // three euler angles. Although we'll surely find a
- // possible multiple (haha) it could be somewhat large
- // for our purposes. So we need to modify the angles
- // here in order to get good results.
- // -----------------------------------------------------
- int angles[3];
- angles[0] = (int)(in.direction.x*100);
- angles[1] = (int)(in.direction.y*100);
- angles[2] = (int)(in.direction.z*100);
-
- angles[0] %= 360;
- angles[1] %= 360;
- angles[2] %= 360;
-
- if ((angles[0]*angles[1]) && (angles[1]*angles[2]))
- {
- FindSuitableMultiple(angles[0]);
- FindSuitableMultiple(angles[1]);
- FindSuitableMultiple(angles[2]);
- }
-
- int lcm = 360;
-
- if (angles[0])
- lcm = boost::math::lcm(lcm,angles[0]);
-
- if (angles[1])
- lcm = boost::math::lcm(lcm,angles[1]);
-
- if (angles[2])
- lcm = boost::math::lcm(lcm,angles[2]);
-
- if (360 == lcm)
- break;
+ ai_assert(NULL != root && NULL != real);
+
+ // XXX totally WIP - doesn't produce proper results, need to evaluate
+ // whether there's any use for Irrlicht's proprietary scene format
+ // outside Irrlicht ...
+
+ if (root->animators.empty()) {
+ return;
+ }
+ unsigned int total = 0;
+ for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it) {
+ if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) {
+ DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator");
+ continue;
+ }
+ ++total;
+ }
+ if (!total)return;
+ else if (1 == total) {
+ DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators");
+ }
+
+ // NOTE: 1 tick == i millisecond
+
+ unsigned int cur = 0;
+ for (std::list<Animator>::iterator it = root->animators.begin();
+ it != root->animators.end(); ++it)
+ {
+ if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)continue;
+
+ Animator& in = *it ;
+ aiNodeAnim* anim = new aiNodeAnim();
+
+ if (cur != total-1) {
+ // Build a new name - a prefix instead of a suffix because it is
+ // easier to check against
+ anim->mNodeName.length = ::ai_snprintf(anim->mNodeName.data, MAXLEN,
+ "$INST_DUMMY_%i_%s",total-1,
+ (root->name.length() ? root->name.c_str() : ""));
+
+ // we'll also need to insert a dummy in the node hierarchy.
+ aiNode* dummy = new aiNode();
+
+ for (unsigned int i = 0; i < real->mParent->mNumChildren;++i)
+ if (real->mParent->mChildren[i] == real)
+ real->mParent->mChildren[i] = dummy;
+
+ dummy->mParent = real->mParent;
+ dummy->mName = anim->mNodeName;
+
+ dummy->mNumChildren = 1;
+ dummy->mChildren = new aiNode*[dummy->mNumChildren];
+ dummy->mChildren[0] = real;
+
+ // the transformation matrix of the dummy node is the identity
+
+ real->mParent = dummy;
+ }
+ else anim->mNodeName.Set(root->name);
+ ++cur;
+
+ switch (in.type) {
+ case Animator::ROTATION:
+ {
+ // -----------------------------------------------------
+ // find out how long a full rotation will take
+ // This is the least common multiple of 360.f and all
+ // three euler angles. Although we'll surely find a
+ // possible multiple (haha) it could be somewhat large
+ // for our purposes. So we need to modify the angles
+ // here in order to get good results.
+ // -----------------------------------------------------
+ int angles[3];
+ angles[0] = (int)(in.direction.x*100);
+ angles[1] = (int)(in.direction.y*100);
+ angles[2] = (int)(in.direction.z*100);
+
+ angles[0] %= 360;
+ angles[1] %= 360;
+ angles[2] %= 360;
+
+ if ((angles[0]*angles[1]) && (angles[1]*angles[2]))
+ {
+ FindSuitableMultiple(angles[0]);
+ FindSuitableMultiple(angles[1]);
+ FindSuitableMultiple(angles[2]);
+ }
+
+ int lcm = 360;
+
+ if (angles[0])
+ lcm = Math::lcm(lcm,angles[0]);
+
+ if (angles[1])
+ lcm = Math::lcm(lcm,angles[1]);
+
+ if (angles[2])
+ lcm = Math::lcm(lcm,angles[2]);
+
+ if (360 == lcm)
+ break;
#if 0
- // This can be a division through zero, but we don't care
- float f1 = (float)lcm / angles[0];
- float f2 = (float)lcm / angles[1];
- float f3 = (float)lcm / angles[2];
+ // This can be a division through zero, but we don't care
+ float f1 = (float)lcm / angles[0];
+ float f2 = (float)lcm / angles[1];
+ float f3 = (float)lcm / angles[2];
#endif
- // find out how many time units we'll need for the finest
- // track (in seconds) - this defines the number of output
- // keys (fps * seconds)
- float max = 0.f;
- if (angles[0])
- max = (float)lcm / angles[0];
- if (angles[1])
- max = std::max(max, (float)lcm / angles[1]);
- if (angles[2])
- max = std::max(max, (float)lcm / angles[2]);
-
- anim->mNumRotationKeys = (unsigned int)(max*fps);
- anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
-
- // begin with a zero angle
- aiVector3D angle;
- for (unsigned int i = 0; i < anim->mNumRotationKeys;++i)
- {
- // build the quaternion for the given euler angles
- aiQuatKey& q = anim->mRotationKeys[i];
-
- q.mValue = aiQuaternion(angle.x, angle.y, angle.z);
- q.mTime = (double)i;
-
- // increase the angle
- angle += in.direction;
- }
-
- // This animation is repeated and repeated ...
- anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
- }
- break;
-
- case Animator::FLY_CIRCLE:
- {
- // -----------------------------------------------------
- // Find out how much time we'll need to perform a
- // full circle.
- // -----------------------------------------------------
- const double seconds = (1. / in.speed) / 1000.;
- const double tdelta = 1000. / fps;
-
- anim->mNumPositionKeys = (unsigned int) (fps * seconds);
- anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
- // from Irrlicht, what else should we do than copying it?
- aiVector3D vecU,vecV;
- if (in.direction.y) {
- vecV = aiVector3D(50,0,0) ^ in.direction;
- }
- else vecV = aiVector3D(0,50,00) ^ in.direction;
- vecV.Normalize();
- vecU = (vecV ^ in.direction).Normalize();
-
- // build the output keys
- for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
- aiVectorKey& key = anim->mPositionKeys[i];
- key.mTime = i * tdelta;
-
- const float t = (float) ( in.speed * key.mTime );
- key.mValue = in.circleCenter + in.circleRadius * ((vecU*::cosf(t)) + (vecV*::sinf(t)));
- }
-
- // This animation is repeated and repeated ...
- anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
- }
- break;
-
- case Animator::FLY_STRAIGHT:
- {
- anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT);
- const double seconds = in.timeForWay / 1000.;
- const double tdelta = 1000. / fps;
-
- anim->mNumPositionKeys = (unsigned int) (fps * seconds);
- anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
- aiVector3D diff = in.direction - in.circleCenter;
- const float lengthOfWay = diff.Length();
- diff.Normalize();
-
- const double timeFactor = lengthOfWay / in.timeForWay;
-
- // build the output keys
- for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
- aiVectorKey& key = anim->mPositionKeys[i];
- key.mTime = i * tdelta;
- key.mValue = in.circleCenter + diff * float(timeFactor * key.mTime);
- }
- }
- break;
-
- case Animator::FOLLOW_SPLINE:
- {
- // repeat outside the defined time range
- anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
- const int size = (int)in.splineKeys.size();
- if (!size) {
- // We have no point in the spline. That's bad. Really bad.
- DefaultLogger::get()->warn("IRR: Spline animators with no points defined");
-
- delete anim;anim = NULL;
- break;
- }
- else if (size == 1) {
- // We have just one point in the spline so we don't need the full calculation
- anim->mNumPositionKeys = 1;
- anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
- anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue;
- anim->mPositionKeys[0].mTime = 0.f;
- break;
- }
-
- unsigned int ticksPerFull = 15;
- anim->mNumPositionKeys = (unsigned int) ( ticksPerFull * fps );
- anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
-
- for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)
- {
- aiVectorKey& key = anim->mPositionKeys[i];
-
- const float dt = (i * in.speed * 0.001f );
- const float u = dt - std::floor(dt);
- const int idx = (int)std::floor(dt) % size;
-
- // get the 4 current points to evaluate the spline
- const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;
- const aiVector3D& p1 = in.splineKeys[ ClampSpline( idx + 0, size ) ].mValue;
- const aiVector3D& p2 = in.splineKeys[ ClampSpline( idx + 1, size ) ].mValue;
- const aiVector3D& p3 = in.splineKeys[ ClampSpline( idx + 2, size ) ].mValue;
-
- // compute polynomials
- const float u2 = u*u;
- const float u3 = u2*2;
-
- const float h1 = 2.0f * u3 - 3.0f * u2 + 1.0f;
- const float h2 = -2.0f * u3 + 3.0f * u3;
- const float h3 = u3 - 2.0f * u3;
- const float h4 = u3 - u2;
-
- // compute the spline tangents
- const aiVector3D t1 = ( p2 - p0 ) * in.tightness;
- aiVector3D t2 = ( p3 - p1 ) * in.tightness;
-
- // and use them to get the interpolated point
- t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2);
-
- // build a simple translation matrix from it
- key.mValue = t2;
- key.mTime = (double) i;
- }
- }
- break;
- default:
- // UNKNOWN , OTHER
- break;
- };
- if (anim) {
- anims.push_back(anim);
- ++total;
- }
- }
+ // find out how many time units we'll need for the finest
+ // track (in seconds) - this defines the number of output
+ // keys (fps * seconds)
+ float max = 0.f;
+ if (angles[0])
+ max = (float)lcm / angles[0];
+ if (angles[1])
+ max = std::max(max, (float)lcm / angles[1]);
+ if (angles[2])
+ max = std::max(max, (float)lcm / angles[2]);
+
+ anim->mNumRotationKeys = (unsigned int)(max*fps);
+ anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
+
+ // begin with a zero angle
+ aiVector3D angle;
+ for (unsigned int i = 0; i < anim->mNumRotationKeys;++i)
+ {
+ // build the quaternion for the given euler angles
+ aiQuatKey& q = anim->mRotationKeys[i];
+
+ q.mValue = aiQuaternion(angle.x, angle.y, angle.z);
+ q.mTime = (double)i;
+
+ // increase the angle
+ angle += in.direction;
+ }
+
+ // This animation is repeated and repeated ...
+ anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+ }
+ break;
+
+ case Animator::FLY_CIRCLE:
+ {
+ // -----------------------------------------------------
+ // Find out how much time we'll need to perform a
+ // full circle.
+ // -----------------------------------------------------
+ const double seconds = (1. / in.speed) / 1000.;
+ const double tdelta = 1000. / fps;
+
+ anim->mNumPositionKeys = (unsigned int) (fps * seconds);
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+ // from Irrlicht, what else should we do than copying it?
+ aiVector3D vecU,vecV;
+ if (in.direction.y) {
+ vecV = aiVector3D(50,0,0) ^ in.direction;
+ }
+ else vecV = aiVector3D(0,50,00) ^ in.direction;
+ vecV.Normalize();
+ vecU = (vecV ^ in.direction).Normalize();
+
+ // build the output keys
+ for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
+ aiVectorKey& key = anim->mPositionKeys[i];
+ key.mTime = i * tdelta;
+
+ const float t = (float) ( in.speed * key.mTime );
+ key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
+ }
+
+ // This animation is repeated and repeated ...
+ anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+ }
+ break;
+
+ case Animator::FLY_STRAIGHT:
+ {
+ anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT);
+ const double seconds = in.timeForWay / 1000.;
+ const double tdelta = 1000. / fps;
+
+ anim->mNumPositionKeys = (unsigned int) (fps * seconds);
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+ aiVector3D diff = in.direction - in.circleCenter;
+ const float lengthOfWay = diff.Length();
+ diff.Normalize();
+
+ const double timeFactor = lengthOfWay / in.timeForWay;
+
+ // build the output keys
+ for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) {
+ aiVectorKey& key = anim->mPositionKeys[i];
+ key.mTime = i * tdelta;
+ key.mValue = in.circleCenter + diff * float(timeFactor * key.mTime);
+ }
+ }
+ break;
+
+ case Animator::FOLLOW_SPLINE:
+ {
+ // repeat outside the defined time range
+ anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT;
+ const int size = (int)in.splineKeys.size();
+ if (!size) {
+ // We have no point in the spline. That's bad. Really bad.
+ DefaultLogger::get()->warn("IRR: Spline animators with no points defined");
+
+ delete anim;anim = NULL;
+ break;
+ }
+ else if (size == 1) {
+ // We have just one point in the spline so we don't need the full calculation
+ anim->mNumPositionKeys = 1;
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+ anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue;
+ anim->mPositionKeys[0].mTime = 0.f;
+ break;
+ }
+
+ unsigned int ticksPerFull = 15;
+ anim->mNumPositionKeys = (unsigned int) ( ticksPerFull * fps );
+ anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+
+ for (unsigned int i = 0; i < anim->mNumPositionKeys;++i)
+ {
+ aiVectorKey& key = anim->mPositionKeys[i];
+
+ const float dt = (i * in.speed * 0.001f );
+ const float u = dt - std::floor(dt);
+ const int idx = (int)std::floor(dt) % size;
+
+ // get the 4 current points to evaluate the spline
+ const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;
+ const aiVector3D& p1 = in.splineKeys[ ClampSpline( idx + 0, size ) ].mValue;
+ const aiVector3D& p2 = in.splineKeys[ ClampSpline( idx + 1, size ) ].mValue;
+ const aiVector3D& p3 = in.splineKeys[ ClampSpline( idx + 2, size ) ].mValue;
+
+ // compute polynomials
+ const float u2 = u*u;
+ const float u3 = u2*2;
+
+ const float h1 = 2.0f * u3 - 3.0f * u2 + 1.0f;
+ const float h2 = -2.0f * u3 + 3.0f * u3;
+ const float h3 = u3 - 2.0f * u3;
+ const float h4 = u3 - u2;
+
+ // compute the spline tangents
+ const aiVector3D t1 = ( p2 - p0 ) * in.tightness;
+ aiVector3D t2 = ( p3 - p1 ) * in.tightness;
+
+ // and use them to get the interpolated point
+ t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2);
+
+ // build a simple translation matrix from it
+ key.mValue = t2;
+ key.mTime = (double) i;
+ }
+ }
+ break;
+ default:
+ // UNKNOWN , OTHER
+ break;
+ };
+ if (anim) {
+ anims.push_back(anim);
+ ++total;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// This function is maybe more generic than we'd need it here
void SetupMapping (aiMaterial* mat, aiTextureMapping mode, const aiVector3D& axis = aiVector3D(0.f,0.f,-1.f))
{
- // Check whether there are texture properties defined - setup
- // the desired texture mapping mode for all of them and ignore
- // all UV settings we might encounter. WE HAVE NO UVS!
-
- std::vector<aiMaterialProperty*> p;
- p.reserve(mat->mNumProperties+1);
-
- for (unsigned int i = 0; i < mat->mNumProperties;++i)
- {
- aiMaterialProperty* prop = mat->mProperties[i];
- if (!::strcmp( prop->mKey.data, "$tex.file")) {
- // Setup the mapping key
- aiMaterialProperty* m = new aiMaterialProperty();
- m->mKey.Set("$tex.mapping");
- m->mIndex = prop->mIndex;
- m->mSemantic = prop->mSemantic;
- m->mType = aiPTI_Integer;
-
- m->mDataLength = 4;
- m->mData = new char[4];
- *((int*)m->mData) = mode;
-
- p.push_back(prop);
- p.push_back(m);
-
- // Setup the mapping axis
- if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) {
- m = new aiMaterialProperty();
- m->mKey.Set("$tex.mapaxis");
- m->mIndex = prop->mIndex;
- m->mSemantic = prop->mSemantic;
- m->mType = aiPTI_Float;
-
- m->mDataLength = 12;
- m->mData = new char[12];
- *((aiVector3D*)m->mData) = axis;
- p.push_back(m);
- }
- }
- else if (! ::strcmp( prop->mKey.data, "$tex.uvwsrc")) {
- delete mat->mProperties[i];
- }
- else p.push_back(prop);
- }
-
- if (p.empty())return;
-
- // rebuild the output array
- if (p.size() > mat->mNumAllocated) {
- delete[] mat->mProperties;
- mat->mProperties = new aiMaterialProperty*[p.size()*2];
-
- mat->mNumAllocated = p.size()*2;
- }
- mat->mNumProperties = (unsigned int)p.size();
- ::memcpy(mat->mProperties,&p[0],sizeof(void*)*mat->mNumProperties);
+ // Check whether there are texture properties defined - setup
+ // the desired texture mapping mode for all of them and ignore
+ // all UV settings we might encounter. WE HAVE NO UVS!
+
+ std::vector<aiMaterialProperty*> p;
+ p.reserve(mat->mNumProperties+1);
+
+ for (unsigned int i = 0; i < mat->mNumProperties;++i)
+ {
+ aiMaterialProperty* prop = mat->mProperties[i];
+ if (!::strcmp( prop->mKey.data, "$tex.file")) {
+ // Setup the mapping key
+ aiMaterialProperty* m = new aiMaterialProperty();
+ m->mKey.Set("$tex.mapping");
+ m->mIndex = prop->mIndex;
+ m->mSemantic = prop->mSemantic;
+ m->mType = aiPTI_Integer;
+
+ m->mDataLength = 4;
+ m->mData = new char[4];
+ *((int*)m->mData) = mode;
+
+ p.push_back(prop);
+ p.push_back(m);
+
+ // Setup the mapping axis
+ if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) {
+ m = new aiMaterialProperty();
+ m->mKey.Set("$tex.mapaxis");
+ m->mIndex = prop->mIndex;
+ m->mSemantic = prop->mSemantic;
+ m->mType = aiPTI_Float;
+
+ m->mDataLength = 12;
+ m->mData = new char[12];
+ *((aiVector3D*)m->mData) = axis;
+ p.push_back(m);
+ }
+ }
+ else if (! ::strcmp( prop->mKey.data, "$tex.uvwsrc")) {
+ delete mat->mProperties[i];
+ }
+ else p.push_back(prop);
+ }
+
+ if (p.empty())return;
+
+ // rebuild the output array
+ if (p.size() > mat->mNumAllocated) {
+ delete[] mat->mProperties;
+ mat->mProperties = new aiMaterialProperty*[p.size()*2];
+
+ mat->mNumAllocated = p.size()*2;
+ }
+ mat->mNumProperties = (unsigned int)p.size();
+ ::memcpy(mat->mProperties,&p[0],sizeof(void*)*mat->mNumProperties);
}
// ------------------------------------------------------------------------------------------------
void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
- BatchLoader& batch,
- std::vector<aiMesh*>& meshes,
- std::vector<aiNodeAnim*>& anims,
- std::vector<AttachmentInfo>& attach,
- std::vector<aiMaterial*>& materials,
- unsigned int& defMatIdx)
+ BatchLoader& batch,
+ std::vector<aiMesh*>& meshes,
+ std::vector<aiNodeAnim*>& anims,
+ std::vector<AttachmentInfo>& attach,
+ std::vector<aiMaterial*>& materials,
+ unsigned int& defMatIdx)
{
- unsigned int oldMeshSize = (unsigned int)meshes.size();
- //unsigned int meshTrafoAssign = 0;
-
- // Now determine the type of the node
- switch (root->type)
- {
- case Node::ANIMMESH:
- case Node::MESH:
- {
- if (!root->meshPath.length())
- break;
-
- // Get the loaded mesh from the scene and add it to
- // the list of all scenes to be attached to the
- // graph we're currently building
- aiScene* scene = batch.GetImport(root->id);
- if (!scene) {
- DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
- break;
- }
- attach.push_back(AttachmentInfo(scene,rootOut));
-
- // Now combine the material we've loaded for this mesh
- // with the real materials we got from the file. As we
- // don't execute any pp-steps on the file, the numbers
- // should be equal. If they are not, we can impossibly
- // do this ...
- if (root->materials.size() != (unsigned int)scene->mNumMaterials) {
- DefaultLogger::get()->warn("IRR: Failed to match imported materials "
- "with the materials found in the IRR scene file");
-
- break;
- }
- for (unsigned int i = 0; i < scene->mNumMaterials;++i) {
- // Delete the old material, we don't need it anymore
- delete scene->mMaterials[i];
-
- std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
- scene->mMaterials[i] = src.first;
- }
-
- // NOTE: Each mesh should have exactly one material assigned,
- // but we do it in a separate loop if this behaviour changes
- // in future.
- for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
- // Process material flags
- aiMesh* mesh = scene->mMeshes[i];
-
-
- // If "trans_vertex_alpha" mode is enabled, search all vertex colors
- // and check whether they have a common alpha value. This is quite
- // often the case so we can simply extract it to a shared oacity
- // value.
- std::pair<aiMaterial*, unsigned int>& src = root->materials[mesh->mMaterialIndex];
- aiMaterial* mat = (aiMaterial*)src.first;
-
- if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha)
- {
- bool bdo = true;
- for (unsigned int a = 1; a < mesh->mNumVertices;++a) {
-
- if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a) {
- bdo = false;
- break;
- }
- }
- if (bdo) {
- DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity");
-
- for (unsigned int a = 0; a < mesh->mNumVertices;++a)
- mesh->mColors[0][a].a = 1.f;
-
- mat->AddProperty(& mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY);
- }
- }
-
- // If we have a second texture coordinate set and a second texture
- // (either lightmap, normalmap, 2layered material) we need to
- // setup the correct UV index for it. The texture can either
- // be diffuse (lightmap & 2layer) or a normal map (normal & parallax)
- if (mesh->HasTextureCoords(1)) {
-
- int idx = 1;
- if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) {
- mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
- }
- else if (src.second & AI_IRRMESH_MAT_normalmap_solid) {
- mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
- }
- }
- }
- }
- break;
-
- case Node::LIGHT:
- case Node::CAMERA:
-
- // We're already finished with lights and cameras
- break;
-
-
- case Node::SPHERE:
- {
- // Generate the sphere model. Our input parameter to
- // the sphere generation algorithm is the number of
- // subdivisions of each triangle - but here we have
- // the number of poylgons on a specific axis. Just
- // use some hardcoded limits to approximate this ...
- unsigned int mul = root->spherePolyCountX*root->spherePolyCountY;
- if (mul < 100)mul = 2;
- else if (mul < 300)mul = 3;
- else mul = 4;
-
- meshes.push_back(StandardShapes::MakeMesh(mul,
- &StandardShapes::MakeSphere));
-
- // Adjust scaling
- root->scaling *= root->sphereRadius/2;
-
- // Copy one output material
- CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
-
- // Now adjust this output material - if there is a first texture
- // set, setup spherical UV mapping around the Y axis.
- SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_SPHERE);
- }
- break;
-
- case Node::CUBE:
- {
- // Generate an unit cube first
- meshes.push_back(StandardShapes::MakeMesh(
- &StandardShapes::MakeHexahedron));
-
- // Adjust scaling
- root->scaling *= root->sphereRadius;
-
- // Copy one output material
- CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
-
- // Now adjust this output material - if there is a first texture
- // set, setup cubic UV mapping
- SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_BOX );
- }
- break;
-
-
- case Node::SKYBOX:
- {
- // A skybox is defined by six materials
- if (root->materials.size() < 6) {
- DefaultLogger::get()->error("IRR: There should be six materials for a skybox");
- break;
- }
-
- // copy those materials and generate 6 meshes for our new skybox
- materials.reserve(materials.size() + 6);
- for (unsigned int i = 0; i < 6;++i)
- materials.insert(materials.end(),root->materials[i].first);
-
- BuildSkybox(meshes,materials);
-
- // *************************************************************
- // Skyboxes will require a different code path for rendering,
- // so there must be a way for the user to add special support
- // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
- // *************************************************************
- root->name = "IRR.SkyBox_" + root->name;
- DefaultLogger::get()->info("IRR: Loading skybox, this will "
- "require special handling to be displayed correctly");
- }
- break;
-
- case Node::TERRAIN:
- {
- // to support terrains, we'd need to have a texture decoder
- DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN");
- }
- break;
- default:
- // DUMMY
- break;
- };
-
- // Check whether we added a mesh (or more than one ...). In this case
- // we'll also need to attach it to the node
- if (oldMeshSize != (unsigned int) meshes.size()) {
-
- rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize;
- rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes];
-
- for (unsigned int a = 0; a < rootOut->mNumMeshes;++a) {
- rootOut->mMeshes[a] = oldMeshSize+a;
- }
- }
-
- // Setup the name of this node
- rootOut->mName.Set(root->name);
-
- // Now compute the final local transformation matrix of the
- // node from the given translation, rotation and scaling values.
- // (the rotation is given in Euler angles, XYZ order)
- //std::swap((float&)root->rotation.z,(float&)root->rotation.y);
- rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) );
-
- // apply scaling
- aiMatrix4x4& mat = rootOut->mTransformation;
- mat.a1 *= root->scaling.x;
- mat.b1 *= root->scaling.x;
- mat.c1 *= root->scaling.x;
- mat.a2 *= root->scaling.y;
- mat.b2 *= root->scaling.y;
- mat.c2 *= root->scaling.y;
- mat.a3 *= root->scaling.z;
- mat.b3 *= root->scaling.z;
- mat.c3 *= root->scaling.z;
-
- // apply translation
- mat.a4 += root->position.x;
- mat.b4 += root->position.y;
- mat.c4 += root->position.z;
-
- // now compute animations for the node
- ComputeAnimations(root,rootOut, anims);
-
- // Add all children recursively. First allocate enough storage
- // for them, then call us again
- rootOut->mNumChildren = (unsigned int)root->children.size();
- if (rootOut->mNumChildren) {
-
- rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
- for (unsigned int i = 0; i < rootOut->mNumChildren;++i) {
-
- aiNode* node = rootOut->mChildren[i] = new aiNode();
- node->mParent = rootOut;
- GenerateGraph(root->children[i],node,scene,batch,meshes,
- anims,attach,materials,defMatIdx);
- }
- }
+ unsigned int oldMeshSize = (unsigned int)meshes.size();
+ //unsigned int meshTrafoAssign = 0;
+
+ // Now determine the type of the node
+ switch (root->type)
+ {
+ case Node::ANIMMESH:
+ case Node::MESH:
+ {
+ if (!root->meshPath.length())
+ break;
+
+ // Get the loaded mesh from the scene and add it to
+ // the list of all scenes to be attached to the
+ // graph we're currently building
+ aiScene* scene = batch.GetImport(root->id);
+ if (!scene) {
+ DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
+ break;
+ }
+ attach.push_back(AttachmentInfo(scene,rootOut));
+
+ // Now combine the material we've loaded for this mesh
+ // with the real materials we got from the file. As we
+ // don't execute any pp-steps on the file, the numbers
+ // should be equal. If they are not, we can impossibly
+ // do this ...
+ if (root->materials.size() != (unsigned int)scene->mNumMaterials) {
+ DefaultLogger::get()->warn("IRR: Failed to match imported materials "
+ "with the materials found in the IRR scene file");
+
+ break;
+ }
+ for (unsigned int i = 0; i < scene->mNumMaterials;++i) {
+ // Delete the old material, we don't need it anymore
+ delete scene->mMaterials[i];
+
+ std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
+ scene->mMaterials[i] = src.first;
+ }
+
+ // NOTE: Each mesh should have exactly one material assigned,
+ // but we do it in a separate loop if this behaviour changes
+ // in future.
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ // Process material flags
+ aiMesh* mesh = scene->mMeshes[i];
+
+
+ // If "trans_vertex_alpha" mode is enabled, search all vertex colors
+ // and check whether they have a common alpha value. This is quite
+ // often the case so we can simply extract it to a shared oacity
+ // value.
+ std::pair<aiMaterial*, unsigned int>& src = root->materials[mesh->mMaterialIndex];
+ aiMaterial* mat = (aiMaterial*)src.first;
+
+ if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha)
+ {
+ bool bdo = true;
+ for (unsigned int a = 1; a < mesh->mNumVertices;++a) {
+
+ if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a) {
+ bdo = false;
+ break;
+ }
+ }
+ if (bdo) {
+ DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity");
+
+ for (unsigned int a = 0; a < mesh->mNumVertices;++a)
+ mesh->mColors[0][a].a = 1.f;
+
+ mat->AddProperty(& mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY);
+ }
+ }
+
+ // If we have a second texture coordinate set and a second texture
+ // (either lightmap, normalmap, 2layered material) we need to
+ // setup the correct UV index for it. The texture can either
+ // be diffuse (lightmap & 2layer) or a normal map (normal & parallax)
+ if (mesh->HasTextureCoords(1)) {
+
+ int idx = 1;
+ if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) {
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
+ }
+ else if (src.second & AI_IRRMESH_MAT_normalmap_solid) {
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
+ }
+ }
+ }
+ }
+ break;
+
+ case Node::LIGHT:
+ case Node::CAMERA:
+
+ // We're already finished with lights and cameras
+ break;
+
+
+ case Node::SPHERE:
+ {
+ // Generate the sphere model. Our input parameter to
+ // the sphere generation algorithm is the number of
+ // subdivisions of each triangle - but here we have
+ // the number of poylgons on a specific axis. Just
+ // use some hardcoded limits to approximate this ...
+ unsigned int mul = root->spherePolyCountX*root->spherePolyCountY;
+ if (mul < 100)mul = 2;
+ else if (mul < 300)mul = 3;
+ else mul = 4;
+
+ meshes.push_back(StandardShapes::MakeMesh(mul,
+ &StandardShapes::MakeSphere));
+
+ // Adjust scaling
+ root->scaling *= root->sphereRadius/2;
+
+ // Copy one output material
+ CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
+
+ // Now adjust this output material - if there is a first texture
+ // set, setup spherical UV mapping around the Y axis.
+ SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_SPHERE);
+ }
+ break;
+
+ case Node::CUBE:
+ {
+ // Generate an unit cube first
+ meshes.push_back(StandardShapes::MakeMesh(
+ &StandardShapes::MakeHexahedron));
+
+ // Adjust scaling
+ root->scaling *= root->sphereRadius;
+
+ // Copy one output material
+ CopyMaterial(materials, root->materials, defMatIdx, meshes.back());
+
+ // Now adjust this output material - if there is a first texture
+ // set, setup cubic UV mapping
+ SetupMapping ( (aiMaterial*) materials.back(), aiTextureMapping_BOX );
+ }
+ break;
+
+
+ case Node::SKYBOX:
+ {
+ // A skybox is defined by six materials
+ if (root->materials.size() < 6) {
+ DefaultLogger::get()->error("IRR: There should be six materials for a skybox");
+ break;
+ }
+
+ // copy those materials and generate 6 meshes for our new skybox
+ materials.reserve(materials.size() + 6);
+ for (unsigned int i = 0; i < 6;++i)
+ materials.insert(materials.end(),root->materials[i].first);
+
+ BuildSkybox(meshes,materials);
+
+ // *************************************************************
+ // Skyboxes will require a different code path for rendering,
+ // so there must be a way for the user to add special support
+ // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
+ // *************************************************************
+ root->name = "IRR.SkyBox_" + root->name;
+ DefaultLogger::get()->info("IRR: Loading skybox, this will "
+ "require special handling to be displayed correctly");
+ }
+ break;
+
+ case Node::TERRAIN:
+ {
+ // to support terrains, we'd need to have a texture decoder
+ DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN");
+ }
+ break;
+ default:
+ // DUMMY
+ break;
+ };
+
+ // Check whether we added a mesh (or more than one ...). In this case
+ // we'll also need to attach it to the node
+ if (oldMeshSize != (unsigned int) meshes.size()) {
+
+ rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize;
+ rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes];
+
+ for (unsigned int a = 0; a < rootOut->mNumMeshes;++a) {
+ rootOut->mMeshes[a] = oldMeshSize+a;
+ }
+ }
+
+ // Setup the name of this node
+ rootOut->mName.Set(root->name);
+
+ // Now compute the final local transformation matrix of the
+ // node from the given translation, rotation and scaling values.
+ // (the rotation is given in Euler angles, XYZ order)
+ //std::swap((float&)root->rotation.z,(float&)root->rotation.y);
+ rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) );
+
+ // apply scaling
+ aiMatrix4x4& mat = rootOut->mTransformation;
+ mat.a1 *= root->scaling.x;
+ mat.b1 *= root->scaling.x;
+ mat.c1 *= root->scaling.x;
+ mat.a2 *= root->scaling.y;
+ mat.b2 *= root->scaling.y;
+ mat.c2 *= root->scaling.y;
+ mat.a3 *= root->scaling.z;
+ mat.b3 *= root->scaling.z;
+ mat.c3 *= root->scaling.z;
+
+ // apply translation
+ mat.a4 += root->position.x;
+ mat.b4 += root->position.y;
+ mat.c4 += root->position.z;
+
+ // now compute animations for the node
+ ComputeAnimations(root,rootOut, anims);
+
+ // Add all children recursively. First allocate enough storage
+ // for them, then call us again
+ rootOut->mNumChildren = (unsigned int)root->children.size();
+ if (rootOut->mNumChildren) {
+
+ rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
+ for (unsigned int i = 0; i < rootOut->mNumChildren;++i) {
+
+ aiNode* node = rootOut->mChildren[i] = new aiNode();
+ node->mParent = rootOut;
+ GenerateGraph(root->children[i],node,scene,batch,meshes,
+ anims,attach,materials,defMatIdx);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void IRRImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void IRRImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open IRR file " + pFile + "");
-
- // Construct the irrXML parser
- CIrrXML_IOStreamReader st(file.get());
- reader = createIrrXMLReader((IFileReadCallBack*) &st);
-
- // The root node of the scene
- Node* root = new Node(Node::DUMMY);
- root->parent = NULL;
- root->name = "<IRRSceneRoot>";
-
- // Current node parent
- Node* curParent = root;
-
- // Scenegraph node we're currently working on
- Node* curNode = NULL;
-
- // List of output cameras
- std::vector<aiCamera*> cameras;
-
- // List of output lights
- std::vector<aiLight*> lights;
-
- // Batch loader used to load external models
- BatchLoader batch(pIOHandler);
-// batch.SetBasePath(pFile);
-
- cameras.reserve(5);
- lights.reserve(5);
-
- bool inMaterials = false, inAnimator = false;
- unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
-
- // Parse the XML file
- while (reader->read()) {
- switch (reader->getNodeType()) {
- case EXN_ELEMENT:
-
- if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
- // ***********************************************************************
- /* What we're going to do with the node depends
- * on its type:
- *
- * "mesh" - Load a mesh from an external file
- * "cube" - Generate a cube
- * "skybox" - Generate a skybox
- * "light" - A light source
- * "sphere" - Generate a sphere mesh
- * "animatedMesh" - Load an animated mesh from an external file
- * and join its animation channels with ours.
- * "empty" - A dummy node
- * "camera" - A camera
- * "terrain" - a terrain node (data comes from a heightmap)
- * "billboard", ""
- *
- * Each of these nodes can be animated and all can have multiple
- * materials assigned (except lights, cameras and dummies, of course).
- */
- // ***********************************************************************
- const char* sz = reader->getAttributeValueSafe("type");
- Node* nd;
- if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree")) {
- // OctTree's and meshes are treated equally
- nd = new Node(Node::MESH);
- }
- else if (!ASSIMP_stricmp(sz,"cube")) {
- nd = new Node(Node::CUBE);
- ++guessedMeshCnt;
- // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
- }
- else if (!ASSIMP_stricmp(sz,"skybox")) {
- nd = new Node(Node::SKYBOX);
- guessedMeshCnt += 6;
- }
- else if (!ASSIMP_stricmp(sz,"camera")) {
- nd = new Node(Node::CAMERA);
-
- // Setup a temporary name for the camera
- aiCamera* cam = new aiCamera();
- cam->mName.Set( nd->name );
- cameras.push_back(cam);
- }
- else if (!ASSIMP_stricmp(sz,"light")) {
- nd = new Node(Node::LIGHT);
-
- // Setup a temporary name for the light
- aiLight* cam = new aiLight();
- cam->mName.Set( nd->name );
- lights.push_back(cam);
- }
- else if (!ASSIMP_stricmp(sz,"sphere")) {
- nd = new Node(Node::SPHERE);
- ++guessedMeshCnt;
- }
- else if (!ASSIMP_stricmp(sz,"animatedMesh")) {
- nd = new Node(Node::ANIMMESH);
- }
- else if (!ASSIMP_stricmp(sz,"empty")) {
- nd = new Node(Node::DUMMY);
- }
- else if (!ASSIMP_stricmp(sz,"terrain")) {
- nd = new Node(Node::TERRAIN);
- }
- else if (!ASSIMP_stricmp(sz,"billBoard")) {
- // We don't support billboards, so ignore them
- DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp");
- nd = new Node(Node::DUMMY);
- }
- else {
- DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
-
- /* We skip the contents of nodes we don't know.
- * We parse the transformation and all animators
- * and skip the rest.
- */
- nd = new Node(Node::DUMMY);
- }
-
- /* Attach the newly created node to the scenegraph
- */
- curNode = nd;
- nd->parent = curParent;
- curParent->children.push_back(nd);
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
- inMaterials = true;
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
- inAnimator = true;
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
- /* We should have a valid node here
- * FIX: no ... the scene root node is also contained in an attributes block
- */
- if (!curNode) {
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open IRR file " + pFile + "");
+
+ // Construct the irrXML parser
+ CIrrXML_IOStreamReader st(file.get());
+ reader = createIrrXMLReader((IFileReadCallBack*) &st);
+
+ // The root node of the scene
+ Node* root = new Node(Node::DUMMY);
+ root->parent = NULL;
+ root->name = "<IRRSceneRoot>";
+
+ // Current node parent
+ Node* curParent = root;
+
+ // Scenegraph node we're currently working on
+ Node* curNode = NULL;
+
+ // List of output cameras
+ std::vector<aiCamera*> cameras;
+
+ // List of output lights
+ std::vector<aiLight*> lights;
+
+ // Batch loader used to load external models
+ BatchLoader batch(pIOHandler);
+// batch.SetBasePath(pFile);
+
+ cameras.reserve(5);
+ lights.reserve(5);
+
+ bool inMaterials = false, inAnimator = false;
+ unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0;
+
+ // Parse the XML file
+ while (reader->read()) {
+ switch (reader->getNodeType()) {
+ case EXN_ELEMENT:
+
+ if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
+ // ***********************************************************************
+ /* What we're going to do with the node depends
+ * on its type:
+ *
+ * "mesh" - Load a mesh from an external file
+ * "cube" - Generate a cube
+ * "skybox" - Generate a skybox
+ * "light" - A light source
+ * "sphere" - Generate a sphere mesh
+ * "animatedMesh" - Load an animated mesh from an external file
+ * and join its animation channels with ours.
+ * "empty" - A dummy node
+ * "camera" - A camera
+ * "terrain" - a terrain node (data comes from a heightmap)
+ * "billboard", ""
+ *
+ * Each of these nodes can be animated and all can have multiple
+ * materials assigned (except lights, cameras and dummies, of course).
+ */
+ // ***********************************************************************
+ const char* sz = reader->getAttributeValueSafe("type");
+ Node* nd;
+ if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree")) {
+ // OctTree's and meshes are treated equally
+ nd = new Node(Node::MESH);
+ }
+ else if (!ASSIMP_stricmp(sz,"cube")) {
+ nd = new Node(Node::CUBE);
+ ++guessedMeshCnt;
+ // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
+ }
+ else if (!ASSIMP_stricmp(sz,"skybox")) {
+ nd = new Node(Node::SKYBOX);
+ guessedMeshCnt += 6;
+ }
+ else if (!ASSIMP_stricmp(sz,"camera")) {
+ nd = new Node(Node::CAMERA);
+
+ // Setup a temporary name for the camera
+ aiCamera* cam = new aiCamera();
+ cam->mName.Set( nd->name );
+ cameras.push_back(cam);
+ }
+ else if (!ASSIMP_stricmp(sz,"light")) {
+ nd = new Node(Node::LIGHT);
+
+ // Setup a temporary name for the light
+ aiLight* cam = new aiLight();
+ cam->mName.Set( nd->name );
+ lights.push_back(cam);
+ }
+ else if (!ASSIMP_stricmp(sz,"sphere")) {
+ nd = new Node(Node::SPHERE);
+ ++guessedMeshCnt;
+ }
+ else if (!ASSIMP_stricmp(sz,"animatedMesh")) {
+ nd = new Node(Node::ANIMMESH);
+ }
+ else if (!ASSIMP_stricmp(sz,"empty")) {
+ nd = new Node(Node::DUMMY);
+ }
+ else if (!ASSIMP_stricmp(sz,"terrain")) {
+ nd = new Node(Node::TERRAIN);
+ }
+ else if (!ASSIMP_stricmp(sz,"billBoard")) {
+ // We don't support billboards, so ignore them
+ DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp");
+ nd = new Node(Node::DUMMY);
+ }
+ else {
+ DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
+
+ /* We skip the contents of nodes we don't know.
+ * We parse the transformation and all animators
+ * and skip the rest.
+ */
+ nd = new Node(Node::DUMMY);
+ }
+
+ /* Attach the newly created node to the scenegraph
+ */
+ curNode = nd;
+ nd->parent = curParent;
+ curParent->children.push_back(nd);
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
+ inMaterials = true;
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
+ inAnimator = true;
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
+ /* We should have a valid node here
+ * FIX: no ... the scene root node is also contained in an attributes block
+ */
+ if (!curNode) {
#if 0
- DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
- "there is no node active");
+ DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
+ "there is no node active");
#endif
- continue;
- }
-
- Animator* curAnim = NULL;
-
- // Materials can occur for nearly any type of node
- if (inMaterials && curNode->type != Node::DUMMY) {
- /* This is a material description - parse it!
- */
- curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () );
- std::pair< aiMaterial*, unsigned int >& p = curNode->materials.back();
-
- p.first = ParseMaterial(p.second);
-
- ++guessedMatCnt;
- continue;
- }
- else if (inAnimator) {
- /* This is an animation path - add a new animator
- * to the list.
- */
- curNode->animators.push_back(Animator());
- curAnim = & curNode->animators.back();
-
- ++guessedAnimCnt;
- }
-
- /* Parse all elements in the attributes block
- * and process them.
- */
- while (reader->read()) {
- if (reader->getNodeType() == EXN_ELEMENT) {
- if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d")) {
- VectorProperty prop;
- ReadVectorProperty(prop);
-
- if (inAnimator) {
- if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
- // We store the rotation euler angles in 'direction'
- curAnim->direction = prop.value;
- }
- else if (curAnim->type == Animator::FOLLOW_SPLINE) {
- // Check whether the vector follows the PointN naming scheme,
- // here N is the ONE-based index of the point
- if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point") {
- // Add a new key to the list
- curAnim->splineKeys.push_back(aiVectorKey());
- aiVectorKey& key = curAnim->splineKeys.back();
-
- // and parse its properties
- key.mValue = prop.value;
- key.mTime = strtoul10(&prop.name[5]);
- }
- }
- else if (curAnim->type == Animator::FLY_CIRCLE) {
- if (prop.name == "Center") {
- curAnim->circleCenter = prop.value;
- }
- else if (prop.name == "Direction") {
- curAnim->direction = prop.value;
-
- // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
- if (curAnim->direction == aiVector3D()) {
- curAnim->direction = aiVector3D(0.f,1.f,0.f);
- }
- else curAnim->direction.Normalize();
- }
- }
- else if (curAnim->type == Animator::FLY_STRAIGHT) {
- if (prop.name == "Start") {
- // We reuse the field here
- curAnim->circleCenter = prop.value;
- }
- else if (prop.name == "End") {
- // We reuse the field here
- curAnim->direction = prop.value;
- }
- }
- }
- else {
- if (prop.name == "Position") {
- curNode->position = prop.value;
- }
- else if (prop.name == "Rotation") {
- curNode->rotation = prop.value;
- }
- else if (prop.name == "Scale") {
- curNode->scaling = prop.value;
- }
- else if (Node::CAMERA == curNode->type)
- {
- aiCamera* cam = cameras.back();
- if (prop.name == "Target") {
- cam->mLookAt = prop.value;
- }
- else if (prop.name == "UpVector") {
- cam->mUp = prop.value;
- }
- }
- }
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) {
- BoolProperty prop;
- ReadBoolProperty(prop);
-
- if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
- curAnim->loop = prop.value;
- }
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) {
- FloatProperty prop;
- ReadFloatProperty(prop);
-
- if (inAnimator) {
- // The speed property exists for several animators
- if (prop.name == "Speed") {
- curAnim->speed = prop.value;
- }
- else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
- curAnim->circleRadius = prop.value;
- }
- else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
- curAnim->tightness = prop.value;
- }
- }
- else {
- if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
- curNode->framesPerSecond = prop.value;
- }
- else if (Node::CAMERA == curNode->type) {
- /* This is the vertical, not the horizontal FOV.
- * We need to compute the right FOV from the
- * screen aspect which we don't know yet.
- */
- if (prop.name == "Fovy") {
- cameras.back()->mHorizontalFOV = prop.value;
- }
- else if (prop.name == "Aspect") {
- cameras.back()->mAspect = prop.value;
- }
- else if (prop.name == "ZNear") {
- cameras.back()->mClipPlaneNear = prop.value;
- }
- else if (prop.name == "ZFar") {
- cameras.back()->mClipPlaneFar = prop.value;
- }
- }
- else if (Node::LIGHT == curNode->type) {
- /* Additional light information
- */
- if (prop.name == "Attenuation") {
- lights.back()->mAttenuationLinear = prop.value;
- }
- else if (prop.name == "OuterCone") {
- lights.back()->mAngleOuterCone = AI_DEG_TO_RAD( prop.value );
- }
- else if (prop.name == "InnerCone") {
- lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
- }
- }
- // radius of the sphere to be generated -
- // or alternatively, size of the cube
- else if ((Node::SPHERE == curNode->type && prop.name == "Radius")
- || (Node::CUBE == curNode->type && prop.name == "Size" )) {
-
- curNode->sphereRadius = prop.value;
- }
- }
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"int")) {
- IntProperty prop;
- ReadIntProperty(prop);
-
- if (inAnimator) {
- if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") {
- curAnim->timeForWay = prop.value;
- }
- }
- else {
- // sphere polgon numbers in each direction
- if (Node::SPHERE == curNode->type) {
-
- if (prop.name == "PolyCountX") {
- curNode->spherePolyCountX = prop.value;
- }
- else if (prop.name == "PolyCountY") {
- curNode->spherePolyCountY = prop.value;
- }
- }
- }
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum")) {
- StringProperty prop;
- ReadStringProperty(prop);
- if (prop.value.length()) {
- if (prop.name == "Name") {
- curNode->name = prop.value;
-
- /* If we're either a camera or a light source
- * we need to update the name in the aiLight/
- * aiCamera structure, too.
- */
- if (Node::CAMERA == curNode->type) {
- cameras.back()->mName.Set(prop.value);
- }
- else if (Node::LIGHT == curNode->type) {
- lights.back()->mName.Set(prop.value);
- }
- }
- else if (Node::LIGHT == curNode->type && "LightType" == prop.name)
- {
- if (prop.value == "Spot")
- lights.back()->mType = aiLightSource_SPOT;
- else if (prop.value == "Point")
- lights.back()->mType = aiLightSource_POINT;
- else if (prop.value == "Directional")
- lights.back()->mType = aiLightSource_DIRECTIONAL;
- else
- {
- // We won't pass the validation with aiLightSourceType_UNDEFINED,
- // so we remove the light and replace it with a silly dummy node
- delete lights.back();
- lights.pop_back();
- curNode->type = Node::DUMMY;
-
- DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value);
- }
- }
- else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
- Node::ANIMMESH == curNode->type)
- {
- /* This is the file name of the mesh - either
- * animated or not. We need to make sure we setup
- * the correct postprocessing settings here.
- */
- unsigned int pp = 0;
- BatchLoader::PropertyMap map;
-
- /* If the mesh is a static one remove all animations from the impor data
- */
- if (Node::ANIMMESH != curNode->type) {
- pp |= aiProcess_RemoveComponent;
- SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS,
- aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
- }
-
- /* TODO: maybe implement the protection against recursive
- * loading calls directly in BatchLoader? The current
- * implementation is not absolutely safe. A LWS and an IRR
- * file referencing each other *could* cause the system to
- * recurse forever.
- */
-
- const std::string extension = GetExtension(prop.value);
- if ("irr" == extension) {
- DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
- }
- else
- {
- curNode->id = batch.AddLoadRequest(prop.value,pp,&map);
- curNode->meshPath = prop.value;
- }
- }
- else if (inAnimator && prop.name == "Type")
- {
- // type of the animator
- if (prop.value == "rotation") {
- curAnim->type = Animator::ROTATION;
- }
- else if (prop.value == "flyCircle") {
- curAnim->type = Animator::FLY_CIRCLE;
- }
- else if (prop.value == "flyStraight") {
- curAnim->type = Animator::FLY_CIRCLE;
- }
- else if (prop.value == "followSpline") {
- curAnim->type = Animator::FOLLOW_SPLINE;
- }
- else {
- DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
- + prop.value);
-
- curAnim->type = Animator::UNKNOWN;
- }
- }
- }
- }
- }
- else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
- break;
- }
- }
- }
- break;
-
- case EXN_ELEMENT_END:
-
- // If we reached the end of a node, we need to continue processing its parent
- if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
- if (!curNode) {
- // currently is no node set. We need to go
- // back in the node hierarchy
- if (!curParent) {
- curParent = root;
- DefaultLogger::get()->error("IRR: Too many closing <node> elements");
- }
- else curParent = curParent->parent;
- }
- else curNode = NULL;
- }
- // clear all flags
- else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
- inMaterials = false;
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
- inAnimator = false;
- }
- break;
-
- default:
- // GCC complains that not all enumeration values are handled
- break;
- }
- }
-
- /* Now iterate through all cameras and compute their final (horizontal) FOV
- */
- for (std::vector<aiCamera*>::iterator it = cameras.begin(), end = cameras.end();it != end; ++it) {
- aiCamera* cam = *it;
-
- // screen aspect could be missing
- if (cam->mAspect) {
- cam->mHorizontalFOV *= cam->mAspect;
- }
- else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
- }
-
- batch.LoadAll();
-
- /* Allocate a tempoary scene data structure
- */
- aiScene* tempScene = new aiScene();
- tempScene->mRootNode = new aiNode();
- tempScene->mRootNode->mName.Set("<IRRRoot>");
-
- /* Copy the cameras to the output array
- */
- if (!cameras.empty()) {
- tempScene->mNumCameras = (unsigned int)cameras.size();
- tempScene->mCameras = new aiCamera*[tempScene->mNumCameras];
- ::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras);
- }
-
- /* Copy the light sources to the output array
- */
- if (!lights.empty()) {
- tempScene->mNumLights = (unsigned int)lights.size();
- tempScene->mLights = new aiLight*[tempScene->mNumLights];
- ::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
- }
-
- // temporary data
- std::vector< aiNodeAnim*> anims;
- std::vector< aiMaterial*> materials;
- std::vector< AttachmentInfo > attach;
- std::vector<aiMesh*> meshes;
-
- // try to guess how much storage we'll need
- anims.reserve (guessedAnimCnt + (guessedAnimCnt >> 2));
- meshes.reserve (guessedMeshCnt + (guessedMeshCnt >> 2));
- materials.reserve (guessedMatCnt + (guessedMatCnt >> 2));
-
- /* Now process our scenegraph recursively: generate final
- * meshes and generate animation channels for all nodes.
- */
- unsigned int defMatIdx = UINT_MAX;
- GenerateGraph(root,tempScene->mRootNode, tempScene,
- batch, meshes, anims, attach, materials, defMatIdx);
-
- if (!anims.empty())
- {
- tempScene->mNumAnimations = 1;
- tempScene->mAnimations = new aiAnimation*[tempScene->mNumAnimations];
- aiAnimation* an = tempScene->mAnimations[0] = new aiAnimation();
-
- // ***********************************************************
- // This is only the global animation channel of the scene.
- // If there are animated models, they will have separate
- // animation channels in the scene. To display IRR scenes
- // correctly, users will need to combine the global anim
- // channel with all the local animations they want to play
- // ***********************************************************
- an->mName.Set("Irr_GlobalAnimChannel");
-
- // copy all node animation channels to the global channel
- an->mNumChannels = (unsigned int)anims.size();
- an->mChannels = new aiNodeAnim*[an->mNumChannels];
- ::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels);
- }
- if (!meshes.empty()) {
- // copy all meshes to the temporary scene
- tempScene->mNumMeshes = (unsigned int)meshes.size();
- tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
- ::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes*
- sizeof(void*));
- }
-
- /* Copy all materials to the output array
- */
- if (!materials.empty()) {
- tempScene->mNumMaterials = (unsigned int)materials.size();
- tempScene->mMaterials = new aiMaterial*[tempScene->mNumMaterials];
- ::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)*
- tempScene->mNumMaterials);
- }
-
- /* Now merge all sub scenes and attach them to the correct
- * attachment points in the scenegraph.
- */
- SceneCombiner::MergeScenes(&pScene,tempScene,attach,
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
-
-
- /* If we have no meshes | no materials now set the INCOMPLETE
- * scene flag. This is necessary if we failed to load all
- * models from external files
- */
- if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
- DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- }
-
- /* Finished ... everything destructs automatically and all
- * temporary scenes have already been deleted by MergeScenes()
- */
- return;
+ continue;
+ }
+
+ Animator* curAnim = NULL;
+
+ // Materials can occur for nearly any type of node
+ if (inMaterials && curNode->type != Node::DUMMY) {
+ /* This is a material description - parse it!
+ */
+ curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () );
+ std::pair< aiMaterial*, unsigned int >& p = curNode->materials.back();
+
+ p.first = ParseMaterial(p.second);
+
+ ++guessedMatCnt;
+ continue;
+ }
+ else if (inAnimator) {
+ /* This is an animation path - add a new animator
+ * to the list.
+ */
+ curNode->animators.push_back(Animator());
+ curAnim = & curNode->animators.back();
+
+ ++guessedAnimCnt;
+ }
+
+ /* Parse all elements in the attributes block
+ * and process them.
+ */
+ while (reader->read()) {
+ if (reader->getNodeType() == EXN_ELEMENT) {
+ if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d")) {
+ VectorProperty prop;
+ ReadVectorProperty(prop);
+
+ if (inAnimator) {
+ if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") {
+ // We store the rotation euler angles in 'direction'
+ curAnim->direction = prop.value;
+ }
+ else if (curAnim->type == Animator::FOLLOW_SPLINE) {
+ // Check whether the vector follows the PointN naming scheme,
+ // here N is the ONE-based index of the point
+ if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point") {
+ // Add a new key to the list
+ curAnim->splineKeys.push_back(aiVectorKey());
+ aiVectorKey& key = curAnim->splineKeys.back();
+
+ // and parse its properties
+ key.mValue = prop.value;
+ key.mTime = strtoul10(&prop.name[5]);
+ }
+ }
+ else if (curAnim->type == Animator::FLY_CIRCLE) {
+ if (prop.name == "Center") {
+ curAnim->circleCenter = prop.value;
+ }
+ else if (prop.name == "Direction") {
+ curAnim->direction = prop.value;
+
+ // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1
+ if (curAnim->direction == aiVector3D()) {
+ curAnim->direction = aiVector3D(0.f,1.f,0.f);
+ }
+ else curAnim->direction.Normalize();
+ }
+ }
+ else if (curAnim->type == Animator::FLY_STRAIGHT) {
+ if (prop.name == "Start") {
+ // We reuse the field here
+ curAnim->circleCenter = prop.value;
+ }
+ else if (prop.name == "End") {
+ // We reuse the field here
+ curAnim->direction = prop.value;
+ }
+ }
+ }
+ else {
+ if (prop.name == "Position") {
+ curNode->position = prop.value;
+ }
+ else if (prop.name == "Rotation") {
+ curNode->rotation = prop.value;
+ }
+ else if (prop.name == "Scale") {
+ curNode->scaling = prop.value;
+ }
+ else if (Node::CAMERA == curNode->type)
+ {
+ aiCamera* cam = cameras.back();
+ if (prop.name == "Target") {
+ cam->mLookAt = prop.value;
+ }
+ else if (prop.name == "UpVector") {
+ cam->mUp = prop.value;
+ }
+ }
+ }
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) {
+ BoolProperty prop;
+ ReadBoolProperty(prop);
+
+ if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") {
+ curAnim->loop = prop.value;
+ }
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) {
+ FloatProperty prop;
+ ReadFloatProperty(prop);
+
+ if (inAnimator) {
+ // The speed property exists for several animators
+ if (prop.name == "Speed") {
+ curAnim->speed = prop.value;
+ }
+ else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") {
+ curAnim->circleRadius = prop.value;
+ }
+ else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") {
+ curAnim->tightness = prop.value;
+ }
+ }
+ else {
+ if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) {
+ curNode->framesPerSecond = prop.value;
+ }
+ else if (Node::CAMERA == curNode->type) {
+ /* This is the vertical, not the horizontal FOV.
+ * We need to compute the right FOV from the
+ * screen aspect which we don't know yet.
+ */
+ if (prop.name == "Fovy") {
+ cameras.back()->mHorizontalFOV = prop.value;
+ }
+ else if (prop.name == "Aspect") {
+ cameras.back()->mAspect = prop.value;
+ }
+ else if (prop.name == "ZNear") {
+ cameras.back()->mClipPlaneNear = prop.value;
+ }
+ else if (prop.name == "ZFar") {
+ cameras.back()->mClipPlaneFar = prop.value;
+ }
+ }
+ else if (Node::LIGHT == curNode->type) {
+ /* Additional light information
+ */
+ if (prop.name == "Attenuation") {
+ lights.back()->mAttenuationLinear = prop.value;
+ }
+ else if (prop.name == "OuterCone") {
+ lights.back()->mAngleOuterCone = AI_DEG_TO_RAD( prop.value );
+ }
+ else if (prop.name == "InnerCone") {
+ lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
+ }
+ }
+ // radius of the sphere to be generated -
+ // or alternatively, size of the cube
+ else if ((Node::SPHERE == curNode->type && prop.name == "Radius")
+ || (Node::CUBE == curNode->type && prop.name == "Size" )) {
+
+ curNode->sphereRadius = prop.value;
+ }
+ }
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"int")) {
+ IntProperty prop;
+ ReadIntProperty(prop);
+
+ if (inAnimator) {
+ if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") {
+ curAnim->timeForWay = prop.value;
+ }
+ }
+ else {
+ // sphere polgon numbers in each direction
+ if (Node::SPHERE == curNode->type) {
+
+ if (prop.name == "PolyCountX") {
+ curNode->spherePolyCountX = prop.value;
+ }
+ else if (prop.name == "PolyCountY") {
+ curNode->spherePolyCountY = prop.value;
+ }
+ }
+ }
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum")) {
+ StringProperty prop;
+ ReadStringProperty(prop);
+ if (prop.value.length()) {
+ if (prop.name == "Name") {
+ curNode->name = prop.value;
+
+ /* If we're either a camera or a light source
+ * we need to update the name in the aiLight/
+ * aiCamera structure, too.
+ */
+ if (Node::CAMERA == curNode->type) {
+ cameras.back()->mName.Set(prop.value);
+ }
+ else if (Node::LIGHT == curNode->type) {
+ lights.back()->mName.Set(prop.value);
+ }
+ }
+ else if (Node::LIGHT == curNode->type && "LightType" == prop.name)
+ {
+ if (prop.value == "Spot")
+ lights.back()->mType = aiLightSource_SPOT;
+ else if (prop.value == "Point")
+ lights.back()->mType = aiLightSource_POINT;
+ else if (prop.value == "Directional")
+ lights.back()->mType = aiLightSource_DIRECTIONAL;
+ else
+ {
+ // We won't pass the validation with aiLightSourceType_UNDEFINED,
+ // so we remove the light and replace it with a silly dummy node
+ delete lights.back();
+ lights.pop_back();
+ curNode->type = Node::DUMMY;
+
+ DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value);
+ }
+ }
+ else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
+ Node::ANIMMESH == curNode->type)
+ {
+ /* This is the file name of the mesh - either
+ * animated or not. We need to make sure we setup
+ * the correct postprocessing settings here.
+ */
+ unsigned int pp = 0;
+ BatchLoader::PropertyMap map;
+
+ /* If the mesh is a static one remove all animations from the impor data
+ */
+ if (Node::ANIMMESH != curNode->type) {
+ pp |= aiProcess_RemoveComponent;
+ SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS,
+ aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS);
+ }
+
+ /* TODO: maybe implement the protection against recursive
+ * loading calls directly in BatchLoader? The current
+ * implementation is not absolutely safe. A LWS and an IRR
+ * file referencing each other *could* cause the system to
+ * recurse forever.
+ */
+
+ const std::string extension = GetExtension(prop.value);
+ if ("irr" == extension) {
+ DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
+ }
+ else
+ {
+ curNode->id = batch.AddLoadRequest(prop.value,pp,&map);
+ curNode->meshPath = prop.value;
+ }
+ }
+ else if (inAnimator && prop.name == "Type")
+ {
+ // type of the animator
+ if (prop.value == "rotation") {
+ curAnim->type = Animator::ROTATION;
+ }
+ else if (prop.value == "flyCircle") {
+ curAnim->type = Animator::FLY_CIRCLE;
+ }
+ else if (prop.value == "flyStraight") {
+ curAnim->type = Animator::FLY_CIRCLE;
+ }
+ else if (prop.value == "followSpline") {
+ curAnim->type = Animator::FOLLOW_SPLINE;
+ }
+ else {
+ DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
+ + prop.value);
+
+ curAnim->type = Animator::UNKNOWN;
+ }
+ }
+ }
+ }
+ }
+ else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes")) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case EXN_ELEMENT_END:
+
+ // If we reached the end of a node, we need to continue processing its parent
+ if (!ASSIMP_stricmp(reader->getNodeName(),"node")) {
+ if (!curNode) {
+ // currently is no node set. We need to go
+ // back in the node hierarchy
+ if (!curParent) {
+ curParent = root;
+ DefaultLogger::get()->error("IRR: Too many closing <node> elements");
+ }
+ else curParent = curParent->parent;
+ }
+ else curNode = NULL;
+ }
+ // clear all flags
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) {
+ inMaterials = false;
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) {
+ inAnimator = false;
+ }
+ break;
+
+ default:
+ // GCC complains that not all enumeration values are handled
+ break;
+ }
+ }
+
+ /* Now iterate through all cameras and compute their final (horizontal) FOV
+ */
+ for (aiCamera *cam : cameras) {
+
+ // screen aspect could be missing
+ if (cam->mAspect) {
+ cam->mHorizontalFOV *= cam->mAspect;
+ }
+ else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
+ }
+
+ batch.LoadAll();
+
+ /* Allocate a tempoary scene data structure
+ */
+ aiScene* tempScene = new aiScene();
+ tempScene->mRootNode = new aiNode();
+ tempScene->mRootNode->mName.Set("<IRRRoot>");
+
+ /* Copy the cameras to the output array
+ */
+ if (!cameras.empty()) {
+ tempScene->mNumCameras = (unsigned int)cameras.size();
+ tempScene->mCameras = new aiCamera*[tempScene->mNumCameras];
+ ::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras);
+ }
+
+ /* Copy the light sources to the output array
+ */
+ if (!lights.empty()) {
+ tempScene->mNumLights = (unsigned int)lights.size();
+ tempScene->mLights = new aiLight*[tempScene->mNumLights];
+ ::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
+ }
+
+ // temporary data
+ std::vector< aiNodeAnim*> anims;
+ std::vector< aiMaterial*> materials;
+ std::vector< AttachmentInfo > attach;
+ std::vector<aiMesh*> meshes;
+
+ // try to guess how much storage we'll need
+ anims.reserve (guessedAnimCnt + (guessedAnimCnt >> 2));
+ meshes.reserve (guessedMeshCnt + (guessedMeshCnt >> 2));
+ materials.reserve (guessedMatCnt + (guessedMatCnt >> 2));
+
+ /* Now process our scenegraph recursively: generate final
+ * meshes and generate animation channels for all nodes.
+ */
+ unsigned int defMatIdx = UINT_MAX;
+ GenerateGraph(root,tempScene->mRootNode, tempScene,
+ batch, meshes, anims, attach, materials, defMatIdx);
+
+ if (!anims.empty())
+ {
+ tempScene->mNumAnimations = 1;
+ tempScene->mAnimations = new aiAnimation*[tempScene->mNumAnimations];
+ aiAnimation* an = tempScene->mAnimations[0] = new aiAnimation();
+
+ // ***********************************************************
+ // This is only the global animation channel of the scene.
+ // If there are animated models, they will have separate
+ // animation channels in the scene. To display IRR scenes
+ // correctly, users will need to combine the global anim
+ // channel with all the local animations they want to play
+ // ***********************************************************
+ an->mName.Set("Irr_GlobalAnimChannel");
+
+ // copy all node animation channels to the global channel
+ an->mNumChannels = (unsigned int)anims.size();
+ an->mChannels = new aiNodeAnim*[an->mNumChannels];
+ ::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels);
+ }
+ if (!meshes.empty()) {
+ // copy all meshes to the temporary scene
+ tempScene->mNumMeshes = (unsigned int)meshes.size();
+ tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
+ ::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes*
+ sizeof(void*));
+ }
+
+ /* Copy all materials to the output array
+ */
+ if (!materials.empty()) {
+ tempScene->mNumMaterials = (unsigned int)materials.size();
+ tempScene->mMaterials = new aiMaterial*[tempScene->mNumMaterials];
+ ::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)*
+ tempScene->mNumMaterials);
+ }
+
+ /* Now merge all sub scenes and attach them to the correct
+ * attachment points in the scenegraph.
+ */
+ SceneCombiner::MergeScenes(&pScene,tempScene,attach,
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
+
+
+ /* If we have no meshes | no materials now set the INCOMPLETE
+ * scene flag. This is necessary if we failed to load all
+ * models from external files
+ */
+ if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
+ DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+
+ /* Finished ... everything destructs automatically and all
+ * temporary scenes have already been deleted by MergeScenes()
+ */
+ return;
}
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
diff --git a/src/3rdparty/assimp/code/IRRLoader.h b/src/3rdparty/assimp/code/IRRLoader.h
index d0765976c..129e0cc03 100644
--- a/src/3rdparty/assimp/code/IRRLoader.h
+++ b/src/3rdparty/assimp/code/IRRLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,8 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IRRShared.h"
#include "SceneCombiner.h"
+#include "Importer.h"
+#include "StringUtils.h"
+#include <assimp/anim.h>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
@@ -62,245 +65,247 @@ namespace Assimp {
class IRRImporter : public BaseImporter, public IrrlichtBase
{
public:
- IRRImporter();
- ~IRRImporter();
+ IRRImporter();
+ ~IRRImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /**
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /**
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /**
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /**
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- /**
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /**
+ */
+ void SetupProperties(const Importer* pImp);
private:
- /** Data structure for a scenegraph node animator
- */
- struct Animator
- {
- // Type of the animator
- enum AT
- {
- UNKNOWN = 0x0,
- ROTATION = 0x1,
- FLY_CIRCLE = 0x2,
- FLY_STRAIGHT = 0x3,
- FOLLOW_SPLINE = 0x4,
- OTHER = 0x5
-
- } type;
-
- Animator(AT t = UNKNOWN)
- : type (t)
- , speed (0.001f)
- , direction (0.f,1.f,0.f)
- , circleRadius (1.f)
- , tightness (0.5f)
- , loop (true)
- , timeForWay (100)
- {
- }
-
-
- // common parameters
- float speed;
- aiVector3D direction;
-
- // FLY_CIRCLE
- aiVector3D circleCenter;
- float circleRadius;
-
- // FOLLOW_SPLINE
- float tightness;
- std::vector<aiVectorKey> splineKeys;
-
- // ROTATION (angles given in direction)
-
- // FLY STRAIGHT
- // circleCenter = start, direction = end
- bool loop;
- int timeForWay;
- };
-
- /** Data structure for a scenegraph node in an IRR file
- */
- struct Node
- {
- // Type of the node
- enum ET
- {
- LIGHT,
- CUBE,
- MESH,
- SKYBOX,
- DUMMY,
- CAMERA,
- TERRAIN,
- SPHERE,
- ANIMMESH
- } type;
-
- Node(ET t)
- : type (t)
- , scaling (1.f,1.f,1.f) // assume uniform scaling by default
- , framesPerSecond (0.f)
- , sphereRadius (1.f)
- , spherePolyCountX (100)
- , spherePolyCountY (100)
- {
-
- // Generate a default name for the node
- char buffer[128];
- static int cnt;
- ::sprintf(buffer,"IrrNode_%i",cnt++);
- name = std::string(buffer);
-
- // reserve space for up to 5 materials
- materials.reserve(5);
-
- // reserve space for up to 5 children
- children.reserve(5);
- }
-
- // Transformation of the node
- aiVector3D position, rotation, scaling;
-
- // Name of the node
- std::string name;
-
- // List of all child nodes
- std::vector<Node*> children;
-
- // Parent node
- Node* parent;
-
- // Animated meshes: frames per second
- // 0.f if not specified
- float framesPerSecond;
-
- // Meshes: path to the mesh to be loaded
- std::string meshPath;
- unsigned int id;
-
- // Meshes: List of materials to be assigned
- // along with their corresponding material flags
- std::vector< std::pair<aiMaterial*, unsigned int> > materials;
-
- // Spheres: radius of the sphere to be generates
- float sphereRadius;
-
- // Spheres: Number of polygons in the x,y direction
- unsigned int spherePolyCountX,spherePolyCountY;
-
- // List of all animators assigned to the node
- std::list<Animator> animators;
- };
-
- /** Data structure for a vertex in an IRR skybox
- */
- struct SkyboxVertex
- {
- SkyboxVertex()
- {}
-
- //! Construction from single vertex components
- SkyboxVertex(float px, float py, float pz,
- float nx, float ny, float nz,
- float uvx, float uvy)
-
- : position (px,py,pz)
- , normal (nx,ny,nz)
- , uv (uvx,uvy,0.f)
- {}
-
- aiVector3D position, normal, uv;
- };
-
-
- // -------------------------------------------------------------------
- /** Fill the scenegraph recursively
- */
- void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
- BatchLoader& batch,
- std::vector<aiMesh*>& meshes,
- std::vector<aiNodeAnim*>& anims,
- std::vector<AttachmentInfo>& attach,
- std::vector<aiMaterial*>& materials,
- unsigned int& defaultMatIdx);
-
-
- // -------------------------------------------------------------------
- /** Generate a mesh that consists of just a single quad
- */
- aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1,
- const SkyboxVertex& v2,
- const SkyboxVertex& v3,
- const SkyboxVertex& v4);
-
-
- // -------------------------------------------------------------------
- /** Build a skybox
- *
- * @param meshes Receives 6 output meshes
- * @param materials The last 6 materials are assigned to the newly
- * created meshes. The names of the materials are adjusted.
- */
- void BuildSkybox(std::vector<aiMesh*>& meshes,
- std::vector<aiMaterial*> materials);
-
-
- // -------------------------------------------------------------------
- /** Copy a material for a mesh to the output material list
- *
- * @param materials Receives an output material
- * @param inmaterials List of input materials
- * @param defMatIdx Default material index - UINT_MAX if not present
- * @param mesh Mesh to work on
- */
- void CopyMaterial(std::vector<aiMaterial*>& materials,
- std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
- unsigned int& defMatIdx,
- aiMesh* mesh);
-
-
- // -------------------------------------------------------------------
- /** Compute animations for a specific node
- *
- * @param root Node to be processed
- * @param anims The list of output animations
- */
- void ComputeAnimations(Node* root, aiNode* real,
- std::vector<aiNodeAnim*>& anims);
+ /** Data structure for a scenegraph node animator
+ */
+ struct Animator
+ {
+ // Type of the animator
+ enum AT
+ {
+ UNKNOWN = 0x0,
+ ROTATION = 0x1,
+ FLY_CIRCLE = 0x2,
+ FLY_STRAIGHT = 0x3,
+ FOLLOW_SPLINE = 0x4,
+ OTHER = 0x5
+
+ } type;
+
+ explicit Animator(AT t = UNKNOWN)
+ : type (t)
+ , speed (0.001f)
+ , direction (0.f,1.f,0.f)
+ , circleRadius (1.f)
+ , tightness (0.5f)
+ , loop (true)
+ , timeForWay (100)
+ {
+ }
+
+
+ // common parameters
+ float speed;
+ aiVector3D direction;
+
+ // FLY_CIRCLE
+ aiVector3D circleCenter;
+ float circleRadius;
+
+ // FOLLOW_SPLINE
+ float tightness;
+ std::vector<aiVectorKey> splineKeys;
+
+ // ROTATION (angles given in direction)
+
+ // FLY STRAIGHT
+ // circleCenter = start, direction = end
+ bool loop;
+ int timeForWay;
+ };
+
+ /** Data structure for a scenegraph node in an IRR file
+ */
+ struct Node
+ {
+ // Type of the node
+ enum ET
+ {
+ LIGHT,
+ CUBE,
+ MESH,
+ SKYBOX,
+ DUMMY,
+ CAMERA,
+ TERRAIN,
+ SPHERE,
+ ANIMMESH
+ } type;
+
+ explicit Node(ET t)
+ : type (t)
+ , scaling (1.f,1.f,1.f) // assume uniform scaling by default
+ , parent()
+ , framesPerSecond (0.f)
+ , id()
+ , sphereRadius (1.f)
+ , spherePolyCountX (100)
+ , spherePolyCountY (100)
+ {
+
+ // Generate a default name for the node
+ char buffer[128];
+ static int cnt;
+ ai_snprintf(buffer, 128, "IrrNode_%i",cnt++);
+ name = std::string(buffer);
+
+ // reserve space for up to 5 materials
+ materials.reserve(5);
+
+ // reserve space for up to 5 children
+ children.reserve(5);
+ }
+
+ // Transformation of the node
+ aiVector3D position, rotation, scaling;
+
+ // Name of the node
+ std::string name;
+
+ // List of all child nodes
+ std::vector<Node*> children;
+
+ // Parent node
+ Node* parent;
+
+ // Animated meshes: frames per second
+ // 0.f if not specified
+ float framesPerSecond;
+
+ // Meshes: path to the mesh to be loaded
+ std::string meshPath;
+ unsigned int id;
+
+ // Meshes: List of materials to be assigned
+ // along with their corresponding material flags
+ std::vector< std::pair<aiMaterial*, unsigned int> > materials;
+
+ // Spheres: radius of the sphere to be generates
+ float sphereRadius;
+
+ // Spheres: Number of polygons in the x,y direction
+ unsigned int spherePolyCountX,spherePolyCountY;
+
+ // List of all animators assigned to the node
+ std::list<Animator> animators;
+ };
+
+ /** Data structure for a vertex in an IRR skybox
+ */
+ struct SkyboxVertex
+ {
+ SkyboxVertex()
+ {}
+
+ //! Construction from single vertex components
+ SkyboxVertex(float px, float py, float pz,
+ float nx, float ny, float nz,
+ float uvx, float uvy)
+
+ : position (px,py,pz)
+ , normal (nx,ny,nz)
+ , uv (uvx,uvy,0.f)
+ {}
+
+ aiVector3D position, normal, uv;
+ };
+
+
+ // -------------------------------------------------------------------
+ /** Fill the scenegraph recursively
+ */
+ void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
+ BatchLoader& batch,
+ std::vector<aiMesh*>& meshes,
+ std::vector<aiNodeAnim*>& anims,
+ std::vector<AttachmentInfo>& attach,
+ std::vector<aiMaterial*>& materials,
+ unsigned int& defaultMatIdx);
+
+
+ // -------------------------------------------------------------------
+ /** Generate a mesh that consists of just a single quad
+ */
+ aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1,
+ const SkyboxVertex& v2,
+ const SkyboxVertex& v3,
+ const SkyboxVertex& v4);
+
+
+ // -------------------------------------------------------------------
+ /** Build a skybox
+ *
+ * @param meshes Receives 6 output meshes
+ * @param materials The last 6 materials are assigned to the newly
+ * created meshes. The names of the materials are adjusted.
+ */
+ void BuildSkybox(std::vector<aiMesh*>& meshes,
+ std::vector<aiMaterial*> materials);
+
+
+ // -------------------------------------------------------------------
+ /** Copy a material for a mesh to the output material list
+ *
+ * @param materials Receives an output material
+ * @param inmaterials List of input materials
+ * @param defMatIdx Default material index - UINT_MAX if not present
+ * @param mesh Mesh to work on
+ */
+ void CopyMaterial(std::vector<aiMaterial*>& materials,
+ std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials,
+ unsigned int& defMatIdx,
+ aiMesh* mesh);
+
+
+ // -------------------------------------------------------------------
+ /** Compute animations for a specific node
+ *
+ * @param root Node to be processed
+ * @param anims The list of output animations
+ */
+ void ComputeAnimations(Node* root, aiNode* real,
+ std::vector<aiNodeAnim*>& anims);
private:
- /** Configuration option: desired output FPS */
- double fps;
+ /** Configuration option: desired output FPS */
+ double fps;
- /** Configuration option: speed flag was set? */
- bool configSpeedFlag;
+ /** Configuration option: speed flag was set? */
+ bool configSpeedFlag;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/IRRMeshLoader.cpp b/src/3rdparty/assimp/code/IRRMeshLoader.cpp
index 20e5438d9..0a2a54e84 100644
--- a/src/3rdparty/assimp/code/IRRMeshLoader.cpp
+++ b/src/3rdparty/assimp/code/IRRMeshLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,45 +25,53 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the IrrMesh importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
#include "IRRMeshLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/mesh.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include "Macros.h"
+
using namespace Assimp;
using namespace irr;
using namespace irr::io;
static const aiImporterDesc desc = {
- "Irrlicht Mesh Reader",
- "",
- "",
- "http://irrlicht.sourceforge.net/",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "xml irrmesh"
+ "Irrlicht Mesh Reader",
+ "",
+ "",
+ "http://irrlicht.sourceforge.net/",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "xml irrmesh"
};
// ------------------------------------------------------------------------------------------------
@@ -72,444 +80,444 @@ IRRMeshImporter::IRRMeshImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
IRRMeshImporter::~IRRMeshImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- /* NOTE: A simple check for the file extension is not enough
- * here. Irrmesh and irr are easy, but xml is too generic
- * and could be collada, too. So we need to open the file and
- * search for typical tokens.
- */
- const std::string extension = GetExtension(pFile);
-
- if (extension == "irrmesh")return true;
- else if (extension == "xml" || checkSig)
- {
- /* If CanRead() is called to check whether the loader
- * supports a specific file extension in general we
- * must return true here.
- */
- if (!pIOHandler)return true;
- const char* tokens[] = {"irrmesh"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ /* NOTE: A simple check for the file extension is not enough
+ * here. Irrmesh and irr are easy, but xml is too generic
+ * and could be collada, too. So we need to open the file and
+ * search for typical tokens.
+ */
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "irrmesh")return true;
+ else if (extension == "xml" || checkSig)
+ {
+ /* If CanRead() is called to check whether the loader
+ * supports a specific file extension in general we
+ * must return true here.
+ */
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"irrmesh"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get a list of all file extensions which are handled by this class
const aiImporterDesc* IRRMeshImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void IRRMeshImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void IRRMeshImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + "");
-
- // Construct the irrXML parser
- CIrrXML_IOStreamReader st(file.get());
- reader = createIrrXMLReader((IFileReadCallBack*) &st);
-
- // final data
- std::vector<aiMaterial*> materials;
- std::vector<aiMesh*> meshes;
- materials.reserve (5);
- meshes.reserve (5);
-
- // temporary data - current mesh buffer
- aiMaterial* curMat = NULL;
- aiMesh* curMesh = NULL;
- unsigned int curMatFlags = 0;
-
- std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
- std::vector<aiColor4D> curColors;
- std::vector<aiVector3D> curUVs,curUV2s;
-
- // some temporary variables
- int textMeaning = 0;
- int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents
- bool useColors = false;
-
- // Parse the XML file
- while (reader->read()) {
- switch (reader->getNodeType()) {
- case EXN_ELEMENT:
-
- if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
- // end of previous buffer. A material and a mesh should be there
- if ( !curMat || !curMesh) {
- DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
- delete curMat;
- delete curMesh;
- }
- else {
- materials.push_back(curMat);
- meshes.push_back(curMesh);
- }
- curMat = NULL;
- curMesh = NULL;
-
- curVertices.clear();
- curColors.clear();
- curNormals.clear();
- curUV2s.clear();
- curUVs.clear();
- curTangents.clear();
- curBitangents.clear();
- }
-
-
- if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
- if (curMat) {
- DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
- delete curMat;curMat = NULL;
- }
- curMat = ParseMaterial(curMatFlags);
- }
- /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
- {
- int num = reader->getAttributeValueAsInt("vertexCount");
-
- if (!num) {
- // This is possible ... remove the mesh from the list and skip further reading
- DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
-
- delete curMat;curMat = NULL;
-
- curMesh = NULL;
- textMeaning = 0;
- continue;
- }
-
- curVertices.reserve (num);
- curNormals.reserve (num);
- curColors.reserve (num);
- curUVs.reserve (num);
-
- // Determine the file format
- const char* t = reader->getAttributeValueSafe("type");
- if (!ASSIMP_stricmp("2tcoords", t)) {
- curUV2s.reserve (num);
- vertexFormat = 1;
-
- if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) {
- // *********************************************************
- // We have a second texture! So use this UV channel
- // for it. The 2nd texture can be either a normal
- // texture (solid_2layer or lightmap_xxx) or a normal
- // map (normal_..., parallax_...)
- // *********************************************************
- int idx = 1;
- aiMaterial* mat = ( aiMaterial* ) curMat;
-
- if (curMatFlags & AI_IRRMESH_MAT_lightmap){
- mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_LIGHTMAP(0));
- }
- else if (curMatFlags & AI_IRRMESH_MAT_normalmap_solid){
- mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
- }
- else if (curMatFlags & AI_IRRMESH_MAT_solid_2layer) {
- mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
- }
- }
- }
- else if (!ASSIMP_stricmp("tangents", t)) {
- curTangents.reserve (num);
- curBitangents.reserve (num);
- vertexFormat = 2;
- }
- else if (ASSIMP_stricmp("standard", t)) {
- delete curMat;
- DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
- }
- else vertexFormat = 0;
- textMeaning = 1;
- }
- else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
- if (curVertices.empty() && curMat) {
- delete curMat;
- throw DeadlyImportError("IRRMESH: indices must come after vertices");
- }
-
- textMeaning = 2;
-
- // start a new mesh
- curMesh = new aiMesh();
-
- // allocate storage for all faces
- curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
- if (!curMesh->mNumVertices) {
- // This is possible ... remove the mesh from the list and skip further reading
- DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
-
- // mesh - away
- delete curMesh; curMesh = NULL;
-
- // material - away
- delete curMat;curMat = NULL;
-
- textMeaning = 0;
- continue;
- }
-
- if (curMesh->mNumVertices % 3) {
- DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
- }
-
- curMesh->mNumFaces = curMesh->mNumVertices / 3;
- curMesh->mFaces = new aiFace[curMesh->mNumFaces];
-
- // setup some members
- curMesh->mMaterialIndex = (unsigned int)materials.size();
- curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // allocate storage for all vertices
- curMesh->mVertices = new aiVector3D[curMesh->mNumVertices];
-
- if (curNormals.size() == curVertices.size()) {
- curMesh->mNormals = new aiVector3D[curMesh->mNumVertices];
- }
- if (curTangents.size() == curVertices.size()) {
- curMesh->mTangents = new aiVector3D[curMesh->mNumVertices];
- }
- if (curBitangents.size() == curVertices.size()) {
- curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices];
- }
- if (curColors.size() == curVertices.size() && useColors) {
- curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices];
- }
- if (curUVs.size() == curVertices.size()) {
- curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices];
- }
- if (curUV2s.size() == curVertices.size()) {
- curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices];
- }
- }
- break;
-
- case EXN_TEXT:
- {
- const char* sz = reader->getNodeData();
- if (textMeaning == 1) {
- textMeaning = 0;
-
- // read vertices
- do {
- SkipSpacesAndLineEnd(&sz);
- aiVector3D temp;aiColor4D c;
-
- // Read the vertex position
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.z);
- SkipSpaces(&sz);
- curVertices.push_back(temp);
-
- // Read the vertex normals
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.z);
- SkipSpaces(&sz);
- curNormals.push_back(temp);
-
- // read the vertex colors
- uint32_t clr = strtoul16(sz,&sz);
- ColorFromARGBPacked(clr,c);
-
- if (!curColors.empty() && c != *(curColors.end()-1))
- useColors = true;
-
- curColors.push_back(c);
- SkipSpaces(&sz);
-
-
- // read the first UV coordinate set
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- SkipSpaces(&sz);
- temp.z = 0.f;
- temp.y = 1.f - temp.y; // DX to OGL
- curUVs.push_back(temp);
-
- // read the (optional) second UV coordinate set
- if (vertexFormat == 1) {
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- temp.y = 1.f - temp.y; // DX to OGL
- curUV2s.push_back(temp);
- }
- // read optional tangent and bitangent vectors
- else if (vertexFormat == 2) {
- // tangents
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.z);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- SkipSpaces(&sz);
- temp.y *= -1.0f;
- curTangents.push_back(temp);
-
- // bitangents
- sz = fast_atoreal_move<float>(sz,(float&)temp.x);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.z);
- SkipSpaces(&sz);
-
- sz = fast_atoreal_move<float>(sz,(float&)temp.y);
- SkipSpaces(&sz);
- temp.y *= -1.0f;
- curBitangents.push_back(temp);
- }
- }
-
- /* IMPORTANT: We assume that each vertex is specified in one
- line. So we can skip the rest of the line - unknown vertex
- elements are ignored.
- */
-
- while (SkipLine(&sz));
- }
- else if (textMeaning == 2) {
- textMeaning = 0;
-
- // read indices
- aiFace* curFace = curMesh->mFaces;
- aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces;
-
- aiVector3D* pcV = curMesh->mVertices;
- aiVector3D* pcN = curMesh->mNormals;
- aiVector3D* pcT = curMesh->mTangents;
- aiVector3D* pcB = curMesh->mBitangents;
- aiColor4D* pcC0 = curMesh->mColors[0];
- aiVector3D* pcT0 = curMesh->mTextureCoords[0];
- aiVector3D* pcT1 = curMesh->mTextureCoords[1];
-
- unsigned int curIdx = 0;
- unsigned int total = 0;
- while(SkipSpacesAndLineEnd(&sz)) {
- if (curFace >= faceEnd) {
- DefaultLogger::get()->error("IRRMESH: Too many indices");
- break;
- }
- if (!curIdx) {
- curFace->mNumIndices = 3;
- curFace->mIndices = new unsigned int[3];
- }
-
- unsigned int idx = strtoul10(sz,&sz);
- if (idx >= curVertices.size()) {
- DefaultLogger::get()->error("IRRMESH: Index out of range");
- idx = 0;
- }
-
- curFace->mIndices[curIdx] = total++;
-
- *pcV++ = curVertices[idx];
- if (pcN)*pcN++ = curNormals[idx];
- if (pcT)*pcT++ = curTangents[idx];
- if (pcB)*pcB++ = curBitangents[idx];
- if (pcC0)*pcC0++ = curColors[idx];
- if (pcT0)*pcT0++ = curUVs[idx];
- if (pcT1)*pcT1++ = curUV2s[idx];
-
- if (++curIdx == 3) {
- ++curFace;
- curIdx = 0;
- }
- }
-
- if (curFace != faceEnd)
- DefaultLogger::get()->error("IRRMESH: Not enough indices");
-
- // Finish processing the mesh - do some small material workarounds
- if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
- // Take the opacity value of the current material
- // from the common vertex color alpha
- aiMaterial* mat = (aiMaterial*)curMat;
- mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY);
- }
- }}
- break;
-
- default:
-
- // GCC complains here ...
- break;
-
- };
- }
-
- // End of the last buffer. A material and a mesh should be there
- if (curMat || curMesh) {
- if ( !curMat || !curMesh) {
- DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
- delete curMat;
- delete curMesh;
- }
- else {
- materials.push_back(curMat);
- meshes.push_back(curMesh);
- }
- }
-
- if (materials.empty())
- throw DeadlyImportError("IRRMESH: Unable to read a mesh from this file");
-
-
- // now generate the output scene
- pScene->mNumMeshes = (unsigned int)meshes.size();
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
- pScene->mMeshes[i] = meshes[i];
-
- // clean this value ...
- pScene->mMeshes[i]->mNumUVComponents[3] = 0;
- }
-
- pScene->mNumMaterials = (unsigned int)materials.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- ::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials);
-
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<IRRMesh>");
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
-
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mRootNode->mMeshes[i] = i;
-
- // clean up and return
- delete reader;
- AI_DEBUG_INVALIDATE_PTR(reader);
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + "");
+
+ // Construct the irrXML parser
+ CIrrXML_IOStreamReader st(file.get());
+ reader = createIrrXMLReader((IFileReadCallBack*) &st);
+
+ // final data
+ std::vector<aiMaterial*> materials;
+ std::vector<aiMesh*> meshes;
+ materials.reserve (5);
+ meshes.reserve (5);
+
+ // temporary data - current mesh buffer
+ aiMaterial* curMat = NULL;
+ aiMesh* curMesh = NULL;
+ unsigned int curMatFlags = 0;
+
+ std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
+ std::vector<aiColor4D> curColors;
+ std::vector<aiVector3D> curUVs,curUV2s;
+
+ // some temporary variables
+ int textMeaning = 0;
+ int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents
+ bool useColors = false;
+
+ // Parse the XML file
+ while (reader->read()) {
+ switch (reader->getNodeType()) {
+ case EXN_ELEMENT:
+
+ if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
+ // end of previous buffer. A material and a mesh should be there
+ if ( !curMat || !curMesh) {
+ DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+ delete curMat;
+ delete curMesh;
+ }
+ else {
+ materials.push_back(curMat);
+ meshes.push_back(curMesh);
+ }
+ curMat = NULL;
+ curMesh = NULL;
+
+ curVertices.clear();
+ curColors.clear();
+ curNormals.clear();
+ curUV2s.clear();
+ curUVs.clear();
+ curTangents.clear();
+ curBitangents.clear();
+ }
+
+
+ if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
+ if (curMat) {
+ DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
+ delete curMat;curMat = NULL;
+ }
+ curMat = ParseMaterial(curMatFlags);
+ }
+ /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
+ {
+ int num = reader->getAttributeValueAsInt("vertexCount");
+
+ if (!num) {
+ // This is possible ... remove the mesh from the list and skip further reading
+ DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
+
+ delete curMat;curMat = NULL;
+
+ curMesh = NULL;
+ textMeaning = 0;
+ continue;
+ }
+
+ curVertices.reserve (num);
+ curNormals.reserve (num);
+ curColors.reserve (num);
+ curUVs.reserve (num);
+
+ // Determine the file format
+ const char* t = reader->getAttributeValueSafe("type");
+ if (!ASSIMP_stricmp("2tcoords", t)) {
+ curUV2s.reserve (num);
+ vertexFormat = 1;
+
+ if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) {
+ // *********************************************************
+ // We have a second texture! So use this UV channel
+ // for it. The 2nd texture can be either a normal
+ // texture (solid_2layer or lightmap_xxx) or a normal
+ // map (normal_..., parallax_...)
+ // *********************************************************
+ int idx = 1;
+ aiMaterial* mat = ( aiMaterial* ) curMat;
+
+ if (curMatFlags & AI_IRRMESH_MAT_lightmap){
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_LIGHTMAP(0));
+ }
+ else if (curMatFlags & AI_IRRMESH_MAT_normalmap_solid){
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
+ }
+ else if (curMatFlags & AI_IRRMESH_MAT_solid_2layer) {
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
+ }
+ }
+ }
+ else if (!ASSIMP_stricmp("tangents", t)) {
+ curTangents.reserve (num);
+ curBitangents.reserve (num);
+ vertexFormat = 2;
+ }
+ else if (ASSIMP_stricmp("standard", t)) {
+ delete curMat;
+ DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
+ }
+ else vertexFormat = 0;
+ textMeaning = 1;
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
+ if (curVertices.empty() && curMat) {
+ delete curMat;
+ throw DeadlyImportError("IRRMESH: indices must come after vertices");
+ }
+
+ textMeaning = 2;
+
+ // start a new mesh
+ curMesh = new aiMesh();
+
+ // allocate storage for all faces
+ curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
+ if (!curMesh->mNumVertices) {
+ // This is possible ... remove the mesh from the list and skip further reading
+ DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
+
+ // mesh - away
+ delete curMesh; curMesh = NULL;
+
+ // material - away
+ delete curMat;curMat = NULL;
+
+ textMeaning = 0;
+ continue;
+ }
+
+ if (curMesh->mNumVertices % 3) {
+ DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
+ }
+
+ curMesh->mNumFaces = curMesh->mNumVertices / 3;
+ curMesh->mFaces = new aiFace[curMesh->mNumFaces];
+
+ // setup some members
+ curMesh->mMaterialIndex = (unsigned int)materials.size();
+ curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // allocate storage for all vertices
+ curMesh->mVertices = new aiVector3D[curMesh->mNumVertices];
+
+ if (curNormals.size() == curVertices.size()) {
+ curMesh->mNormals = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curTangents.size() == curVertices.size()) {
+ curMesh->mTangents = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curBitangents.size() == curVertices.size()) {
+ curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curColors.size() == curVertices.size() && useColors) {
+ curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices];
+ }
+ if (curUVs.size() == curVertices.size()) {
+ curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curUV2s.size() == curVertices.size()) {
+ curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices];
+ }
+ }
+ break;
+
+ case EXN_TEXT:
+ {
+ const char* sz = reader->getNodeData();
+ if (textMeaning == 1) {
+ textMeaning = 0;
+
+ // read vertices
+ do {
+ SkipSpacesAndLineEnd(&sz);
+ aiVector3D temp;aiColor4D c;
+
+ // Read the vertex position
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+ curVertices.push_back(temp);
+
+ // Read the vertex normals
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+ curNormals.push_back(temp);
+
+ // read the vertex colors
+ uint32_t clr = strtoul16(sz,&sz);
+ ColorFromARGBPacked(clr,c);
+
+ if (!curColors.empty() && c != *(curColors.end()-1))
+ useColors = true;
+
+ curColors.push_back(c);
+ SkipSpaces(&sz);
+
+
+ // read the first UV coordinate set
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.z = 0.f;
+ temp.y = 1.f - temp.y; // DX to OGL
+ curUVs.push_back(temp);
+
+ // read the (optional) second UV coordinate set
+ if (vertexFormat == 1) {
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ temp.y = 1.f - temp.y; // DX to OGL
+ curUV2s.push_back(temp);
+ }
+ // read optional tangent and bitangent vectors
+ else if (vertexFormat == 2) {
+ // tangents
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.y *= -1.0f;
+ curTangents.push_back(temp);
+
+ // bitangents
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.y *= -1.0f;
+ curBitangents.push_back(temp);
+ }
+ }
+
+ /* IMPORTANT: We assume that each vertex is specified in one
+ line. So we can skip the rest of the line - unknown vertex
+ elements are ignored.
+ */
+
+ while (SkipLine(&sz));
+ }
+ else if (textMeaning == 2) {
+ textMeaning = 0;
+
+ // read indices
+ aiFace* curFace = curMesh->mFaces;
+ aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces;
+
+ aiVector3D* pcV = curMesh->mVertices;
+ aiVector3D* pcN = curMesh->mNormals;
+ aiVector3D* pcT = curMesh->mTangents;
+ aiVector3D* pcB = curMesh->mBitangents;
+ aiColor4D* pcC0 = curMesh->mColors[0];
+ aiVector3D* pcT0 = curMesh->mTextureCoords[0];
+ aiVector3D* pcT1 = curMesh->mTextureCoords[1];
+
+ unsigned int curIdx = 0;
+ unsigned int total = 0;
+ while(SkipSpacesAndLineEnd(&sz)) {
+ if (curFace >= faceEnd) {
+ DefaultLogger::get()->error("IRRMESH: Too many indices");
+ break;
+ }
+ if (!curIdx) {
+ curFace->mNumIndices = 3;
+ curFace->mIndices = new unsigned int[3];
+ }
+
+ unsigned int idx = strtoul10(sz,&sz);
+ if (idx >= curVertices.size()) {
+ DefaultLogger::get()->error("IRRMESH: Index out of range");
+ idx = 0;
+ }
+
+ curFace->mIndices[curIdx] = total++;
+
+ *pcV++ = curVertices[idx];
+ if (pcN)*pcN++ = curNormals[idx];
+ if (pcT)*pcT++ = curTangents[idx];
+ if (pcB)*pcB++ = curBitangents[idx];
+ if (pcC0)*pcC0++ = curColors[idx];
+ if (pcT0)*pcT0++ = curUVs[idx];
+ if (pcT1)*pcT1++ = curUV2s[idx];
+
+ if (++curIdx == 3) {
+ ++curFace;
+ curIdx = 0;
+ }
+ }
+
+ if (curFace != faceEnd)
+ DefaultLogger::get()->error("IRRMESH: Not enough indices");
+
+ // Finish processing the mesh - do some small material workarounds
+ if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
+ // Take the opacity value of the current material
+ // from the common vertex color alpha
+ aiMaterial* mat = (aiMaterial*)curMat;
+ mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY);
+ }
+ }}
+ break;
+
+ default:
+
+ // GCC complains here ...
+ break;
+
+ };
+ }
+
+ // End of the last buffer. A material and a mesh should be there
+ if (curMat || curMesh) {
+ if ( !curMat || !curMesh) {
+ DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+ delete curMat;
+ delete curMesh;
+ }
+ else {
+ materials.push_back(curMat);
+ meshes.push_back(curMesh);
+ }
+ }
+
+ if (materials.empty())
+ throw DeadlyImportError("IRRMESH: Unable to read a mesh from this file");
+
+
+ // now generate the output scene
+ pScene->mNumMeshes = (unsigned int)meshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ pScene->mMeshes[i] = meshes[i];
+
+ // clean this value ...
+ pScene->mMeshes[i]->mNumUVComponents[3] = 0;
+ }
+
+ pScene->mNumMaterials = (unsigned int)materials.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ ::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials);
+
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<IRRMesh>");
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mRootNode->mMeshes[i] = i;
+
+ // clean up and return
+ delete reader;
+ AI_DEBUG_INVALIDATE_PTR(reader);
}
#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER
diff --git a/src/3rdparty/assimp/code/IRRMeshLoader.h b/src/3rdparty/assimp/code/IRRMeshLoader.h
index d4cac04e6..6c208224c 100644
--- a/src/3rdparty/assimp/code/IRRMeshLoader.h
+++ b/src/3rdparty/assimp/code/IRRMeshLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file IRRMeshLoader.h
* @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format)
- * importer class.
+ * importer class.
*/
#ifndef AI_IRRMESHLOADER_H_INCLUDED
#define AI_IRRMESHLOADER_H_INCLUDED
@@ -48,7 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "IRRShared.h"
-namespace Assimp {
+#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** IrrMesh importer class.
@@ -60,36 +62,38 @@ namespace Assimp {
class IRRMeshImporter : public BaseImporter, public IrrlichtBase
{
public:
- IRRMeshImporter();
- ~IRRMeshImporter();
+ IRRMeshImporter();
+ ~IRRMeshImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
};
} // end of namespace Assimp
+#endif // ASSIMP_BUILD_NO_IRRMESH_IMPORTER
+
#endif // AI_IRRMESHIMPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/IRRShared.cpp b/src/3rdparty/assimp/code/IRRShared.cpp
index 197c3df99..e38ad1378 100644
--- a/src/3rdparty/assimp/code/IRRShared.cpp
+++ b/src/3rdparty/assimp/code/IRRShared.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Shared utilities for the IRR and IRRMESH loaders
*/
-#include "AssimpPCH.h"
+
//This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
#if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
@@ -51,451 +51,454 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IRRShared.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/material.h>
+
using namespace Assimp;
using namespace irr;
using namespace irr::io;
// Transformation matrix to convert from Assimp to IRR space
-const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f);
+const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 (
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
// ------------------------------------------------------------------------------------------------
// read a property in hexadecimal format (i.e. ffffffff)
void IrrlichtBase::ReadHexProperty (HexProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // parse the hexadecimal value
- out.value = strtoul16(reader->getAttributeValue(i));
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // parse the hexadecimal value
+ out.value = strtoul16(reader->getAttributeValue(i));
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// read a decimal property
void IrrlichtBase::ReadIntProperty (IntProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // parse the ecimal value
- out.value = strtol10(reader->getAttributeValue(i));
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // parse the ecimal value
+ out.value = strtol10(reader->getAttributeValue(i));
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// read a string property
void IrrlichtBase::ReadStringProperty (StringProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // simple copy the string
- out.value = std::string (reader->getAttributeValue(i));
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // simple copy the string
+ out.value = std::string (reader->getAttributeValue(i));
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// read a boolean property
void IrrlichtBase::ReadBoolProperty (BoolProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // true or false, case insensitive
- out.value = (ASSIMP_stricmp( reader->getAttributeValue(i),
- "true") ? false : true);
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // true or false, case insensitive
+ out.value = (ASSIMP_stricmp( reader->getAttributeValue(i),
+ "true") ? false : true);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// read a float property
void IrrlichtBase::ReadFloatProperty (FloatProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // just parse the float
- out.value = fast_atof( reader->getAttributeValue(i) );
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // just parse the float
+ out.value = fast_atof( reader->getAttributeValue(i) );
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// read a vector property
void IrrlichtBase::ReadVectorProperty (VectorProperty& out)
{
- for (int i = 0; i < reader->getAttributeCount();++i)
- {
- if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
- {
- out.name = std::string( reader->getAttributeValue(i) );
- }
- else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
- {
- // three floats, separated with commas
- const char* ptr = reader->getAttributeValue(i);
-
- SkipSpaces(&ptr);
- ptr = fast_atoreal_move<float>( ptr,(float&)out.value.x );
- SkipSpaces(&ptr);
- if (',' != *ptr)
- {
- DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
- }
- else SkipSpaces(ptr+1,&ptr);
- ptr = fast_atoreal_move<float>( ptr,(float&)out.value.y );
- SkipSpaces(&ptr);
- if (',' != *ptr)
- {
- DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
- }
- else SkipSpaces(ptr+1,&ptr);
- ptr = fast_atoreal_move<float>( ptr,(float&)out.value.z );
- }
- }
+ for (int i = 0; i < reader->getAttributeCount();++i)
+ {
+ if (!ASSIMP_stricmp(reader->getAttributeName(i),"name"))
+ {
+ out.name = std::string( reader->getAttributeValue(i) );
+ }
+ else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value"))
+ {
+ // three floats, separated with commas
+ const char* ptr = reader->getAttributeValue(i);
+
+ SkipSpaces(&ptr);
+ ptr = fast_atoreal_move<float>( ptr,(float&)out.value.x );
+ SkipSpaces(&ptr);
+ if (',' != *ptr)
+ {
+ DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
+ }
+ else SkipSpaces(ptr+1,&ptr);
+ ptr = fast_atoreal_move<float>( ptr,(float&)out.value.y );
+ SkipSpaces(&ptr);
+ if (',' != *ptr)
+ {
+ DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
+ }
+ else SkipSpaces(ptr+1,&ptr);
+ ptr = fast_atoreal_move<float>( ptr,(float&)out.value.z );
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Convert a string to a proper aiMappingMode
int ConvertMappingMode(const std::string& mode)
{
- if (mode == "texture_clamp_repeat")
- {
- return aiTextureMapMode_Wrap;
- }
- else if (mode == "texture_clamp_mirror")
- return aiTextureMapMode_Mirror;
-
- return aiTextureMapMode_Clamp;
+ if (mode == "texture_clamp_repeat")
+ {
+ return aiTextureMapMode_Wrap;
+ }
+ else if (mode == "texture_clamp_mirror")
+ return aiTextureMapMode_Mirror;
+
+ return aiTextureMapMode_Clamp;
}
// ------------------------------------------------------------------------------------------------
// Parse a material from the XML file
aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
{
- aiMaterial* mat = new aiMaterial();
- aiColor4D clr;
- aiString s;
-
- matFlags = 0; // zero output flags
- int cnt = 0; // number of used texture channels
- unsigned int nd = 0;
-
- // Continue reading from the file
- while (reader->read())
- {
- switch (reader->getNodeType())
- {
- case EXN_ELEMENT:
-
- // Hex properties
- if (!ASSIMP_stricmp(reader->getNodeName(),"color"))
- {
- HexProperty prop;
- ReadHexProperty(prop);
- if (prop.name == "Diffuse")
- {
- ColorFromARGBPacked(prop.value,clr);
- mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
- }
- else if (prop.name == "Ambient")
- {
- ColorFromARGBPacked(prop.value,clr);
- mat->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
- }
- else if (prop.name == "Specular")
- {
- ColorFromARGBPacked(prop.value,clr);
- mat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
- }
-
- // NOTE: The 'emissive' property causes problems. It is
- // often != 0, even if there is obviously no light
- // emitted by the described surface. In fact I think
- // IRRLICHT ignores this property, too.
+ aiMaterial* mat = new aiMaterial();
+ aiColor4D clr;
+ aiString s;
+
+ matFlags = 0; // zero output flags
+ int cnt = 0; // number of used texture channels
+ unsigned int nd = 0;
+
+ // Continue reading from the file
+ while (reader->read())
+ {
+ switch (reader->getNodeType())
+ {
+ case EXN_ELEMENT:
+
+ // Hex properties
+ if (!ASSIMP_stricmp(reader->getNodeName(),"color"))
+ {
+ HexProperty prop;
+ ReadHexProperty(prop);
+ if (prop.name == "Diffuse")
+ {
+ ColorFromARGBPacked(prop.value,clr);
+ mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ }
+ else if (prop.name == "Ambient")
+ {
+ ColorFromARGBPacked(prop.value,clr);
+ mat->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
+ }
+ else if (prop.name == "Specular")
+ {
+ ColorFromARGBPacked(prop.value,clr);
+ mat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
+ }
+
+ // NOTE: The 'emissive' property causes problems. It is
+ // often != 0, even if there is obviously no light
+ // emitted by the described surface. In fact I think
+ // IRRLICHT ignores this property, too.
#if 0
- else if (prop.name == "Emissive")
- {
- ColorFromARGBPacked(prop.value,clr);
- mat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
- }
+ else if (prop.name == "Emissive")
+ {
+ ColorFromARGBPacked(prop.value,clr);
+ mat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
+ }
#endif
- }
- // Float properties
- else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
- {
- FloatProperty prop;
- ReadFloatProperty(prop);
- if (prop.name == "Shininess")
- {
- mat->AddProperty(&prop.value,1,AI_MATKEY_SHININESS);
- }
- }
- // Bool properties
- else if (!ASSIMP_stricmp(reader->getNodeName(),"bool"))
- {
- BoolProperty prop;
- ReadBoolProperty(prop);
- if (prop.name == "Wireframe")
- {
- int val = (prop.value ? true : false);
- mat->AddProperty(&val,1,AI_MATKEY_ENABLE_WIREFRAME);
- }
- else if (prop.name == "GouraudShading")
- {
- int val = (prop.value ? aiShadingMode_Gouraud
- : aiShadingMode_NoShading);
- mat->AddProperty(&val,1,AI_MATKEY_SHADING_MODEL);
- }
- else if (prop.name == "BackfaceCulling")
- {
- int val = (!prop.value);
- mat->AddProperty(&val,1,AI_MATKEY_TWOSIDED);
- }
- }
- // String properties - textures and texture related properties
- else if (!ASSIMP_stricmp(reader->getNodeName(),"texture") ||
- !ASSIMP_stricmp(reader->getNodeName(),"enum"))
- {
- StringProperty prop;
- ReadStringProperty(prop);
- if (prop.value.length())
- {
- // material type (shader)
- if (prop.name == "Type")
- {
- if (prop.value == "solid")
- {
- // default material ...
- }
- else if (prop.value == "trans_vertex_alpha")
- {
- matFlags = AI_IRRMESH_MAT_trans_vertex_alpha;
- }
- else if (prop.value == "lightmap")
- {
- matFlags = AI_IRRMESH_MAT_lightmap;
- }
- else if (prop.value == "solid_2layer")
- {
- matFlags = AI_IRRMESH_MAT_solid_2layer;
- }
- else if (prop.value == "lightmap_m2")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_m2;
- }
- else if (prop.value == "lightmap_m4")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_m4;
- }
- else if (prop.value == "lightmap_light")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_light;
- }
- else if (prop.value == "lightmap_light_m2")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_light_m2;
- }
- else if (prop.value == "lightmap_light_m4")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_light_m4;
- }
- else if (prop.value == "lightmap_add")
- {
- matFlags = AI_IRRMESH_MAT_lightmap_add;
- }
- // Normal and parallax maps are treated equally
- else if (prop.value == "normalmap_solid" ||
- prop.value == "parallaxmap_solid")
- {
- matFlags = AI_IRRMESH_MAT_normalmap_solid;
- }
- else if (prop.value == "normalmap_trans_vertex_alpha" ||
- prop.value == "parallaxmap_trans_vertex_alpha")
- {
- matFlags = AI_IRRMESH_MAT_normalmap_tva;
- }
- else if (prop.value == "normalmap_trans_add" ||
- prop.value == "parallaxmap_trans_add")
- {
- matFlags = AI_IRRMESH_MAT_normalmap_ta;
- }
- else {
- DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value);
- }
- }
-
- // Up to 4 texture channels are supported
- if (prop.name == "Texture1")
- {
- // Always accept the primary texture channel
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- else if (prop.name == "Texture2" && cnt == 1)
- {
- // 2-layer material lightmapped?
- if (matFlags & AI_IRRMESH_MAT_lightmap) {
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_LIGHTMAP(0));
-
- // set the corresponding material flag
- matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
- }
- // alternatively: normal or parallax mapping
- else if (matFlags & AI_IRRMESH_MAT_normalmap_solid) {
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_NORMALS(0));
-
- // set the corresponding material flag
- matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
- }
- // or just as second diffuse texture
- else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1));
- ++nd;
-
- // set the corresponding material flag
- matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
- }
- else DefaultLogger::get()->warn("IRRmat: Skipping second texture");
- }
-
- else if (prop.name == "Texture3" && cnt == 2)
- {
- // Irrlicht does not seem to use these channels.
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1));
- }
- else if (prop.name == "Texture4" && cnt == 3)
- {
- // Irrlicht does not seem to use these channels.
- ++cnt;
- s.Set(prop.value);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+2));
- }
-
- // Texture mapping options
- if (prop.name == "TextureWrap1" && cnt >= 1)
- {
- int map = ConvertMappingMode(prop.value);
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
- }
- else if (prop.name == "TextureWrap2" && cnt >= 2)
- {
- int map = ConvertMappingMode(prop.value);
- if (matFlags & AI_IRRMESH_MAT_lightmap) {
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(0));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(0));
- }
- else if (matFlags & (AI_IRRMESH_MAT_normalmap_solid)) {
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_NORMALS(0));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_NORMALS(0));
- }
- else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(1));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(1));
- }
- }
- else if (prop.name == "TextureWrap3" && cnt >= 3)
- {
- int map = ConvertMappingMode(prop.value);
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+1));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+1));
- }
- else if (prop.name == "TextureWrap4" && cnt >= 4)
- {
- int map = ConvertMappingMode(prop.value);
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+2));
- mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+2));
- }
- }
- }
- break;
- case EXN_ELEMENT_END:
-
- /* Assume there are no further nested nodes in <material> elements
- */
- if (/* IRRMESH */ !ASSIMP_stricmp(reader->getNodeName(),"material") ||
- /* IRR */ !ASSIMP_stricmp(reader->getNodeName(),"attributes"))
- {
- // Now process lightmapping flags
- // We should have at least one textur to do that ..
- if (cnt && matFlags & AI_IRRMESH_MAT_lightmap)
- {
- float f = 1.f;
- unsigned int unmasked = matFlags&~AI_IRRMESH_MAT_lightmap;
-
- // Additive lightmap?
- int op = (unmasked & AI_IRRMESH_MAT_lightmap_add
- ? aiTextureOp_Add : aiTextureOp_Multiply);
-
- // Handle Irrlicht's lightmapping scaling factor
- if (unmasked & AI_IRRMESH_MAT_lightmap_m2 ||
- unmasked & AI_IRRMESH_MAT_lightmap_light_m2)
- {
- f = 2.f;
- }
- else if (unmasked & AI_IRRMESH_MAT_lightmap_m4 ||
- unmasked & AI_IRRMESH_MAT_lightmap_light_m4)
- {
- f = 4.f;
- }
- mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_LIGHTMAP(0));
- mat->AddProperty( &op,1, AI_MATKEY_TEXOP_LIGHTMAP(0));
- }
-
- return mat;
- }
- default:
-
- // GCC complains here ...
- break;
- }
- }
- DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete");
- return mat;
+ }
+ // Float properties
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"float"))
+ {
+ FloatProperty prop;
+ ReadFloatProperty(prop);
+ if (prop.name == "Shininess")
+ {
+ mat->AddProperty(&prop.value,1,AI_MATKEY_SHININESS);
+ }
+ }
+ // Bool properties
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"bool"))
+ {
+ BoolProperty prop;
+ ReadBoolProperty(prop);
+ if (prop.name == "Wireframe")
+ {
+ int val = (prop.value ? true : false);
+ mat->AddProperty(&val,1,AI_MATKEY_ENABLE_WIREFRAME);
+ }
+ else if (prop.name == "GouraudShading")
+ {
+ int val = (prop.value ? aiShadingMode_Gouraud
+ : aiShadingMode_NoShading);
+ mat->AddProperty(&val,1,AI_MATKEY_SHADING_MODEL);
+ }
+ else if (prop.name == "BackfaceCulling")
+ {
+ int val = (!prop.value);
+ mat->AddProperty(&val,1,AI_MATKEY_TWOSIDED);
+ }
+ }
+ // String properties - textures and texture related properties
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"texture") ||
+ !ASSIMP_stricmp(reader->getNodeName(),"enum"))
+ {
+ StringProperty prop;
+ ReadStringProperty(prop);
+ if (prop.value.length())
+ {
+ // material type (shader)
+ if (prop.name == "Type")
+ {
+ if (prop.value == "solid")
+ {
+ // default material ...
+ }
+ else if (prop.value == "trans_vertex_alpha")
+ {
+ matFlags = AI_IRRMESH_MAT_trans_vertex_alpha;
+ }
+ else if (prop.value == "lightmap")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap;
+ }
+ else if (prop.value == "solid_2layer")
+ {
+ matFlags = AI_IRRMESH_MAT_solid_2layer;
+ }
+ else if (prop.value == "lightmap_m2")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_m2;
+ }
+ else if (prop.value == "lightmap_m4")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_m4;
+ }
+ else if (prop.value == "lightmap_light")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_light;
+ }
+ else if (prop.value == "lightmap_light_m2")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_light_m2;
+ }
+ else if (prop.value == "lightmap_light_m4")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_light_m4;
+ }
+ else if (prop.value == "lightmap_add")
+ {
+ matFlags = AI_IRRMESH_MAT_lightmap_add;
+ }
+ // Normal and parallax maps are treated equally
+ else if (prop.value == "normalmap_solid" ||
+ prop.value == "parallaxmap_solid")
+ {
+ matFlags = AI_IRRMESH_MAT_normalmap_solid;
+ }
+ else if (prop.value == "normalmap_trans_vertex_alpha" ||
+ prop.value == "parallaxmap_trans_vertex_alpha")
+ {
+ matFlags = AI_IRRMESH_MAT_normalmap_tva;
+ }
+ else if (prop.value == "normalmap_trans_add" ||
+ prop.value == "parallaxmap_trans_add")
+ {
+ matFlags = AI_IRRMESH_MAT_normalmap_ta;
+ }
+ else {
+ DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value);
+ }
+ }
+
+ // Up to 4 texture channels are supported
+ if (prop.name == "Texture1")
+ {
+ // Always accept the primary texture channel
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ else if (prop.name == "Texture2" && cnt == 1)
+ {
+ // 2-layer material lightmapped?
+ if (matFlags & AI_IRRMESH_MAT_lightmap) {
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_LIGHTMAP(0));
+
+ // set the corresponding material flag
+ matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
+ }
+ // alternatively: normal or parallax mapping
+ else if (matFlags & AI_IRRMESH_MAT_normalmap_solid) {
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_NORMALS(0));
+
+ // set the corresponding material flag
+ matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
+ }
+ // or just as second diffuse texture
+ else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1));
+ ++nd;
+
+ // set the corresponding material flag
+ matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
+ }
+ else DefaultLogger::get()->warn("IRRmat: Skipping second texture");
+ }
+
+ else if (prop.name == "Texture3" && cnt == 2)
+ {
+ // Irrlicht does not seem to use these channels.
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1));
+ }
+ else if (prop.name == "Texture4" && cnt == 3)
+ {
+ // Irrlicht does not seem to use these channels.
+ ++cnt;
+ s.Set(prop.value);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+2));
+ }
+
+ // Texture mapping options
+ if (prop.name == "TextureWrap1" && cnt >= 1)
+ {
+ int map = ConvertMappingMode(prop.value);
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
+ }
+ else if (prop.name == "TextureWrap2" && cnt >= 2)
+ {
+ int map = ConvertMappingMode(prop.value);
+ if (matFlags & AI_IRRMESH_MAT_lightmap) {
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(0));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(0));
+ }
+ else if (matFlags & (AI_IRRMESH_MAT_normalmap_solid)) {
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_NORMALS(0));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_NORMALS(0));
+ }
+ else if (matFlags & AI_IRRMESH_MAT_solid_2layer) {
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(1));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(1));
+ }
+ }
+ else if (prop.name == "TextureWrap3" && cnt >= 3)
+ {
+ int map = ConvertMappingMode(prop.value);
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+1));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+1));
+ }
+ else if (prop.name == "TextureWrap4" && cnt >= 4)
+ {
+ int map = ConvertMappingMode(prop.value);
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+2));
+ mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+2));
+ }
+ }
+ }
+ break;
+ case EXN_ELEMENT_END:
+
+ /* Assume there are no further nested nodes in <material> elements
+ */
+ if (/* IRRMESH */ !ASSIMP_stricmp(reader->getNodeName(),"material") ||
+ /* IRR */ !ASSIMP_stricmp(reader->getNodeName(),"attributes"))
+ {
+ // Now process lightmapping flags
+ // We should have at least one textur to do that ..
+ if (cnt && matFlags & AI_IRRMESH_MAT_lightmap)
+ {
+ float f = 1.f;
+ unsigned int unmasked = matFlags&~AI_IRRMESH_MAT_lightmap;
+
+ // Additive lightmap?
+ int op = (unmasked & AI_IRRMESH_MAT_lightmap_add
+ ? aiTextureOp_Add : aiTextureOp_Multiply);
+
+ // Handle Irrlicht's lightmapping scaling factor
+ if (unmasked & AI_IRRMESH_MAT_lightmap_m2 ||
+ unmasked & AI_IRRMESH_MAT_lightmap_light_m2)
+ {
+ f = 2.f;
+ }
+ else if (unmasked & AI_IRRMESH_MAT_lightmap_m4 ||
+ unmasked & AI_IRRMESH_MAT_lightmap_light_m4)
+ {
+ f = 4.f;
+ }
+ mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_LIGHTMAP(0));
+ mat->AddProperty( &op,1, AI_MATKEY_TEXOP_LIGHTMAP(0));
+ }
+
+ return mat;
+ }
+ default:
+
+ // GCC complains here ...
+ break;
+ }
+ }
+ DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete");
+ return mat;
}
#endif // !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
diff --git a/src/3rdparty/assimp/code/IRRShared.h b/src/3rdparty/assimp/code/IRRShared.h
index 049411363..b5cd5d5ba 100644
--- a/src/3rdparty/assimp/code/IRRShared.h
+++ b/src/3rdparty/assimp/code/IRRShared.h
@@ -9,8 +9,11 @@
#include "irrXMLWrapper.h"
#include "BaseImporter.h"
+#include <stdint.h>
-namespace Assimp {
+struct aiMaterial;
+
+namespace Assimp {
/** @brief Matrix to convert from Assimp to IRR and backwards
@@ -19,83 +22,83 @@ extern const aiMatrix4x4 AI_TO_IRR_MATRIX;
// Default: 0 = solid, one texture
-#define AI_IRRMESH_MAT_solid_2layer 0x10000
+#define AI_IRRMESH_MAT_solid_2layer 0x10000
// Transparency flags
-#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1
-#define AI_IRRMESH_MAT_trans_add 0x2
+#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1
+#define AI_IRRMESH_MAT_trans_add 0x2
// Lightmapping flags
-#define AI_IRRMESH_MAT_lightmap 0x2
-#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4)
-#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x8)
-#define AI_IRRMESH_MAT_lightmap_light (AI_IRRMESH_MAT_lightmap|0x10)
-#define AI_IRRMESH_MAT_lightmap_light_m2 (AI_IRRMESH_MAT_lightmap|0x20)
-#define AI_IRRMESH_MAT_lightmap_light_m4 (AI_IRRMESH_MAT_lightmap|0x40)
-#define AI_IRRMESH_MAT_lightmap_add (AI_IRRMESH_MAT_lightmap|0x80)
+#define AI_IRRMESH_MAT_lightmap 0x2
+#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4)
+#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x8)
+#define AI_IRRMESH_MAT_lightmap_light (AI_IRRMESH_MAT_lightmap|0x10)
+#define AI_IRRMESH_MAT_lightmap_light_m2 (AI_IRRMESH_MAT_lightmap|0x20)
+#define AI_IRRMESH_MAT_lightmap_light_m4 (AI_IRRMESH_MAT_lightmap|0x40)
+#define AI_IRRMESH_MAT_lightmap_add (AI_IRRMESH_MAT_lightmap|0x80)
// Standard NormalMap (or Parallax map, they're treated equally)
-#define AI_IRRMESH_MAT_normalmap_solid (0x100)
+#define AI_IRRMESH_MAT_normalmap_solid (0x100)
// Normal map combined with vertex alpha
-#define AI_IRRMESH_MAT_normalmap_tva \
- (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_vertex_alpha)
+#define AI_IRRMESH_MAT_normalmap_tva \
+ (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_vertex_alpha)
// Normal map combined with additive transparency
-#define AI_IRRMESH_MAT_normalmap_ta \
- (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_add)
+#define AI_IRRMESH_MAT_normalmap_ta \
+ (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_add)
// Special flag. It indicates a second texture has been found
// Its type depends ... either a normal textue or a normal map
-#define AI_IRRMESH_EXTRA_2ND_TEXTURE 0x100000
+#define AI_IRRMESH_EXTRA_2ND_TEXTURE 0x100000
// ---------------------------------------------------------------------------
/** Base class for the Irr and IrrMesh importers.
*
* Declares some irrlight-related xml parsing utilities and provides tools
- * to load materials from IRR and IRRMESH files.
+ * to load materials from IRR and IRRMESH files.
*/
class IrrlichtBase
{
protected:
- /** @brief Data structure for a simple name-value property
- */
- template <class T>
- struct Property
- {
- std::string name;
- T value;
- };
-
- typedef Property<uint32_t> HexProperty;
- typedef Property<std::string> StringProperty;
- typedef Property<bool> BoolProperty;
- typedef Property<float> FloatProperty;
- typedef Property<aiVector3D> VectorProperty;
- typedef Property<int> IntProperty;
-
- /** XML reader instance
- */
+ /** @brief Data structure for a simple name-value property
+ */
+ template <class T>
+ struct Property
+ {
+ std::string name;
+ T value;
+ };
+
+ typedef Property<uint32_t> HexProperty;
+ typedef Property<std::string> StringProperty;
+ typedef Property<bool> BoolProperty;
+ typedef Property<float> FloatProperty;
+ typedef Property<aiVector3D> VectorProperty;
+ typedef Property<int> IntProperty;
+
+ /** XML reader instance
+ */
irr::io::IrrXMLReader* reader;
- // -------------------------------------------------------------------
- /** Parse a material description from the XML
- * @return The created material
- * @param matFlags Receives AI_IRRMESH_MAT_XX flags
- */
- aiMaterial* ParseMaterial(unsigned int& matFlags);
-
- // -------------------------------------------------------------------
- /** Read a property of the specified type from the current XML element.
- * @param out Recives output data
- */
- void ReadHexProperty (HexProperty& out);
- void ReadStringProperty (StringProperty& out);
- void ReadBoolProperty (BoolProperty& out);
- void ReadFloatProperty (FloatProperty& out);
- void ReadVectorProperty (VectorProperty& out);
- void ReadIntProperty (IntProperty& out);
+ // -------------------------------------------------------------------
+ /** Parse a material description from the XML
+ * @return The created material
+ * @param matFlags Receives AI_IRRMESH_MAT_XX flags
+ */
+ aiMaterial* ParseMaterial(unsigned int& matFlags);
+
+ // -------------------------------------------------------------------
+ /** Read a property of the specified type from the current XML element.
+ * @param out Recives output data
+ */
+ void ReadHexProperty (HexProperty& out);
+ void ReadStringProperty (StringProperty& out);
+ void ReadBoolProperty (BoolProperty& out);
+ void ReadFloatProperty (FloatProperty& out);
+ void ReadVectorProperty (VectorProperty& out);
+ void ReadIntProperty (IntProperty& out);
};
@@ -103,10 +106,10 @@ protected:
// Unpack a hex color, e.g. 0xdcdedfff
inline void ColorFromARGBPacked(uint32_t in, aiColor4D& clr)
{
- clr.a = ((in >> 24) & 0xff) / 255.f;
- clr.r = ((in >> 16) & 0xff) / 255.f;
- clr.g = ((in >> 8) & 0xff) / 255.f;
- clr.b = ((in ) & 0xff) / 255.f;
+ clr.a = ((in >> 24) & 0xff) / 255.f;
+ clr.r = ((in >> 16) & 0xff) / 255.f;
+ clr.g = ((in >> 8) & 0xff) / 255.f;
+ clr.b = ((in ) & 0xff) / 255.f;
}
diff --git a/src/3rdparty/assimp/code/Importer.cpp b/src/3rdparty/assimp/code/Importer.cpp
index ea81f4972..3599138eb 100644
--- a/src/3rdparty/assimp/code/Importer.cpp
+++ b/src/3rdparty/assimp/code/Importer.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,25 +43,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the CPP-API class #Importer
*/
-#include "AssimpPCH.h"
-#include "../include/assimp/version.h"
+#include <assimp/version.h>
// ------------------------------------------------------------------------------------------------
/* Uncomment this line to prevent Assimp from catching unknown exceptions.
*
- * Note that any Exception except DeadlyImportError may lead to
+ * 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
+# define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
#endif
// ------------------------------------------------------------------------------------------------
// Internal headers
// ------------------------------------------------------------------------------------------------
#include "Importer.h"
+#include "BaseImporter.h"
#include "BaseProcess.h"
#include "DefaultIOStream.h"
@@ -70,22 +70,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "GenericProperty.h"
#include "ProcessHelper.h"
#include "ScenePreprocessor.h"
+#include "ScenePrivate.h"
#include "MemoryIOWrapper.h"
#include "Profiler.h"
#include "TinyFormatter.h"
+#include "Exceptional.h"
+#include "Profiler.h"
+#include <set>
+#include <memory>
+#include <cctype>
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-# include "ValidateDataStructure.h"
+# include "ValidateDataStructure.h"
#endif
using namespace Assimp::Profiling;
using namespace Assimp::Formatter;
namespace Assimp {
- // ImporterRegistry.cpp
- void GetImporterInstanceList(std::vector< BaseImporter* >& out);
- // PostStepRegistry.cpp
- void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
+ // 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;
@@ -97,625 +105,638 @@ using namespace Assimp::Intern;
// 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) {
+ 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 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 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) {
+ 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;
- }
+ try {
+ return AllocateFromAssimpHeap::operator new[]( num_bytes );
+ }
+ catch( ... ) {
+ return NULL;
+ }
}
-void AllocateFromAssimpHeap::operator delete[] ( void* data) {
- return ::operator delete[](data);
+void AllocateFromAssimpHeap::operator delete[] ( void* data) {
+ return ::operator delete[](data);
}
// ------------------------------------------------------------------------------------------------
-// Importer constructor.
-Importer::Importer()
-{
- // allocate the pimpl first
- 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);
- }
+// Importer constructor.
+Importer::Importer()
+ : pimpl( NULL ) {
+ // allocate the pimpl first
+ 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
- for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)
- delete pimpl->mImporter[a];
+ // 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 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;
+ // Delete the assigned IO and progress handler
+ delete pimpl->mIOHandler;
+ delete pimpl->mProgressHandler;
- // Kill imported scene. Destructors should do that recursivly
- delete pimpl->mScene;
+ // Kill imported scene. Destructors should do that recursivly
+ delete pimpl->mScene;
- // Delete shared post-processing data
- delete pimpl->mPPShared;
+ // Delete shared post-processing data
+ delete pimpl->mPPShared;
- // and finally the pimpl itself
- delete pimpl;
+ // and finally the pimpl itself
+ delete pimpl;
}
// ------------------------------------------------------------------------------------------------
// Copy constructor - copies the config of another Importer, not the scene
Importer::Importer(const Importer &other)
-{
- new(this) Importer();
+ : pimpl(NULL) {
+ new(this) Importer();
- pimpl->mIntProperties = other.pimpl->mIntProperties;
- pimpl->mFloatProperties = other.pimpl->mFloatProperties;
- pimpl->mStringProperties = other.pimpl->mStringProperties;
- pimpl->mMatrixProperties = other.pimpl->mMatrixProperties;
+ pimpl->mIntProperties = other.pimpl->mIntProperties;
+ pimpl->mFloatProperties = other.pimpl->mFloatProperties;
+ pimpl->mStringProperties = other.pimpl->mStringProperties;
+ pimpl->mMatrixProperties = other.pimpl->mMatrixProperties;
}
// ------------------------------------------------------------------------------------------------
// Register a custom post-processing step
aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
{
- ai_assert(NULL != pImp);
- ASSIMP_BEGIN_EXCEPTION_REGION();
-
- pimpl->mPostProcessingSteps.push_back(pImp);
- DefaultLogger::get()->info("Registering custom post-processing step");
-
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_SUCCESS;
+ ai_assert(NULL != pImp);
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+
+ pimpl->mPostProcessingSteps.push_back(pImp);
+ DefaultLogger::get()->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();
+ 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);
+ // --------------------------------------------------------------------
+ // 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) {
+ for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
#ifdef ASSIMP_BUILD_DEBUG
- if (IsExtensionSupported(*it)) {
- DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
- }
+ if (IsExtensionSupported(*it)) {
+ DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
+ }
#endif
- baked += *it;
- }
-
- // add the loader
- pimpl->mImporter.push_back(pImp);
- DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_SUCCESS;
+ baked += *it;
+ }
+
+ // add the loader
+ pimpl->mImporter.push_back(pImp);
+ DefaultLogger::get()->info("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);
-
- std::set<std::string> st;
- pImp->GetExtensionList(st);
-
- DefaultLogger::get()->info("Unregistering custom importer: ");
- return AI_SUCCESS;
- }
- DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_FAILURE;
+ 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);
+
+ std::set<std::string> st;
+ pImp->GetExtensionList(st);
+
+ DefaultLogger::get()->info("Unregistering custom importer: ");
+ return AI_SUCCESS;
+ }
+ DefaultLogger::get()->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);
- DefaultLogger::get()->info("Unregistering custom post-processing step");
- return AI_SUCCESS;
- }
- DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_FAILURE;
+ 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);
+ DefaultLogger::get()->info("Unregistering custom post-processing step");
+ return AI_SUCCESS;
+ }
+ DefaultLogger::get()->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);
+ 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;
+ return pimpl->mIOHandler;
}
// ------------------------------------------------------------------------------------------------
// Check whether a custom IO handler is currently set
bool Importer::IsDefaultIOHandler() const
{
- return pimpl->mIsDefaultHandler;
+ 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);
+ 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;
+ return pimpl->mProgressHandler;
}
// ------------------------------------------------------------------------------------------------
// Check whether a custom progress handler is currently set
bool Importer::IsDefaultProgressHandler() const
{
- return pimpl->mIsDefaultProgressHandler;
+ return pimpl->mIsDefaultProgressHandler;
}
// ------------------------------------------------------------------------------------------------
-// Validate post process step flags
-bool _ValidateFlags(unsigned int pFlags)
+// Validate post process step flags
+bool _ValidateFlags(unsigned int pFlags)
{
- if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
- DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
- return false;
- }
- if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
- DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
- return false;
- }
- return true;
+ if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
+ DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
+ return false;
+ }
+ if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
+ DefaultLogger::get()->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;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ delete pimpl->mScene;
+ pimpl->mScene = NULL;
- pimpl->mErrorString = "";
- ASSIMP_END_EXCEPTION_REGION(void);
+ 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();
+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;
+ pimpl->bExtraVerbose = bDo;
}
// ------------------------------------------------------------------------------------------------
// Get the current scene
const aiScene* Importer::GetScene() const
{
- return pimpl->mScene;
+ return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
// Orphan the current scene and return it.
aiScene* Importer::GetOrphanedScene()
{
- aiScene* s = pimpl->mScene;
+ aiScene* s = pimpl->mScene;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- pimpl->mScene = NULL;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ pimpl->mScene = NULL;
- pimpl->mErrorString = ""; /* reset error string */
- ASSIMP_END_EXCEPTION_REGION(aiScene*);
- return s;
+ 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;
- }
+ 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 ...
+ // 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;
- }
+ 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;
+ 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 /*= ""*/)
+ size_t pLength,
+ unsigned int pFlags,
+ const char* pHint /*= ""*/)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- if (!pHint) {
- pHint = "";
- }
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ if (!pHint) {
+ pHint = "";
+ }
- if (!pBuffer || !pLength || strlen(pHint) > 100) {
- pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
- return NULL;
- }
+ 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;
+ // prevent deletion of the previous IOHandler
+ IOSystem* io = pimpl->mIOHandler;
+ pimpl->mIOHandler = NULL;
- SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
+ SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
- // read the file and recover the previous IOSystem
- char fbuff[128];
- sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
+ // read the file and recover the previous IOSystem
+ static const size_t BufferSize(Importer::MaxLenHint + 28);
+ char fbuff[ BufferSize ];
+ ai_snprintf(fbuff, BufferSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
- ReadFile(fbuff,pFlags);
- SetIOHandler(io);
+ ReadFile(fbuff,pFlags);
+ SetIOHandler(io);
- ASSIMP_END_EXCEPTION_REGION(const aiScene*);
- return pimpl->mScene;
+ ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ return pimpl->mScene;
}
// ------------------------------------------------------------------------------------------------
void WriteLogOpening(const std::string& file)
{
- Logger* l = DefaultLogger::get();
- if (!l) {
- return;
- }
- l->info("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();
- l->debug(format()
- << "Assimp "
- << aiGetVersionMajor()
- << "."
- << aiGetVersionMinor()
- << "."
- << aiGetVersionRevision()
-
- << " "
+ Logger* l = DefaultLogger::get();
+ if (!l) {
+ return;
+ }
+ l->info("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();
+ l->debug(format()
+ << "Assimp "
+ << aiGetVersionMajor()
+ << "."
+ << aiGetVersionMinor()
+ << "."
+ << aiGetVersionRevision()
+
+ << " "
#if defined(ASSIMP_BUILD_ARCHITECTURE)
- << ASSIMP_BUILD_ARCHITECTURE
+ << ASSIMP_BUILD_ARCHITECTURE
#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
- << "x86"
-#elif defined(_M_X64) || defined(__x86_64__)
- << "amd64"
+ << "x86"
+#elif defined(_M_X64) || defined(__x86_64__)
+ << "amd64"
#elif defined(_M_IA64) || defined(__ia64__)
- << "itanium"
+ << "itanium"
#elif defined(__ppc__) || defined(__powerpc__)
- << "ppc32"
+ << "ppc32"
#elif defined(__powerpc64__)
- << "ppc64"
+ << "ppc64"
#elif defined(__arm__)
- << "arm"
+ << "arm"
#else
- << "<unknown architecture>"
+ << "<unknown architecture>"
#endif
- << " "
+ << " "
#if defined(ASSIMP_BUILD_COMPILER)
- << ASSIMP_BUILD_COMPILER
+ << ASSIMP_BUILD_COMPILER
#elif defined(_MSC_VER)
- << "msvc"
+ << "msvc"
#elif defined(__GNUC__)
- << "gcc"
+ << "gcc"
#else
- << "<unknown compiler>"
+ << "<unknown compiler>"
#endif
#ifdef ASSIMP_BUILD_DEBUG
- << " debug"
+ << " debug"
#endif
- << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
- << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
- << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
- );
+ << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
+ << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
+ << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
+ );
}
// ------------------------------------------------------------------------------------------------
// 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);
+ 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.
- //-----------------------------------------------------------------------
+ // ----------------------------------------------------------------------
+ // 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);
+ WriteLogOpening(pFile);
#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- try
+ 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) {
-
- DefaultLogger::get()->debug("(Deleting previous scene)");
- FreeScene();
- }
-
- // First check if the file is accessable at all
- if( !pimpl->mIOHandler->Exists( pFile)) {
-
- pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
- DefaultLogger::get()->error(pimpl->mErrorString);
- return NULL;
- }
-
- boost::scoped_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;
- for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
-
- if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
- imp = pimpl->mImporter[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) {
- DefaultLogger::get()->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];
- 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 + "\".";
- DefaultLogger::get()->error(pimpl->mErrorString);
- return NULL;
- }
- }
-
- // Dispatch the reading to the worker class for this format
- DefaultLogger::get()->info("Found a matching importer for this file format");
- pimpl->mProgressHandler->Update();
-
- if (profiler) {
- profiler->BeginRegion("import");
- }
-
- pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
- pimpl->mProgressHandler->Update();
-
- if (profiler) {
- profiler->EndRegion("import");
- }
-
- // If successful, apply all active post processing steps to the imported data
- if( pimpl->mScene) {
+ {
+ // Check whether this Importer instance has already loaded
+ // a scene. In this case we need to delete the old one
+ if (pimpl->mScene) {
+
+ DefaultLogger::get()->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 + "\".";
+ DefaultLogger::get()->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;
+ for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
+
+ if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
+ imp = pimpl->mImporter[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) {
+ DefaultLogger::get()->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];
+ 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 + "\".";
+ DefaultLogger::get()->error(pimpl->mErrorString);
+ return NULL;
+ }
+ }
+
+ // Get file size for progress handler
+ IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
+ uint32_t fileSize = 0;
+ if (fileIO)
+ {
+ fileSize = 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;
+ }
+ DefaultLogger::get()->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");
+ }
+
+ // 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;
- }
- }
+ // 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();
-
- pimpl->mProgressHandler->Update();
- 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");
- }
- }
+ // 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 occured
- pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
+ 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();
+ pimpl->mErrorString = std::string("std::exception: ") + e.what();
#endif
- DefaultLogger::get()->error(pimpl->mErrorString);
- delete pimpl->mScene; pimpl->mScene = NULL;
- }
+ DefaultLogger::get()->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;
+ // either successful or failure - the pointer expresses it anyways
+ ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+ return pimpl->mScene;
}
@@ -723,374 +744,452 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// 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;
- }
+ 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;
- }
+ // 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));
- DefaultLogger::get()->info("Entering post processing pipeline");
+ // In debug builds: run basic flag validation
+ ai_assert(_ValidateFlags(pFlags));
+ DefaultLogger::get()->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;
- }
- }
+ // 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)
- {
+ if (pimpl->bExtraVerbose)
+ {
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- DefaultLogger::get()->error("Verbose Import is not available due to build settings");
+ DefaultLogger::get()->error("Verbose Import is not available due to build settings");
#endif // no validation
- pFlags |= aiProcess_ValidateDataStructure;
- }
+ pFlags |= aiProcess_ValidateDataStructure;
+ }
#else
- if (pimpl->bExtraVerbose) {
- DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
- }
+ if (pimpl->bExtraVerbose) {
+ DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
+ }
#endif // ! DEBUG
- boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
- for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+ 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];
- if( process->IsActive( pFlags)) {
+ BaseProcess* process = pimpl->mPostProcessingSteps[a];
+ pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
+ if( process->IsActive( pFlags)) {
- if (profiler) {
- profiler->BeginRegion("postprocess");
- }
+ if (profiler) {
+ profiler->BeginRegion("postprocess");
+ }
- process->ExecuteOnScene ( this );
- pimpl->mProgressHandler->Update();
+ process->ExecuteOnScene ( this );
- if (profiler) {
- profiler->EndRegion("postprocess");
- }
- }
- if( !pimpl->mScene) {
- break;
- }
+ if (profiler) {
+ profiler->EndRegion("postprocess");
+ }
+ }
+ if( !pimpl->mScene) {
+ break;
+ }
#ifdef ASSIMP_BUILD_DEBUG
#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- continue;
+ continue;
#endif // no validation
- // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
- if (pimpl->bExtraVerbose) {
- DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
-
- ValidateDSProcess ds;
- ds.ExecuteOnScene (this);
- if( !pimpl->mScene) {
- DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
- break;
- }
- }
+ // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
+ if (pimpl->bExtraVerbose) {
+ DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
+
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene (this);
+ if( !pimpl->mScene) {
+ DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
+ break;
+ }
+ }
#endif // ! DEBUG
- }
+ }
+ pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
- // update private scene flags
+ // update private scene flags
if( pimpl->mScene )
- ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
+ ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
+
+ // clear any data allocated by post-process steps
+ pimpl->mPPShared->Clean();
+ DefaultLogger::get()->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;
+ }
- // clear any data allocated by post-process steps
- pimpl->mPPShared->Clean();
- DefaultLogger::get()->info("Leaving post processing pipeline");
+ // If no flags are given, return the current scene with no further action
+ if ( NULL == rootProcess ) {
+ return pimpl->mScene;
+ }
- ASSIMP_END_EXCEPTION_REGION(const aiScene*);
- return pimpl->mScene;
+ // In debug builds: run basic flag validation
+ DefaultLogger::get()->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
+ DefaultLogger::get()->error( "Verbose Import is not available due to build settings" );
+#endif // no validation
+ }
+#else
+ if ( pimpl->bExtraVerbose ) {
+ DefaultLogger::get()->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 ) {
+ DefaultLogger::get()->debug( "Verbose Import: revalidating data structures" );
+
+ ValidateDSProcess ds;
+ ds.ExecuteOnScene( this );
+ if ( !pimpl->mScene ) {
+ DefaultLogger::get()->error( "Verbose Import: failed to revalidate data structures" );
+ }
+ }
+
+ // clear any data allocated by post-process steps
+ pimpl->mPPShared->Clean();
+ DefaultLogger::get()->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 NULL != GetImporter(szExtension);
+ return NULL != GetImporter(szExtension);
}
// ------------------------------------------------------------------------------------------------
size_t Importer::GetImporterCount() const
{
- return pimpl->mImporter.size();
+ return pimpl->mImporter.size();
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
{
- if (index >= pimpl->mImporter.size()) {
- return NULL;
- }
- return pimpl->mImporter[index]->GetInfo();
+ 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];
+ 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));
+ return GetImporter(GetImporterIndex(szExtension));
}
// ------------------------------------------------------------------------------------------------
// Find a loader plugin for a given file extension
size_t Importer::GetImporterIndex (const char* szExtension) const
{
- ai_assert(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);
-
- 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);
+ ai_assert(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);
+
+ 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);
- }
-
- 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);
+ 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);
+ }
+
+ 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
-void Importer::SetPropertyInteger(const char* szName, int iValue,
- bool* bWasExisting /*= NULL*/)
+bool Importer::SetPropertyInteger(const char* szName, int iValue)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue,bWasExisting);
- ASSIMP_END_EXCEPTION_REGION(void);
+ bool existing;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return existing;
}
// ------------------------------------------------------------------------------------------------
// Set a configuration property
-void Importer::SetPropertyFloat(const char* szName, float iValue,
- bool* bWasExisting /*= NULL*/)
+bool Importer::SetPropertyFloat(const char* szName, float iValue)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue,bWasExisting);
- ASSIMP_END_EXCEPTION_REGION(void);
+ bool exising;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ exising = SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return exising;
}
// ------------------------------------------------------------------------------------------------
// Set a configuration property
-void Importer::SetPropertyString(const char* szName, const std::string& value,
- bool* bWasExisting /*= NULL*/)
+bool Importer::SetPropertyString(const char* szName, const std::string& value)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value,bWasExisting);
- ASSIMP_END_EXCEPTION_REGION(void);
+ bool exising;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ exising = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return exising;
}
// ------------------------------------------------------------------------------------------------
// Set a configuration property
-void Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value,
- bool* bWasExisting /*= NULL*/)
+bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
{
- ASSIMP_BEGIN_EXCEPTION_REGION();
- SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value,bWasExisting);
- ASSIMP_END_EXCEPTION_REGION(void);
+ bool exising;
+ ASSIMP_BEGIN_EXCEPTION_REGION();
+ exising = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
+ ASSIMP_END_EXCEPTION_REGION(bool);
+ return exising;
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-int Importer::GetPropertyInteger(const char* szName,
- int iErrorReturn /*= 0xffffffff*/) const
+int Importer::GetPropertyInteger(const char* szName,
+ int iErrorReturn /*= 0xffffffff*/) const
{
- return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
+ return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-float Importer::GetPropertyFloat(const char* szName,
- float iErrorReturn /*= 10e10*/) const
+float Importer::GetPropertyFloat(const char* szName,
+ float iErrorReturn /*= 10e10*/) const
{
- return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
+ return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-const std::string Importer::GetPropertyString(const char* szName,
- const std::string& iErrorReturn /*= ""*/) const
+const std::string Importer::GetPropertyString(const char* szName,
+ const std::string& iErrorReturn /*= ""*/) const
{
- return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
+ return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
}
// ------------------------------------------------------------------------------------------------
// Get a configuration property
-const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
- const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
+const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName,
+ const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
{
- return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
+ 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]);
- }
+ 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 = 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;
+ // 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;
}
-
diff --git a/src/3rdparty/assimp/code/Importer.h b/src/3rdparty/assimp/code/Importer.h
index f2a7c524f..750b9bbbd 100644
--- a/src/3rdparty/assimp/code/Importer.h
+++ b/src/3rdparty/assimp/code/Importer.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,12 +42,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_IMPORTER_H
#define INCLUDED_AI_IMPORTER_H
-namespace Assimp {
+#include <map>
+#include <string>
+#include <vector>
+#include <assimp/matrix4x4.h>
+
+struct aiScene;
+
+namespace Assimp {
+ class ProgressHandler;
+ class IOSystem;
+ class BaseImporter;
+ class BaseProcess;
+ class SharedPostProcessInfo;
- class BaseImporter;
- class BaseProcess;
-
//! @cond never
// ---------------------------------------------------------------------------
/** @brief Internal PIMPL implementation for Assimp::Importer
@@ -56,60 +65,60 @@ namespace Assimp {
* 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
+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, float> FloatPropertyMap;
- typedef std::map<KeyType, std::string> StringPropertyMap;
- typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
+ // 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, float> FloatPropertyMap;
+ typedef std::map<KeyType, std::string> StringPropertyMap;
+ typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
public:
- /** IO handler to use for all file accesses. */
- IOSystem* mIOHandler;
- bool mIsDefaultHandler;
+ /** IO handler to use for all file accesses. */
+ IOSystem* mIOHandler;
+ bool mIsDefaultHandler;
- /** Progress handler for feedback. */
- ProgressHandler* mProgressHandler;
- bool mIsDefaultProgressHandler;
+ /** Progress handler for feedback. */
+ ProgressHandler* mProgressHandler;
+ bool mIsDefaultProgressHandler;
- /** Format-specific importer worker objects - one for each format we can read.*/
- std::vector< BaseImporter* > mImporter;
+ /** 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;
+ /** 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 imported data, if ReadFile() was successful, NULL otherwise. */
+ aiScene* mScene;
- /** The error description, if there was one. */
- std::string mErrorString;
+ /** The error description, if there was one. */
+ std::string mErrorString;
- /** List of integer properties */
- IntPropertyMap mIntProperties;
+ /** List of integer properties */
+ IntPropertyMap mIntProperties;
- /** List of floating-point properties */
- FloatPropertyMap mFloatProperties;
+ /** List of floating-point properties */
+ FloatPropertyMap mFloatProperties;
- /** List of string properties */
- StringPropertyMap mStringProperties;
+ /** List of string properties */
+ StringPropertyMap mStringProperties;
- /** List of Matrix properties */
- MatrixPropertyMap mMatrixProperties;
+ /** List of Matrix properties */
+ MatrixPropertyMap mMatrixProperties;
- /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
- * to be executed before and after every single postprocess step */
- bool bExtraVerbose;
+ /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
+ * to be executed before and after every single postprocess step */
+ bool bExtraVerbose;
- /** Used by post-process steps to share data */
- SharedPostProcessInfo* mPPShared;
+ /** Used by post-process steps to share data */
+ SharedPostProcessInfo* mPPShared;
};
//! @endcond
@@ -117,89 +126,89 @@ public:
struct BatchData;
// ---------------------------------------------------------------------------
-/** FOR IMPORTER PLUGINS ONLY: A helper class to the pleasure of importers
+/** 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 BatchLoader
+class BatchLoader
{
- // friend of Importer
+ // 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
+ //! @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 acess external files */
- BatchLoader(IOSystem* pIO);
- ~BatchLoader();
-
-
- // -------------------------------------------------------------------
- /** 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();
+
+
+ // -------------------------------------------------------------------
+ /** Construct a batch loader from a given IO system to be used
+ * to access external files */
+ explicit BatchLoader(IOSystem* pIO);
+ ~BatchLoader();
+
+
+ // -------------------------------------------------------------------
+ /** 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* data;
+ // No need to have that in the public API ...
+ BatchData* data;
};
}
diff --git a/src/3rdparty/assimp/code/ImporterRegistry.cpp b/src/3rdparty/assimp/code/ImporterRegistry.cpp
index 7b72c5eb6..d6a175963 100644
--- a/src/3rdparty/assimp/code/ImporterRegistry.cpp
+++ b/src/3rdparty/assimp/code/ImporterRegistry.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -46,251 +46,293 @@ directly (unless you are adding new loaders), instead use the
corresponding preprocessor flag to selectively disable formats.
*/
-#include "AssimpPCH.h"
-
// ------------------------------------------------------------------------------------------------
// Importers
// (include_new_importers_here)
// ------------------------------------------------------------------------------------------------
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
-# include "XFileImporter.h"
+# include "XFileImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
-# include "3DSLoader.h"
+# include "3DSLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
-# include "MD3Loader.h"
+# include "MD3Loader.h"
#endif
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
-# include "MDLLoader.h"
+# include "MDLLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
-# include "MD2Loader.h"
+# include "MD2Loader.h"
#endif
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
-# include "PlyLoader.h"
+# include "PlyLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
-# include "ASELoader.h"
+# include "ASELoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
-# include "ObjFileImporter.h"
+# include "ObjFileImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
-# include "HMPLoader.h"
+# include "HMPLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
-# include "SMDLoader.h"
+# include "SMDLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
-# include "MDCLoader.h"
+# include "MDCLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
-# include "MD5Loader.h"
+# include "MD5Loader.h"
#endif
#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
-# include "STLLoader.h"
+# include "STLLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
-# include "LWOLoader.h"
+# include "LWOLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
-# include "DXFLoader.h"
+# include "DXFLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
-# include "NFFLoader.h"
+# include "NFFLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
-# include "RawLoader.h"
+# include "RawLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
+# include "SIBImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
-# include "OFFLoader.h"
+# include "OFFLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER
-# include "ACLoader.h"
+# include "ACLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
-# include "BVHLoader.h"
+# include "BVHLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
-# include "IRRMeshLoader.h"
+# include "IRRMeshLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
-# include "IRRLoader.h"
+# include "IRRLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
-# include "Q3DLoader.h"
+# include "Q3DLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
-# include "B3DImporter.h"
+# include "B3DImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
-# include "ColladaLoader.h"
+# include "ColladaLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
-# include "TerragenLoader.h"
+# include "TerragenLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
-# include "CSMLoader.h"
+# include "CSMLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
-# include "UnrealLoader.h"
+# include "UnrealLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
-# include "LWSLoader.h"
+# include "LWSLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-# include "OgreImporter.h"
+# include "OgreImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+# include "OpenGEXImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
-# include "MS3DLoader.h"
+# include "MS3DLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER
-# include "COBLoader.h"
+# include "COBLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
-# include "BlenderLoader.h"
+# include "BlenderLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
-# include "Q3BSPFileImporter.h"
+# include "Q3BSPFileImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
-# include "NDOLoader.h"
+# include "NDOLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
-# include "IFCLoader.h"
+# include "IFCLoader.h"
#endif
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
# include "XGLLoader.h"
-#endif
+#endif
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
# include "FBXImporter.h"
-#endif
+#endif
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+# include "AssbinLoader.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+# include "glTFImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
+# include "C4DImporter.h"
+#endif
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+# include "D3MFImporter.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);
+ // ----------------------------------------------------------------------------
+ // 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());
+ out.push_back( new XFileImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER)
- out.push_back( new ObjFileImporter());
+ out.push_back( new ObjFileImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER)
- out.push_back( new Discreet3DSImporter());
+ out.push_back( new Discreet3DSImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER)
- out.push_back( new MD3Importer());
+ out.push_back( new MD3Importer());
#endif
#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER)
- out.push_back( new MD2Importer());
+ out.push_back( new MD2Importer());
#endif
#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER)
- out.push_back( new PLYImporter());
+ out.push_back( new PLYImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER)
- out.push_back( new MDLImporter());
+ out.push_back( new MDLImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER)
- out.push_back( new ASEImporter());
+ out.push_back( new ASEImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER)
- out.push_back( new HMPImporter());
+ out.push_back( new HMPImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER)
- out.push_back( new SMDImporter());
+ out.push_back( new SMDImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER)
- out.push_back( new MDCImporter());
+ out.push_back( new MDCImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER)
- out.push_back( new MD5Importer());
+ out.push_back( new MD5Importer());
#endif
#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER)
- out.push_back( new STLImporter());
+ out.push_back( new STLImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER)
- out.push_back( new LWOImporter());
+ out.push_back( new LWOImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER)
- out.push_back( new DXFImporter());
+ out.push_back( new DXFImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER)
- out.push_back( new NFFImporter());
+ out.push_back( new NFFImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
- out.push_back( new RAWImporter());
+ 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());
+ out.push_back( new OFFImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER)
- out.push_back( new AC3DImporter());
+ out.push_back( new AC3DImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER)
- out.push_back( new BVHLoader());
+ out.push_back( new BVHLoader());
#endif
#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER)
- out.push_back( new IRRMeshImporter());
+ out.push_back( new IRRMeshImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER)
- out.push_back( new IRRImporter());
+ out.push_back( new IRRImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER)
- out.push_back( new Q3DImporter());
+ out.push_back( new Q3DImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER)
- out.push_back( new B3DImporter());
+ out.push_back( new B3DImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER)
- out.push_back( new ColladaLoader());
+ out.push_back( new ColladaLoader());
#endif
#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER)
- out.push_back( new TerragenImporter());
+ out.push_back( new TerragenImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER)
- out.push_back( new CSMImporter());
+ out.push_back( new CSMImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER)
- out.push_back( new UnrealImporter());
+ out.push_back( new UnrealImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
- out.push_back( new LWSImporter());
+ out.push_back( new LWSImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER)
- out.push_back( new Ogre::OgreImporter());
+ 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());
+ out.push_back( new MS3DImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER)
- out.push_back( new COBImporter());
+ out.push_back( new COBImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER)
- out.push_back( new BlenderImporter());
+ out.push_back( new BlenderImporter());
#endif
#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER)
- out.push_back( new Q3BSPFileImporter() );
+ out.push_back( new Q3BSPFileImporter() );
#endif
#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER)
- out.push_back( new NDOImporter() );
+ out.push_back( new NDOImporter() );
#endif
#if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
- out.push_back( new IFCImporter() );
+ out.push_back( new IFCImporter() );
#endif
#if ( !defined ASSIMP_BUILD_NO_XGL_IMPORTER )
- out.push_back( new XGLImporter() );
+ out.push_back( new XGLImporter() );
#endif
#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
- out.push_back( new FBXImporter() );
+ 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() );
+#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
}
+/** 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]=NULL;
+ }//for
}
+
+} // namespace Assimp
diff --git a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
index b6aa338a6..9fd76508b 100644
--- a/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
+++ b/src/3rdparty/assimp/code/ImproveCacheLocality.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -46,335 +46,341 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* .. although overdraw rduction isn't implemented yet ...
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "ImproveCacheLocality.h"
#include "VertexTriangleAdjacency.h"
+#include "StringUtils.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <stdio.h>
+#include <stack>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() {
- configCacheDepth = PP_ICL_PTCACHE_SIZE;
+ configCacheDepth = PP_ICL_PTCACHE_SIZE;
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_ImproveCacheLocality) != 0;
+ return (pFlags & aiProcess_ImproveCacheLocality) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration
void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
- configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE);
+ // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
+ configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
{
- if (!pScene->mNumMeshes) {
- DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes");
- return;
- }
-
- DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
-
- float out = 0.f;
- unsigned int numf = 0, numm = 0;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++){
- const float res = ProcessMesh( pScene->mMeshes[a],a);
- if (res) {
- numf += pScene->mMeshes[a]->mNumFaces;
- out += res;
- ++numm;
- }
- }
- if (!DefaultLogger::isNullLogger()) {
- char szBuff[128]; // should be sufficiently large in every case
- ::sprintf(szBuff,"Cache relevant are %i meshes (%i faces). Average output ACMR is %f",
- numm,numf,out/numf);
-
- DefaultLogger::get()->info(szBuff);
- DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. ");
- }
+ if (!pScene->mNumMeshes) {
+ DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes");
+ return;
+ }
+
+ DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
+
+ float out = 0.f;
+ unsigned int numf = 0, numm = 0;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++){
+ const float res = ProcessMesh( pScene->mMeshes[a],a);
+ if (res) {
+ numf += pScene->mMeshes[a]->mNumFaces;
+ out += res;
+ ++numm;
+ }
+ }
+ if (!DefaultLogger::isNullLogger()) {
+ char szBuff[128]; // should be sufficiently large in every case
+ ai_snprintf(szBuff,128,"Cache relevant are %u meshes (%u faces). Average output ACMR is %f",
+ numm,numf,out/numf);
+
+ DefaultLogger::get()->info(szBuff);
+ DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. ");
+ }
}
// ------------------------------------------------------------------------------------------------
// Improves the cache coherency of a specific mesh
float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum)
{
- // TODO: rewrite this to use std::vector or boost::shared_array
- ai_assert(NULL != pMesh);
-
- // Check whether the input data is valid
- // - there must be vertices and faces
- // - all faces must be triangulated or we can't operate on them
- if (!pMesh->HasFaces() || !pMesh->HasPositions())
- return 0.f;
-
- if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
- DefaultLogger::get()->error("This algorithm works on triangle meshes only");
- return 0.f;
- }
-
- if(pMesh->mNumVertices <= configCacheDepth) {
- return 0.f;
- }
-
- float fACMR = 3.f;
- const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
-
- // Input ACMR is for logging purposes only
- if (!DefaultLogger::isNullLogger()) {
-
- unsigned int* piFIFOStack = new unsigned int[configCacheDepth];
- memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int));
- unsigned int* piCur = piFIFOStack;
- const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth;
-
- // count the number of cache misses
- unsigned int iCacheMisses = 0;
- for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
-
- for (unsigned int qq = 0; qq < 3;++qq) {
- bool bInCache = false;
-
- for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
- if (*pp == pcFace->mIndices[qq]) {
- // the vertex is in cache
- bInCache = true;
- break;
- }
- }
- if (!bInCache) {
- ++iCacheMisses;
- if (piCurEnd == piCur) {
- piCur = piFIFOStack;
- }
- *piCur++ = pcFace->mIndices[qq];
- }
- }
- }
- delete[] piFIFOStack;
- fACMR = (float)iCacheMisses / pMesh->mNumFaces;
- if (3.0 == fACMR) {
- char szBuff[128]; // should be sufficiently large in every case
-
- // the JoinIdenticalVertices process has not been executed on this
- // mesh, otherwise this value would normally be at least minimally
- // smaller than 3.0 ...
- sprintf(szBuff,"Mesh %i: Not suitable for vcache optimization",meshNum);
- DefaultLogger::get()->warn(szBuff);
- return 0.f;
- }
- }
-
- // first we need to build a vertex-triangle adjacency list
- VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true);
-
- // build a list to store per-vertex caching time stamps
- unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices];
- memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int));
-
- // allocate an empty output index buffer. We store the output indices in one large array.
- // Since the number of triangles won't change the input faces can be reused. This is how
- // we save thousands of redundant mini allocations for aiFace::mIndices
- const unsigned int iIdxCnt = pMesh->mNumFaces*3;
- unsigned int* const piIBOutput = new unsigned int[iIdxCnt];
- unsigned int* piCSIter = piIBOutput;
-
- // allocate the flag array to hold the information
- // whether a face has already been emitted or not
- std::vector<bool> abEmitted(pMesh->mNumFaces,false);
-
- // dead-end vertex index stack
- std::stack<unsigned int, std::vector<unsigned int> > sDeadEndVStack;
-
- // create a copy of the piNumTriPtr buffer
- unsigned int* const piNumTriPtr = adj.mLiveTriangles;
- const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
-
- // get the largest number of referenced triangles and allocate the "candidate buffer"
- unsigned int iMaxRefTris = 0; {
- const unsigned int* piCur = adj.mLiveTriangles;
- const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices;
- for (;piCur != piCurEnd;++piCur) {
- iMaxRefTris = std::max(iMaxRefTris,*piCur);
- }
- }
- unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
- unsigned int iCacheMisses = 0;
-
- // ...................................................................................
- /** PSEUDOCODE for the algorithm
-
- A = Build-Adjacency(I) Vertex-triangle adjacency
- L = Get-Triangle-Counts(A) Per-vertex live triangle counts
- C = Zero(Vertex-Count(I)) Per-vertex caching time stamps
- D = Empty-Stack() Dead-end vertex stack
- E = False(Triangle-Count(I)) Per triangle emitted flag
- O = Empty-Index-Buffer() Empty output buffer
- f = 0 Arbitrary starting vertex
- s = k+1, i = 1 Time stamp and cursor
- while f >= 0 For all valid fanning vertices
- N = Empty-Set() 1-ring of next candidates
- for each Triangle t in Neighbors(A, f)
- if !Emitted(E,t)
- for each Vertex v in t
- Append(O,v) Output vertex
- Push(D,v) Add to dead-end stack
- Insert(N,v) Register as candidate
- L[v] = L[v]-1 Decrease live triangle count
- if s-C[v] > k If not in cache
- C[v] = s Set time stamp
- s = s+1 Increment time stamp
- E[t] = true Flag triangle as emitted
- Select next fanning vertex
- f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
- return O
- */
- // ...................................................................................
-
- int ivdx = 0;
- int ics = 1;
- int iStampCnt = configCacheDepth+1;
- while (ivdx >= 0) {
-
- unsigned int icnt = piNumTriPtrNoModify[ivdx];
- unsigned int* piList = adj.GetAdjacentTriangles(ivdx);
- unsigned int* piCurCandidate = piCandidates;
-
- // get all triangles in the neighborhood
- for (unsigned int tri = 0; tri < icnt;++tri) {
-
- // if they have not yet been emitted, add them to the output IB
- const unsigned int fidx = *piList++;
- if (!abEmitted[fidx]) {
-
- // so iterate through all vertices of the current triangle
- const aiFace* pcFace = &pMesh->mFaces[ fidx ];
- for (unsigned int* p = pcFace->mIndices, *p2 = pcFace->mIndices+3;p != p2;++p) {
- const unsigned int dp = *p;
-
- // the current vertex won't have any free triangles after this step
- if (ivdx != (int)dp) {
- // append the vertex to the dead-end stack
- sDeadEndVStack.push(dp);
-
- // register as candidate for the next step
- *piCurCandidate++ = dp;
-
- // decrease the per-vertex triangle counts
- piNumTriPtr[dp]--;
- }
-
- // append the vertex to the output index buffer
- *piCSIter++ = dp;
-
- // if the vertex is not yet in cache, set its cache count
- if (iStampCnt-piCachingStamps[dp] > configCacheDepth) {
- piCachingStamps[dp] = iStampCnt++;
- ++iCacheMisses;
- }
- }
- // flag triangle as emitted
- abEmitted[fidx] = true;
- }
- }
-
- // the vertex has now no living adjacent triangles anymore
- piNumTriPtr[ivdx] = 0;
-
- // get next fanning vertex
- ivdx = -1;
- int max_priority = -1;
- for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
- const unsigned int dp = *piCur;
-
- // must have live triangles
- if (piNumTriPtr[dp] > 0) {
- int priority = 0;
-
- // will the vertex be in cache, even after fanning occurs?
- unsigned int tmp;
- if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) {
- priority = tmp;
- }
-
- // keep best candidate
- if (priority > max_priority) {
- max_priority = priority;
- ivdx = dp;
- }
- }
- }
- // did we reach a dead end?
- if (-1 == ivdx) {
- // need to get a non-local vertex for which we have a good chance that it is still
- // in the cache ...
- while (!sDeadEndVStack.empty()) {
- unsigned int iCachedIdx = sDeadEndVStack.top();
- sDeadEndVStack.pop();
- if (piNumTriPtr[ iCachedIdx ] > 0) {
- ivdx = iCachedIdx;
- break;
- }
- }
-
- if (-1 == ivdx) {
- // well, there isn't such a vertex. Simply get the next vertex in input order and
- // hope it is not too bad ...
- while (ics < (int)pMesh->mNumVertices) {
- ++ics;
- if (piNumTriPtr[ics] > 0) {
- ivdx = ics;
- break;
- }
- }
- }
- }
- }
- float fACMR2 = 0.0f;
- if (!DefaultLogger::isNullLogger()) {
- fACMR2 = (float)iCacheMisses / pMesh->mNumFaces;
-
- // very intense verbose logging ... prepare for much text if there are many meshes
- if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
- char szBuff[128]; // should be sufficiently large in every case
-
- ::sprintf(szBuff,"Mesh %i | ACMR in: %f out: %f | ~%.1f%%",meshNum,fACMR,fACMR2,
- ((fACMR - fACMR2) / fACMR) * 100.f);
- DefaultLogger::get()->debug(szBuff);
- }
-
- fACMR2 *= pMesh->mNumFaces;
- }
- // sort the output index buffer back to the input array
- piCSIter = piIBOutput;
- for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) {
- pcFace->mIndices[0] = *piCSIter++;
- pcFace->mIndices[1] = *piCSIter++;
- pcFace->mIndices[2] = *piCSIter++;
- }
-
- // delete temporary storage
- delete[] piCachingStamps;
- delete[] piIBOutput;
- delete[] piCandidates;
-
- return fACMR2;
+ // TODO: rewrite this to use std::vector or boost::shared_array
+ ai_assert(NULL != pMesh);
+
+ // Check whether the input data is valid
+ // - there must be vertices and faces
+ // - all faces must be triangulated or we can't operate on them
+ if (!pMesh->HasFaces() || !pMesh->HasPositions())
+ return 0.f;
+
+ if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
+ DefaultLogger::get()->error("This algorithm works on triangle meshes only");
+ return 0.f;
+ }
+
+ if(pMesh->mNumVertices <= configCacheDepth) {
+ return 0.f;
+ }
+
+ float fACMR = 3.f;
+ const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
+
+ // Input ACMR is for logging purposes only
+ if (!DefaultLogger::isNullLogger()) {
+
+ unsigned int* piFIFOStack = new unsigned int[configCacheDepth];
+ memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int));
+ unsigned int* piCur = piFIFOStack;
+ const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth;
+
+ // count the number of cache misses
+ unsigned int iCacheMisses = 0;
+ for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
+
+ for (unsigned int qq = 0; qq < 3;++qq) {
+ bool bInCache = false;
+
+ for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
+ if (*pp == pcFace->mIndices[qq]) {
+ // the vertex is in cache
+ bInCache = true;
+ break;
+ }
+ }
+ if (!bInCache) {
+ ++iCacheMisses;
+ if (piCurEnd == piCur) {
+ piCur = piFIFOStack;
+ }
+ *piCur++ = pcFace->mIndices[qq];
+ }
+ }
+ }
+ delete[] piFIFOStack;
+ fACMR = (float)iCacheMisses / pMesh->mNumFaces;
+ if (3.0 == fACMR) {
+ char szBuff[128]; // should be sufficiently large in every case
+
+ // the JoinIdenticalVertices process has not been executed on this
+ // mesh, otherwise this value would normally be at least minimally
+ // smaller than 3.0 ...
+ ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum);
+ DefaultLogger::get()->warn(szBuff);
+ return 0.f;
+ }
+ }
+
+ // first we need to build a vertex-triangle adjacency list
+ VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true);
+
+ // build a list to store per-vertex caching time stamps
+ unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices];
+ memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int));
+
+ // allocate an empty output index buffer. We store the output indices in one large array.
+ // Since the number of triangles won't change the input faces can be reused. This is how
+ // we save thousands of redundant mini allocations for aiFace::mIndices
+ const unsigned int iIdxCnt = pMesh->mNumFaces*3;
+ unsigned int* const piIBOutput = new unsigned int[iIdxCnt];
+ unsigned int* piCSIter = piIBOutput;
+
+ // allocate the flag array to hold the information
+ // whether a face has already been emitted or not
+ std::vector<bool> abEmitted(pMesh->mNumFaces,false);
+
+ // dead-end vertex index stack
+ std::stack<unsigned int, std::vector<unsigned int> > sDeadEndVStack;
+
+ // create a copy of the piNumTriPtr buffer
+ unsigned int* const piNumTriPtr = adj.mLiveTriangles;
+ const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
+
+ // get the largest number of referenced triangles and allocate the "candidate buffer"
+ unsigned int iMaxRefTris = 0; {
+ const unsigned int* piCur = adj.mLiveTriangles;
+ const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices;
+ for (;piCur != piCurEnd;++piCur) {
+ iMaxRefTris = std::max(iMaxRefTris,*piCur);
+ }
+ }
+ unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
+ unsigned int iCacheMisses = 0;
+
+ // ...................................................................................
+ /** PSEUDOCODE for the algorithm
+
+ A = Build-Adjacency(I) Vertex-triangle adjacency
+ L = Get-Triangle-Counts(A) Per-vertex live triangle counts
+ C = Zero(Vertex-Count(I)) Per-vertex caching time stamps
+ D = Empty-Stack() Dead-end vertex stack
+ E = False(Triangle-Count(I)) Per triangle emitted flag
+ O = Empty-Index-Buffer() Empty output buffer
+ f = 0 Arbitrary starting vertex
+ s = k+1, i = 1 Time stamp and cursor
+ while f >= 0 For all valid fanning vertices
+ N = Empty-Set() 1-ring of next candidates
+ for each Triangle t in Neighbors(A, f)
+ if !Emitted(E,t)
+ for each Vertex v in t
+ Append(O,v) Output vertex
+ Push(D,v) Add to dead-end stack
+ Insert(N,v) Register as candidate
+ L[v] = L[v]-1 Decrease live triangle count
+ if s-C[v] > k If not in cache
+ C[v] = s Set time stamp
+ s = s+1 Increment time stamp
+ E[t] = true Flag triangle as emitted
+ Select next fanning vertex
+ f = Get-Next-Vertex(I,i,k,N,C,s,L,D)
+ return O
+ */
+ // ...................................................................................
+
+ int ivdx = 0;
+ int ics = 1;
+ int iStampCnt = configCacheDepth+1;
+ while (ivdx >= 0) {
+
+ unsigned int icnt = piNumTriPtrNoModify[ivdx];
+ unsigned int* piList = adj.GetAdjacentTriangles(ivdx);
+ unsigned int* piCurCandidate = piCandidates;
+
+ // get all triangles in the neighborhood
+ for (unsigned int tri = 0; tri < icnt;++tri) {
+
+ // if they have not yet been emitted, add them to the output IB
+ const unsigned int fidx = *piList++;
+ if (!abEmitted[fidx]) {
+
+ // so iterate through all vertices of the current triangle
+ const aiFace* pcFace = &pMesh->mFaces[ fidx ];
+ for (unsigned int* p = pcFace->mIndices, *p2 = pcFace->mIndices+3;p != p2;++p) {
+ const unsigned int dp = *p;
+
+ // the current vertex won't have any free triangles after this step
+ if (ivdx != (int)dp) {
+ // append the vertex to the dead-end stack
+ sDeadEndVStack.push(dp);
+
+ // register as candidate for the next step
+ *piCurCandidate++ = dp;
+
+ // decrease the per-vertex triangle counts
+ piNumTriPtr[dp]--;
+ }
+
+ // append the vertex to the output index buffer
+ *piCSIter++ = dp;
+
+ // if the vertex is not yet in cache, set its cache count
+ if (iStampCnt-piCachingStamps[dp] > configCacheDepth) {
+ piCachingStamps[dp] = iStampCnt++;
+ ++iCacheMisses;
+ }
+ }
+ // flag triangle as emitted
+ abEmitted[fidx] = true;
+ }
+ }
+
+ // the vertex has now no living adjacent triangles anymore
+ piNumTriPtr[ivdx] = 0;
+
+ // get next fanning vertex
+ ivdx = -1;
+ int max_priority = -1;
+ for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) {
+ const unsigned int dp = *piCur;
+
+ // must have live triangles
+ if (piNumTriPtr[dp] > 0) {
+ int priority = 0;
+
+ // will the vertex be in cache, even after fanning occurs?
+ unsigned int tmp;
+ if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) {
+ priority = tmp;
+ }
+
+ // keep best candidate
+ if (priority > max_priority) {
+ max_priority = priority;
+ ivdx = dp;
+ }
+ }
+ }
+ // did we reach a dead end?
+ if (-1 == ivdx) {
+ // need to get a non-local vertex for which we have a good chance that it is still
+ // in the cache ...
+ while (!sDeadEndVStack.empty()) {
+ unsigned int iCachedIdx = sDeadEndVStack.top();
+ sDeadEndVStack.pop();
+ if (piNumTriPtr[ iCachedIdx ] > 0) {
+ ivdx = iCachedIdx;
+ break;
+ }
+ }
+
+ if (-1 == ivdx) {
+ // well, there isn't such a vertex. Simply get the next vertex in input order and
+ // hope it is not too bad ...
+ while (ics < (int)pMesh->mNumVertices) {
+ ++ics;
+ if (piNumTriPtr[ics] > 0) {
+ ivdx = ics;
+ break;
+ }
+ }
+ }
+ }
+ }
+ float fACMR2 = 0.0f;
+ if (!DefaultLogger::isNullLogger()) {
+ fACMR2 = (float)iCacheMisses / pMesh->mNumFaces;
+
+ // very intense verbose logging ... prepare for much text if there are many meshes
+ if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
+ char szBuff[128]; // should be sufficiently large in every case
+
+ ai_snprintf(szBuff,128,"Mesh %u | ACMR in: %f out: %f | ~%.1f%%",meshNum,fACMR,fACMR2,
+ ((fACMR - fACMR2) / fACMR) * 100.f);
+ DefaultLogger::get()->debug(szBuff);
+ }
+
+ fACMR2 *= pMesh->mNumFaces;
+ }
+ // sort the output index buffer back to the input array
+ piCSIter = piIBOutput;
+ for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) {
+ pcFace->mIndices[0] = *piCSIter++;
+ pcFace->mIndices[1] = *piCSIter++;
+ pcFace->mIndices[2] = *piCSIter++;
+ }
+
+ // delete temporary storage
+ delete[] piCachingStamps;
+ delete[] piIBOutput;
+ delete[] piCandidates;
+
+ return fACMR2;
}
diff --git a/src/3rdparty/assimp/code/ImproveCacheLocality.h b/src/3rdparty/assimp/code/ImproveCacheLocality.h
index 4d17d9c84..d43f37f50 100644
--- a/src/3rdparty/assimp/code/ImproveCacheLocality.h
+++ b/src/3rdparty/assimp/code/ImproveCacheLocality.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,28 +23,28 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to reorder faces for
+/** @file Defines a post processing step to reorder faces for
better cache locality*/
#ifndef AI_IMPROVECACHELOCALITY_H_INC
#define AI_IMPROVECACHELOCALITY_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
struct aiMesh;
@@ -62,35 +62,35 @@ class ImproveCacheLocalityProcess : public BaseProcess
{
public:
- ImproveCacheLocalityProcess();
- ~ImproveCacheLocalityProcess();
+ ImproveCacheLocalityProcess();
+ ~ImproveCacheLocalityProcess();
public:
- // -------------------------------------------------------------------
- // Check whether the pp step is active
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ // Check whether the pp step is active
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- // Executes the pp step on a given scene
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ // Executes the pp step on a given scene
+ void Execute( aiScene* pScene);
- // -------------------------------------------------------------------
- // Configures the pp step
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ // Configures the pp step
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Executes the postprocessing step on the given mesh
- * @param pMesh The mesh to process.
- * @param meshNum Index of the mesh to process
- */
- float ProcessMesh( aiMesh* pMesh, unsigned int meshNum);
+ // -------------------------------------------------------------------
+ /** Executes the postprocessing step on the given mesh
+ * @param pMesh The mesh to process.
+ * @param meshNum Index of the mesh to process
+ */
+ float ProcessMesh( aiMesh* pMesh, unsigned int meshNum);
private:
- //! Configuration parameter: specifies the size of the cache to
- //! optimize the vertex data for.
- unsigned int configCacheDepth;
+ //! Configuration parameter: specifies the size of the cache to
+ //! optimize the vertex data for.
+ unsigned int configCacheDepth;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/JoinVerticesProcess.cpp b/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
index bd75bae3b..9cd34e1d0 100644
--- a/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
+++ b/src/3rdparty/assimp/code/JoinVerticesProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,372 +43,374 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* for all imported meshes
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
#include "JoinVerticesProcess.h"
#include "ProcessHelper.h"
#include "Vertex.h"
#include "TinyFormatter.h"
+#include <stdio.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
JoinVerticesProcess::JoinVerticesProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
JoinVerticesProcess::~JoinVerticesProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_JoinIdenticalVertices) != 0;
+ return (pFlags & aiProcess_JoinIdenticalVertices) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void JoinVerticesProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("JoinVerticesProcess begin");
-
- // get the total number of vertices BEFORE the step is executed
- int iNumOldVertices = 0;
- if (!DefaultLogger::isNullLogger()) {
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
- iNumOldVertices += pScene->mMeshes[a]->mNumVertices;
- }
- }
-
- // execute the step
- int iNumVertices = 0;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
-
- // if logging is active, print detailed statistics
- if (!DefaultLogger::isNullLogger())
- {
- if (iNumOldVertices == iNumVertices)
- {
- DefaultLogger::get()->debug("JoinVerticesProcess finished ");
- } else
- {
- char szBuff[128]; // should be sufficiently large in every case
- sprintf(szBuff,"JoinVerticesProcess finished | Verts in: %i out: %i | ~%.1f%%",
- iNumOldVertices,
- iNumVertices,
- ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f);
- DefaultLogger::get()->info(szBuff);
- }
- }
-
- pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ DefaultLogger::get()->debug("JoinVerticesProcess begin");
+
+ // get the total number of vertices BEFORE the step is executed
+ int iNumOldVertices = 0;
+ if (!DefaultLogger::isNullLogger()) {
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+ iNumOldVertices += pScene->mMeshes[a]->mNumVertices;
+ }
+ }
+
+ // execute the step
+ int iNumVertices = 0;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
+
+ // if logging is active, print detailed statistics
+ if (!DefaultLogger::isNullLogger())
+ {
+ if (iNumOldVertices == iNumVertices)
+ {
+ DefaultLogger::get()->debug("JoinVerticesProcess finished ");
+ } else
+ {
+ char szBuff[128]; // should be sufficiently large in every case
+ ::ai_snprintf(szBuff,128,"JoinVerticesProcess finished | Verts in: %i out: %i | ~%.1f%%",
+ iNumOldVertices,
+ iNumVertices,
+ ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f);
+ DefaultLogger::get()->info(szBuff);
+ }
+ }
+
+ pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
}
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
{
- BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_COLOR_SETS == 8);
- BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8);
-
- // Return early if we don't have any positions
- if (!pMesh->HasPositions() || !pMesh->HasFaces()) {
- return 0;
- }
-
- // We'll never have more vertices afterwards.
- std::vector<Vertex> uniqueVertices;
- uniqueVertices.reserve( pMesh->mNumVertices);
-
- // For each vertex the index of the vertex it was replaced by.
- // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark
- // whether a new vertex was created for the index (true) or if it was replaced by an existing
- // unique vertex (false). This saves an additional std::vector<bool> and greatly enhances
- // branching performance.
- BOOST_STATIC_ASSERT(AI_MAX_VERTICES == 0x7fffffff);
- std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
-
- // A little helper to find locally close vertices faster.
- // Try to reuse the lookup table from the last step.
- const static float epsilon = 1e-5f;
- // float posEpsilonSqr;
- SpatialSort* vertexFinder = NULL;
- SpatialSort _vertexFinder;
-
- typedef std::pair<SpatialSort,float> SpatPair;
- if (shared) {
- std::vector<SpatPair >* avf;
- shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
- if (avf) {
- SpatPair& blubb = (*avf)[meshIndex];
- vertexFinder = &blubb.first;
- // posEpsilonSqr = blubb.second;
- }
- }
- if (!vertexFinder) {
- // bad, need to compute it.
- _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
- vertexFinder = &_vertexFinder;
- // posEpsilonSqr = ComputePositionEpsilon(pMesh);
- }
-
- // Squared because we check against squared length of the vector difference
- static const float squareEpsilon = epsilon * epsilon;
-
- // Again, better waste some bytes than a realloc ...
- std::vector<unsigned int> verticesFound;
- verticesFound.reserve(10);
-
- // Run an optimized code path if we don't have multiple UVs or vertex colors.
- // This should yield false in more than 99% of all imports ...
- const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
-
- // Now check each vertex if it brings something new to the table
- for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
- // collect the vertex data
- Vertex v(pMesh,a);
-
- // collect all vertices that are close enough to the given position
- vertexFinder->FindIdenticalPositions( v.position, verticesFound);
- unsigned int matchIndex = 0xffffffff;
-
- // check all unique vertices close to the position if this vertex is already present among them
- for( unsigned int b = 0; b < verticesFound.size(); b++) {
-
- const unsigned int vidx = verticesFound[b];
- const unsigned int uidx = replaceIndex[ vidx];
- if( uidx & 0x80000000)
- continue;
-
- const Vertex& uv = uniqueVertices[ uidx];
- // Position mismatch is impossible - the vertex finder already discarded all non-matching positions
-
- // We just test the other attributes even if they're not present in the mesh.
- // In this case they're initialized to 0 so the comparision succeeds.
- // By this method the non-present attributes are effectively ignored in the comparision.
- if( (uv.normal - v.normal).SquareLength() > squareEpsilon)
- continue;
- if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon)
- continue;
- if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon)
- continue;
- if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon)
- continue;
-
- // Usually we won't have vertex colors or multiple UVs, so we can skip from here
- // Actually this increases runtime performance slightly, at least if branch
- // prediction is on our side.
- if (complex){
- // manually unrolled because continue wouldn't work as desired in an inner loop,
- // also because some compilers seem to fail the task. Colors and UV coords
- // are interleaved since the higher entries are most likely to be
- // zero and thus useless. By interleaving the arrays, vertices are,
- // on average, rejected earlier.
-
- if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon)
- continue;
-
- if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon)
- continue;
- if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon)
- continue;
-
- if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon)
- continue;
- }
-
- // we're still here -> this vertex perfectly matches our given vertex
- matchIndex = uidx;
- break;
- }
-
- // found a replacement vertex among the uniques?
- if( matchIndex != 0xffffffff)
- {
- // store where to found the matching unique vertex
- replaceIndex[a] = matchIndex | 0x80000000;
- }
- else
- {
- // no unique vertex matches it upto now -> so add it
- replaceIndex[a] = (unsigned int)uniqueVertices.size();
- uniqueVertices.push_back( v);
- }
- }
-
- if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
- DefaultLogger::get()->debug((Formatter::format(),
- "Mesh ",meshIndex,
- " (",
- (pMesh->mName.length ? pMesh->mName.data : "unnamed"),
- ") | Verts in: ",pMesh->mNumVertices,
- " out: ",
- uniqueVertices.size(),
- " | ~",
- ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f,
- "%"
- ));
- }
-
- // replace vertex data with the unique data sets
- pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
-
- // ----------------------------------------------------------------------------
- // NOTE - we're *not* calling Vertex::SortBack() because it would check for
- // presence of every single vertex component once PER VERTEX. And our CPU
- // dislikes branches, even if they're easily predictable.
- // ----------------------------------------------------------------------------
-
- // Position
- delete [] pMesh->mVertices;
- pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
- for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
- pMesh->mVertices[a] = uniqueVertices[a].position;
-
- // Normals, if present
- if( pMesh->mNormals)
- {
- delete [] pMesh->mNormals;
- pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
- for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
- pMesh->mNormals[a] = uniqueVertices[a].normal;
- }
- }
- // Tangents, if present
- if( pMesh->mTangents)
- {
- delete [] pMesh->mTangents;
- pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
- for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
- pMesh->mTangents[a] = uniqueVertices[a].tangent;
- }
- }
- // Bitangents as well
- if( pMesh->mBitangents)
- {
- delete [] pMesh->mBitangents;
- pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
- for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
- pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
- }
- }
- // Vertex colors
- for( unsigned int a = 0; pMesh->HasVertexColors(a); a++)
- {
- delete [] pMesh->mColors[a];
- pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
- for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
- pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
- }
- }
- // Texture coords
- for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
- {
- delete [] pMesh->mTextureCoords[a];
- pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
- for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
- pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
- }
- }
-
- // adjust the indices in all faces
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
- {
- aiFace& face = pMesh->mFaces[a];
- for( unsigned int b = 0; b < face.mNumIndices; b++) {
- face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000;
- }
- }
-
- // adjust bone vertex weights.
- for( int a = 0; a < (int)pMesh->mNumBones; a++)
- {
- aiBone* bone = pMesh->mBones[a];
- std::vector<aiVertexWeight> newWeights;
- newWeights.reserve( bone->mNumWeights);
-
- for( unsigned int b = 0; b < bone->mNumWeights; b++)
- {
- const aiVertexWeight& ow = bone->mWeights[b];
- // if the vertex is a unique one, translate it
- if( !(replaceIndex[ow.mVertexId] & 0x80000000))
- {
- aiVertexWeight nw;
- nw.mVertexId = replaceIndex[ow.mVertexId];
- nw.mWeight = ow.mWeight;
- newWeights.push_back( nw);
- }
- }
-
- if (newWeights.size() > 0) {
- // kill the old and replace them with the translated weights
- delete [] bone->mWeights;
- bone->mNumWeights = (unsigned int)newWeights.size();
-
- bone->mWeights = new aiVertexWeight[bone->mNumWeights];
- memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
- }
- else {
-
- /* NOTE:
- *
- * In the algorithm above we're assuming that there are no vertices
- * with a different bone weight setup at the same position. That wouldn't
- * make sense, but it is not absolutely impossible. SkeletonMeshBuilder
- * for example generates such input data if two skeleton points
- * share the same position. Again this doesn't make sense but is
- * reality for some model formats (MD5 for example uses these special
- * nodes as attachment tags for its weapons).
- *
- * Then it is possible that a bone has no weights anymore .... as a quick
- * workaround, we're just removing these bones. If they're animated,
- * model geometry might be modified but at least there's no risk of a crash.
- */
- delete bone;
- --pMesh->mNumBones;
- for (unsigned int n = a; n < pMesh->mNumBones; ++n) {
- pMesh->mBones[n] = pMesh->mBones[n+1];
- }
-
- --a;
- DefaultLogger::get()->warn("Removing bone -> no weights remaining");
- }
- }
- return pMesh->mNumVertices;
+ static_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 8, "AI_MAX_NUMBER_OF_COLOR_SETS == 8");
+ static_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8, "AI_MAX_NUMBER_OF_TEXTURECOORDS == 8");
+
+ // Return early if we don't have any positions
+ if (!pMesh->HasPositions() || !pMesh->HasFaces()) {
+ return 0;
+ }
+
+ // We'll never have more vertices afterwards.
+ std::vector<Vertex> uniqueVertices;
+ uniqueVertices.reserve( pMesh->mNumVertices);
+
+ // For each vertex the index of the vertex it was replaced by.
+ // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark
+ // whether a new vertex was created for the index (true) or if it was replaced by an existing
+ // unique vertex (false). This saves an additional std::vector<bool> and greatly enhances
+ // branching performance.
+ static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff");
+ std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff);
+
+ // A little helper to find locally close vertices faster.
+ // Try to reuse the lookup table from the last step.
+ const static float epsilon = 1e-5f;
+ // float posEpsilonSqr;
+ SpatialSort* vertexFinder = NULL;
+ SpatialSort _vertexFinder;
+
+ typedef std::pair<SpatialSort,float> SpatPair;
+ if (shared) {
+ std::vector<SpatPair >* avf;
+ shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
+ if (avf) {
+ SpatPair& blubb = (*avf)[meshIndex];
+ vertexFinder = &blubb.first;
+ // posEpsilonSqr = blubb.second;
+ }
+ }
+ if (!vertexFinder) {
+ // bad, need to compute it.
+ _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
+ vertexFinder = &_vertexFinder;
+ // posEpsilonSqr = ComputePositionEpsilon(pMesh);
+ }
+
+ // Squared because we check against squared length of the vector difference
+ static const float squareEpsilon = epsilon * epsilon;
+
+ // Again, better waste some bytes than a realloc ...
+ std::vector<unsigned int> verticesFound;
+ verticesFound.reserve(10);
+
+ // Run an optimized code path if we don't have multiple UVs or vertex colors.
+ // This should yield false in more than 99% of all imports ...
+ const bool complex = ( pMesh->GetNumColorChannels() > 0 || pMesh->GetNumUVChannels() > 1);
+
+ // Now check each vertex if it brings something new to the table
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ // collect the vertex data
+ Vertex v(pMesh,a);
+
+ // collect all vertices that are close enough to the given position
+ vertexFinder->FindIdenticalPositions( v.position, verticesFound);
+ unsigned int matchIndex = 0xffffffff;
+
+ // check all unique vertices close to the position if this vertex is already present among them
+ for( unsigned int b = 0; b < verticesFound.size(); b++) {
+
+ const unsigned int vidx = verticesFound[b];
+ const unsigned int uidx = replaceIndex[ vidx];
+ if( uidx & 0x80000000)
+ continue;
+
+ const Vertex& uv = uniqueVertices[ uidx];
+ // Position mismatch is impossible - the vertex finder already discarded all non-matching positions
+
+ // We just test the other attributes even if they're not present in the mesh.
+ // In this case they're initialized to 0 so the comparison succeeds.
+ // By this method the non-present attributes are effectively ignored in the comparison.
+ if( (uv.normal - v.normal).SquareLength() > squareEpsilon)
+ continue;
+ if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon)
+ continue;
+ if( (uv.tangent - v.tangent).SquareLength() > squareEpsilon)
+ continue;
+ if( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon)
+ continue;
+
+ // Usually we won't have vertex colors or multiple UVs, so we can skip from here
+ // Actually this increases runtime performance slightly, at least if branch
+ // prediction is on our side.
+ if (complex){
+ // manually unrolled because continue wouldn't work as desired in an inner loop,
+ // also because some compilers seem to fail the task. Colors and UV coords
+ // are interleaved since the higher entries are most likely to be
+ // zero and thus useless. By interleaving the arrays, vertices are,
+ // on average, rejected earlier.
+
+ if( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[4] - v.texcoords[4]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[5] - v.texcoords[5]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[4], v.colors[4]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[6] - v.texcoords[6]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[5], v.colors[5]) > squareEpsilon)
+ continue;
+
+ if( (uv.texcoords[7] - v.texcoords[7]).SquareLength() > squareEpsilon)
+ continue;
+ if( GetColorDifference( uv.colors[6], v.colors[6]) > squareEpsilon)
+ continue;
+
+ if( GetColorDifference( uv.colors[7], v.colors[7]) > squareEpsilon)
+ continue;
+ }
+
+ // we're still here -> this vertex perfectly matches our given vertex
+ matchIndex = uidx;
+ break;
+ }
+
+ // found a replacement vertex among the uniques?
+ if( matchIndex != 0xffffffff)
+ {
+ // store where to found the matching unique vertex
+ replaceIndex[a] = matchIndex | 0x80000000;
+ }
+ else
+ {
+ // no unique vertex matches it up to now -> so add it
+ replaceIndex[a] = (unsigned int)uniqueVertices.size();
+ uniqueVertices.push_back( v);
+ }
+ }
+
+ if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
+ DefaultLogger::get()->debug((Formatter::format(),
+ "Mesh ",meshIndex,
+ " (",
+ (pMesh->mName.length ? pMesh->mName.data : "unnamed"),
+ ") | Verts in: ",pMesh->mNumVertices,
+ " out: ",
+ uniqueVertices.size(),
+ " | ~",
+ ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f,
+ "%"
+ ));
+ }
+
+ // replace vertex data with the unique data sets
+ pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
+
+ // ----------------------------------------------------------------------------
+ // NOTE - we're *not* calling Vertex::SortBack() because it would check for
+ // presence of every single vertex component once PER VERTEX. And our CPU
+ // dislikes branches, even if they're easily predictable.
+ // ----------------------------------------------------------------------------
+
+ // Position
+ delete [] pMesh->mVertices;
+ pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
+ pMesh->mVertices[a] = uniqueVertices[a].position;
+
+ // Normals, if present
+ if( pMesh->mNormals)
+ {
+ delete [] pMesh->mNormals;
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mNormals[a] = uniqueVertices[a].normal;
+ }
+ }
+ // Tangents, if present
+ if( pMesh->mTangents)
+ {
+ delete [] pMesh->mTangents;
+ pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mTangents[a] = uniqueVertices[a].tangent;
+ }
+ }
+ // Bitangents as well
+ if( pMesh->mBitangents)
+ {
+ delete [] pMesh->mBitangents;
+ pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+ pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
+ }
+ }
+ // Vertex colors
+ for( unsigned int a = 0; pMesh->HasVertexColors(a); a++)
+ {
+ delete [] pMesh->mColors[a];
+ pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
+ for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+ pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
+ }
+ }
+ // Texture coords
+ for( unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
+ {
+ delete [] pMesh->mTextureCoords[a];
+ pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
+ for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+ pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
+ }
+ }
+
+ // adjust the indices in all faces
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+ {
+ aiFace& face = pMesh->mFaces[a];
+ for( unsigned int b = 0; b < face.mNumIndices; b++) {
+ face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000;
+ }
+ }
+
+ // adjust bone vertex weights.
+ for( int a = 0; a < (int)pMesh->mNumBones; a++) {
+ aiBone* bone = pMesh->mBones[a];
+ std::vector<aiVertexWeight> newWeights;
+ newWeights.reserve( bone->mNumWeights);
+
+ if ( NULL != bone->mWeights ) {
+ for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) {
+ const aiVertexWeight& ow = bone->mWeights[ b ];
+ // if the vertex is a unique one, translate it
+ if ( !( replaceIndex[ ow.mVertexId ] & 0x80000000 ) ) {
+ aiVertexWeight nw;
+ nw.mVertexId = replaceIndex[ ow.mVertexId ];
+ nw.mWeight = ow.mWeight;
+ newWeights.push_back( nw );
+ }
+ }
+ } else {
+ DefaultLogger::get()->error( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
+ }
+
+ if (newWeights.size() > 0) {
+ // kill the old and replace them with the translated weights
+ delete [] bone->mWeights;
+ bone->mNumWeights = (unsigned int)newWeights.size();
+
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+ memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight));
+ }
+ else {
+
+ /* NOTE:
+ *
+ * In the algorithm above we're assuming that there are no vertices
+ * with a different bone weight setup at the same position. That wouldn't
+ * make sense, but it is not absolutely impossible. SkeletonMeshBuilder
+ * for example generates such input data if two skeleton points
+ * share the same position. Again this doesn't make sense but is
+ * reality for some model formats (MD5 for example uses these special
+ * nodes as attachment tags for its weapons).
+ *
+ * Then it is possible that a bone has no weights anymore .... as a quick
+ * workaround, we're just removing these bones. If they're animated,
+ * model geometry might be modified but at least there's no risk of a crash.
+ */
+ delete bone;
+ --pMesh->mNumBones;
+ for (unsigned int n = a; n < pMesh->mNumBones; ++n) {
+ pMesh->mBones[n] = pMesh->mBones[n+1];
+ }
+
+ --a;
+ DefaultLogger::get()->warn("Removing bone -> no weights remaining");
+ }
+ }
+ return pMesh->mNumVertices;
}
#endif // !! ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
diff --git a/src/3rdparty/assimp/code/JoinVerticesProcess.h b/src/3rdparty/assimp/code/JoinVerticesProcess.h
index b54358171..af92040d2 100644
--- a/src/3rdparty/assimp/code/JoinVerticesProcess.h
+++ b/src/3rdparty/assimp/code/JoinVerticesProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,72 +23,72 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to join identical vertices
+/** @file Defines a post processing step to join identical vertices
on all imported meshes.*/
#ifndef AI_JOINVERTICESPROCESS_H_INC
#define AI_JOINVERTICESPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+
+struct aiMesh;
namespace Assimp
{
-class JoinVerticesTest;
-
// ---------------------------------------------------------------------------
-/** The JoinVerticesProcess unites identical vertices in all imported meshes.
- * By default the importer returns meshes where each face addressed its own
+/** The JoinVerticesProcess unites identical vertices in all imported meshes.
+ * By default the importer returns meshes where each face addressed its own
* set of vertices even if that means that identical vertices are stored multiple
- * times. The JoinVerticesProcess finds these identical vertices and
+ * times. The JoinVerticesProcess finds these identical vertices and
* erases all but one of the copies. This usually reduces the number of vertices
* in a mesh by a serious amount and is the standard form to render a mesh.
*/
-class ASSIMP_API_WINONLY JoinVerticesProcess : public BaseProcess
+class ASSIMP_API JoinVerticesProcess : public BaseProcess
{
public:
- JoinVerticesProcess();
- ~JoinVerticesProcess();
+ JoinVerticesProcess();
+ ~JoinVerticesProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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);
public:
- // -------------------------------------------------------------------
- /** Unites identical vertices in the given mesh.
- * @param pMesh The mesh to process.
- * @param meshIndex Index of the mesh to process
- */
- int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
+ // -------------------------------------------------------------------
+ /** Unites identical vertices in the given mesh.
+ * @param pMesh The mesh to process.
+ * @param meshIndex Index of the mesh to process
+ */
+ int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
private:
};
diff --git a/src/3rdparty/assimp/code/LWOAnimation.cpp b/src/3rdparty/assimp/code/LWOAnimation.cpp
index 68efa1735..9f23c13b2 100644
--- a/src/3rdparty/assimp/code/LWOAnimation.cpp
+++ b/src/3rdparty/assimp/code/LWOAnimation.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,30 +23,30 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file LWOAnimation.cpp
- * @brief LWOAnimationResolver utility class
+ * @brief LWOAnimationResolver utility class
*
* It's a very generic implementation of LightWave's system of
* componentwise-animated stuff. The one and only fully free
* implementation of LightWave envelopes of which I know.
*/
-#include "AssimpPCH.h"
+
#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER) && (!defined ASSIMP_BUILD_NO_LWS_IMPORTER)
#include <functional>
@@ -60,534 +60,543 @@ using namespace Assimp::LWO;
// ------------------------------------------------------------------------------------------------
// Construct an animation resolver from a given list of envelopes
AnimResolver::AnimResolver(std::list<Envelope>& _envelopes,double tick)
- : envelopes (_envelopes)
- , sample_rate (0.)
+ : envelopes (_envelopes)
+ , sample_rate (0.)
+ , envl_x(), envl_y(), envl_z()
+ , end_x(), end_y(), end_z()
+ , flags()
+ , sample_delta()
{
- trans_x = trans_y = trans_z = NULL;
- rotat_x = rotat_y = rotat_z = NULL;
- scale_x = scale_y = scale_z = NULL;
-
- first = last = 150392.;
-
- // find transformation envelopes
- for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
-
- (*it).old_first = 0;
- (*it).old_last = (*it).keys.size()-1;
-
- if ((*it).keys.empty()) continue;
- switch ((*it).type) {
-
- // translation
- case LWO::EnvelopeType_Position_X:
- trans_x = &*it;break;
- case LWO::EnvelopeType_Position_Y:
- trans_y = &*it;break;
- case LWO::EnvelopeType_Position_Z:
- trans_z = &*it;break;
-
- // rotation
- case LWO::EnvelopeType_Rotation_Heading:
- rotat_x = &*it;break;
- case LWO::EnvelopeType_Rotation_Pitch:
- rotat_y = &*it;break;
- case LWO::EnvelopeType_Rotation_Bank:
- rotat_z = &*it;break;
-
- // scaling
- case LWO::EnvelopeType_Scaling_X:
- scale_x = &*it;break;
- case LWO::EnvelopeType_Scaling_Y:
- scale_y = &*it;break;
- case LWO::EnvelopeType_Scaling_Z:
- scale_z = &*it;break;
- default:
- continue;
- };
-
- // convert from seconds to ticks
- for (std::vector<LWO::Key>::iterator d = (*it).keys.begin(); d != (*it).keys.end(); ++d)
- (*d).time *= tick;
-
- // set default animation range (minimum and maximum time value for which we have a keyframe)
- first = std::min(first, (*it).keys.front().time );
- last = std::max(last, (*it).keys.back().time );
- }
-
- // deferred setup of animation range to increase performance.
- // typically the application will want to specify its own.
- need_to_setup = true;
+ trans_x = trans_y = trans_z = NULL;
+ rotat_x = rotat_y = rotat_z = NULL;
+ scale_x = scale_y = scale_z = NULL;
+
+ first = last = 150392.;
+
+ // find transformation envelopes
+ for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
+
+ (*it).old_first = 0;
+ (*it).old_last = (*it).keys.size()-1;
+
+ if ((*it).keys.empty()) continue;
+ switch ((*it).type) {
+
+ // translation
+ case LWO::EnvelopeType_Position_X:
+ trans_x = &*it;break;
+ case LWO::EnvelopeType_Position_Y:
+ trans_y = &*it;break;
+ case LWO::EnvelopeType_Position_Z:
+ trans_z = &*it;break;
+
+ // rotation
+ case LWO::EnvelopeType_Rotation_Heading:
+ rotat_x = &*it;break;
+ case LWO::EnvelopeType_Rotation_Pitch:
+ rotat_y = &*it;break;
+ case LWO::EnvelopeType_Rotation_Bank:
+ rotat_z = &*it;break;
+
+ // scaling
+ case LWO::EnvelopeType_Scaling_X:
+ scale_x = &*it;break;
+ case LWO::EnvelopeType_Scaling_Y:
+ scale_y = &*it;break;
+ case LWO::EnvelopeType_Scaling_Z:
+ scale_z = &*it;break;
+ default:
+ continue;
+ };
+
+ // convert from seconds to ticks
+ for (std::vector<LWO::Key>::iterator d = (*it).keys.begin(); d != (*it).keys.end(); ++d)
+ (*d).time *= tick;
+
+ // set default animation range (minimum and maximum time value for which we have a keyframe)
+ first = std::min(first, (*it).keys.front().time );
+ last = std::max(last, (*it).keys.back().time );
+ }
+
+ // deferred setup of animation range to increase performance.
+ // typically the application will want to specify its own.
+ need_to_setup = true;
}
// ------------------------------------------------------------------------------------------------
// Reset all envelopes to their original contents
void AnimResolver::ClearAnimRangeSetup()
{
- for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
-
- (*it).keys.erase((*it).keys.begin(),(*it).keys.begin()+(*it).old_first);
- (*it).keys.erase((*it).keys.begin()+(*it).old_last+1,(*it).keys.end());
- }
+ for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
+
+ (*it).keys.erase((*it).keys.begin(),(*it).keys.begin()+(*it).old_first);
+ (*it).keys.erase((*it).keys.begin()+(*it).old_last+1,(*it).keys.end());
+ }
}
// ------------------------------------------------------------------------------------------------
// Insert additional keys to match LWO's pre& post behaviours.
void AnimResolver::UpdateAnimRangeSetup()
{
- // XXX doesn't work yet (hangs if more than one envelope channels needs to be interpolated)
-
- for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
- if ((*it).keys.empty()) continue;
-
- const double my_first = (*it).keys.front().time;
- const double my_last = (*it).keys.back().time;
-
- const double delta = my_last-my_first;
- const size_t old_size = (*it).keys.size();
-
- const float value_delta = (*it).keys.back().value - (*it).keys.front().value;
-
- // NOTE: We won't handle reset, linear and constant here.
- // See DoInterpolation() for their implementation.
-
- // process pre behaviour
- switch ((*it).pre) {
- case LWO::PrePostBehaviour_OffsetRepeat:
- case LWO::PrePostBehaviour_Repeat:
- case LWO::PrePostBehaviour_Oscillate:
- {
- const double start_time = delta - std::fmod(my_first-first,delta);
- std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(),
- std::bind1st(std::greater<double>(),start_time)),m;
-
- size_t ofs = 0;
- if (n != (*it).keys.end()) {
- // copy from here - don't use iterators, insert() would invalidate them
- ofs = (*it).keys.end()-n;
- (*it).keys.insert((*it).keys.begin(),ofs,LWO::Key());
-
- std::copy((*it).keys.end()-ofs,(*it).keys.end(),(*it).keys.begin());
- }
-
- // do full copies. again, no iterators
- const unsigned int num = (unsigned int)((my_first-first) / delta);
- (*it).keys.resize((*it).keys.size() + num*old_size);
-
- n = (*it).keys.begin()+ofs;
- bool reverse = false;
- for (unsigned int i = 0; i < num; ++i) {
- m = n+old_size*(i+1);
- std::copy(n,n+old_size,m);
-
- if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse))
- std::reverse(m,m+old_size-1);
- }
-
- // update time values
- n = (*it).keys.end() - (old_size+1);
- double cur_minus = delta;
- unsigned int tt = 1;
- for (const double tmp = delta*(num+1);cur_minus <= tmp;cur_minus += delta,++tt) {
- m = (delta == tmp ? (*it).keys.begin() : n - (old_size+1));
- for (;m != n; --n) {
- (*n).time -= cur_minus;
-
- // offset repeat? add delta offset to key value
- if ((*it).pre == LWO::PrePostBehaviour_OffsetRepeat) {
- (*n).value += tt * value_delta;
- }
- }
- }
- break;
- }
- default:
- // silence compiler warning
- break;
- }
-
- // process post behaviour
- switch ((*it).post) {
-
- case LWO::PrePostBehaviour_OffsetRepeat:
- case LWO::PrePostBehaviour_Repeat:
- case LWO::PrePostBehaviour_Oscillate:
-
- break;
-
- default:
- // silence compiler warning
- break;
- }
- }
+ // XXX doesn't work yet (hangs if more than one envelope channels needs to be interpolated)
+
+ for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) {
+ if ((*it).keys.empty()) continue;
+
+ const double my_first = (*it).keys.front().time;
+ const double my_last = (*it).keys.back().time;
+
+ const double delta = my_last-my_first;
+ const size_t old_size = (*it).keys.size();
+
+ const float value_delta = (*it).keys.back().value - (*it).keys.front().value;
+
+ // NOTE: We won't handle reset, linear and constant here.
+ // See DoInterpolation() for their implementation.
+
+ // process pre behaviour
+ switch ((*it).pre) {
+ case LWO::PrePostBehaviour_OffsetRepeat:
+ case LWO::PrePostBehaviour_Repeat:
+ case LWO::PrePostBehaviour_Oscillate:
+ {
+ const double start_time = delta - fmod(my_first-first,delta);
+ std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(),
+ std::bind1st(std::greater<double>(),start_time)),m;
+
+ size_t ofs = 0;
+ if (n != (*it).keys.end()) {
+ // copy from here - don't use iterators, insert() would invalidate them
+ ofs = (*it).keys.end()-n;
+ (*it).keys.insert((*it).keys.begin(),ofs,LWO::Key());
+
+ std::copy((*it).keys.end()-ofs,(*it).keys.end(),(*it).keys.begin());
+ }
+
+ // do full copies. again, no iterators
+ const unsigned int num = (unsigned int)((my_first-first) / delta);
+ (*it).keys.resize((*it).keys.size() + num*old_size);
+
+ n = (*it).keys.begin()+ofs;
+ bool reverse = false;
+ for (unsigned int i = 0; i < num; ++i) {
+ m = n+old_size*(i+1);
+ std::copy(n,n+old_size,m);
+
+ if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse))
+ std::reverse(m,m+old_size-1);
+ }
+
+ // update time values
+ n = (*it).keys.end() - (old_size+1);
+ double cur_minus = delta;
+ unsigned int tt = 1;
+ for (const double tmp = delta*(num+1);cur_minus <= tmp;cur_minus += delta,++tt) {
+ m = (delta == tmp ? (*it).keys.begin() : n - (old_size+1));
+ for (;m != n; --n) {
+ (*n).time -= cur_minus;
+
+ // offset repeat? add delta offset to key value
+ if ((*it).pre == LWO::PrePostBehaviour_OffsetRepeat) {
+ (*n).value += tt * value_delta;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ // silence compiler warning
+ break;
+ }
+
+ // process post behaviour
+ switch ((*it).post) {
+
+ case LWO::PrePostBehaviour_OffsetRepeat:
+ case LWO::PrePostBehaviour_Repeat:
+ case LWO::PrePostBehaviour_Oscillate:
+
+ break;
+
+ default:
+ // silence compiler warning
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Extract bind pose matrix
void AnimResolver::ExtractBindPose(aiMatrix4x4& out)
{
- // If we have no envelopes, return identity
- if (envelopes.empty()) {
- out = aiMatrix4x4();
- return;
- }
- aiVector3D angles, scaling(1.f,1.f,1.f), translation;
-
- if (trans_x) translation.x = trans_x->keys[0].value;
- if (trans_y) translation.y = trans_y->keys[0].value;
- if (trans_z) translation.z = trans_z->keys[0].value;
-
- if (rotat_x) angles.x = rotat_x->keys[0].value;
- if (rotat_y) angles.y = rotat_y->keys[0].value;
- if (rotat_z) angles.z = rotat_z->keys[0].value;
-
- if (scale_x) scaling.x = scale_x->keys[0].value;
- if (scale_y) scaling.y = scale_y->keys[0].value;
- if (scale_z) scaling.z = scale_z->keys[0].value;
-
- // build the final matrix
- aiMatrix4x4 s,rx,ry,rz,t;
- aiMatrix4x4::RotationZ(angles.z, rz);
- aiMatrix4x4::RotationX(angles.y, rx);
- aiMatrix4x4::RotationY(angles.x, ry);
- aiMatrix4x4::Translation(translation,t);
- aiMatrix4x4::Scaling(scaling,s);
- out = t*ry*rx*rz*s;
+ // If we have no envelopes, return identity
+ if (envelopes.empty()) {
+ out = aiMatrix4x4();
+ return;
+ }
+ aiVector3D angles, scaling(1.f,1.f,1.f), translation;
+
+ if (trans_x) translation.x = trans_x->keys[0].value;
+ if (trans_y) translation.y = trans_y->keys[0].value;
+ if (trans_z) translation.z = trans_z->keys[0].value;
+
+ if (rotat_x) angles.x = rotat_x->keys[0].value;
+ if (rotat_y) angles.y = rotat_y->keys[0].value;
+ if (rotat_z) angles.z = rotat_z->keys[0].value;
+
+ if (scale_x) scaling.x = scale_x->keys[0].value;
+ if (scale_y) scaling.y = scale_y->keys[0].value;
+ if (scale_z) scaling.z = scale_z->keys[0].value;
+
+ // build the final matrix
+ aiMatrix4x4 s,rx,ry,rz,t;
+ aiMatrix4x4::RotationZ(angles.z, rz);
+ aiMatrix4x4::RotationX(angles.y, rx);
+ aiMatrix4x4::RotationY(angles.x, ry);
+ aiMatrix4x4::Translation(translation,t);
+ aiMatrix4x4::Scaling(scaling,s);
+ out = t*ry*rx*rz*s;
}
// ------------------------------------------------------------------------------------------------
-// Do a single interpolation on a channel
-void AnimResolver::DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
- LWO::Envelope* envl,double time, float& fill)
+// Do a single interpolation on a channel
+void AnimResolver::DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
+ LWO::Envelope* envl,double time, float& fill)
{
- if (envl->keys.size() == 1) {
- fill = envl->keys[0].value;
- return;
- }
-
- // check whether we're at the beginning of the animation track
- if (cur == envl->keys.begin()) {
-
- // ok ... this depends on pre behaviour now
- // we don't need to handle repeat&offset repeat&oszillate here, see UpdateAnimRangeSetup()
- switch (envl->pre)
- {
- case LWO::PrePostBehaviour_Linear:
- DoInterpolation2(cur,cur+1,time,fill);
- return;
-
- case LWO::PrePostBehaviour_Reset:
- fill = 0.f;
- return;
-
- default : //case LWO::PrePostBehaviour_Constant:
- fill = (*cur).value;
- return;
- }
- }
- // check whether we're at the end of the animation track
- else if (cur == envl->keys.end()-1 && time > envl->keys.rbegin()->time) {
- // ok ... this depends on post behaviour now
- switch (envl->post)
- {
- case LWO::PrePostBehaviour_Linear:
- DoInterpolation2(cur,cur-1,time,fill);
- return;
-
- case LWO::PrePostBehaviour_Reset:
- fill = 0.f;
- return;
-
- default : //case LWO::PrePostBehaviour_Constant:
- fill = (*cur).value;
- return;
- }
- }
-
- // Otherwise do a simple interpolation
- DoInterpolation2(cur-1,cur,time,fill);
+ if (envl->keys.size() == 1) {
+ fill = envl->keys[0].value;
+ return;
+ }
+
+ // check whether we're at the beginning of the animation track
+ if (cur == envl->keys.begin()) {
+
+ // ok ... this depends on pre behaviour now
+ // we don't need to handle repeat&offset repeat&oszillate here, see UpdateAnimRangeSetup()
+ switch (envl->pre)
+ {
+ case LWO::PrePostBehaviour_Linear:
+ DoInterpolation2(cur,cur+1,time,fill);
+ return;
+
+ case LWO::PrePostBehaviour_Reset:
+ fill = 0.f;
+ return;
+
+ default : //case LWO::PrePostBehaviour_Constant:
+ fill = (*cur).value;
+ return;
+ }
+ }
+ // check whether we're at the end of the animation track
+ else if (cur == envl->keys.end()-1 && time > envl->keys.rbegin()->time) {
+ // ok ... this depends on post behaviour now
+ switch (envl->post)
+ {
+ case LWO::PrePostBehaviour_Linear:
+ DoInterpolation2(cur,cur-1,time,fill);
+ return;
+
+ case LWO::PrePostBehaviour_Reset:
+ fill = 0.f;
+ return;
+
+ default : //case LWO::PrePostBehaviour_Constant:
+ fill = (*cur).value;
+ return;
+ }
+ }
+
+ // Otherwise do a simple interpolation
+ DoInterpolation2(cur-1,cur,time,fill);
}
// ------------------------------------------------------------------------------------------------
// Almost the same, except we won't handle pre/post conditions here
-void AnimResolver::DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
- std::vector<LWO::Key>::const_iterator end,double time, float& fill)
+void AnimResolver::DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
+ std::vector<LWO::Key>::const_iterator end,double time, float& fill)
{
- switch ((*end).inter) {
-
- case LWO::IT_STEP:
- // no interpolation at all - take the value of the last key
- fill = (*beg).value;
- return;
- default:
-
- // silence compiler warning
- break;
- }
- // linear interpolation - default
- fill = (*beg).value + ((*end).value - (*beg).value)*(float)(((time - (*beg).time) / ((*end).time - (*beg).time)));
+ switch ((*end).inter) {
+
+ case LWO::IT_STEP:
+ // no interpolation at all - take the value of the last key
+ fill = (*beg).value;
+ return;
+ default:
+
+ // silence compiler warning
+ break;
+ }
+ // linear interpolation - default
+ double duration = (*end).time - (*beg).time;
+ if (duration > 0.0) {
+ fill = (*beg).value + ((*end).value - (*beg).value)*(float)(((time - (*beg).time) / duration));
+ } else {
+ fill = (*beg).value;
+ }
}
// ------------------------------------------------------------------------------------------------
// Subsample animation track by given key values
void AnimResolver::SubsampleAnimTrack(std::vector<aiVectorKey>& /*out*/,
- double /*time*/ ,double /*sample_delta*/ )
+ double /*time*/ ,double /*sample_delta*/ )
{
- //ai_assert(out.empty() && sample_delta);
+ //ai_assert(out.empty() && sample_delta);
- //const double time_start = out.back().mTime;
-// for ()
+ //const double time_start = out.back().mTime;
+// for ()
}
// ------------------------------------------------------------------------------------------------
// Track interpolation
void AnimResolver::InterpolateTrack(std::vector<aiVectorKey>& out,aiVectorKey& fill,double time)
{
- // subsample animation track?
- if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
- SubsampleAnimTrack(out,time, sample_delta);
- }
-
- fill.mTime = time;
-
- // get x
- if ((*cur_x).time == time) {
- fill.mValue.x = (*cur_x).value;
-
- if (cur_x != envl_x->keys.end()-1) /* increment x */
- ++cur_x;
- else end_x = true;
- }
- else DoInterpolation(cur_x,envl_x,time,(float&)fill.mValue.x);
-
- // get y
- if ((*cur_y).time == time) {
- fill.mValue.y = (*cur_y).value;
-
- if (cur_y != envl_y->keys.end()-1) /* increment y */
- ++cur_y;
- else end_y = true;
- }
- else DoInterpolation(cur_y,envl_y,time,(float&)fill.mValue.y);
-
- // get z
- if ((*cur_z).time == time) {
- fill.mValue.z = (*cur_z).value;
-
- if (cur_z != envl_z->keys.end()-1) /* increment z */
- ++cur_z;
- else end_x = true;
- }
- else DoInterpolation(cur_z,envl_z,time,(float&)fill.mValue.z);
+ // subsample animation track?
+ if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
+ SubsampleAnimTrack(out,time, sample_delta);
+ }
+
+ fill.mTime = time;
+
+ // get x
+ if ((*cur_x).time == time) {
+ fill.mValue.x = (*cur_x).value;
+
+ if (cur_x != envl_x->keys.end()-1) /* increment x */
+ ++cur_x;
+ else end_x = true;
+ }
+ else DoInterpolation(cur_x,envl_x,time,(float&)fill.mValue.x);
+
+ // get y
+ if ((*cur_y).time == time) {
+ fill.mValue.y = (*cur_y).value;
+
+ if (cur_y != envl_y->keys.end()-1) /* increment y */
+ ++cur_y;
+ else end_y = true;
+ }
+ else DoInterpolation(cur_y,envl_y,time,(float&)fill.mValue.y);
+
+ // get z
+ if ((*cur_z).time == time) {
+ fill.mValue.z = (*cur_z).value;
+
+ if (cur_z != envl_z->keys.end()-1) /* increment z */
+ ++cur_z;
+ else end_x = true;
+ }
+ else DoInterpolation(cur_z,envl_z,time,(float&)fill.mValue.z);
}
// ------------------------------------------------------------------------------------------------
// Build linearly subsampled keys from three single envelopes, one for each component (x,y,z)
-void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
- LWO::Envelope* _envl_x,
- LWO::Envelope* _envl_y,
- LWO::Envelope* _envl_z,
- unsigned int _flags)
+void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
+ LWO::Envelope* _envl_x,
+ LWO::Envelope* _envl_y,
+ LWO::Envelope* _envl_z,
+ unsigned int _flags)
{
- envl_x = _envl_x;
- envl_y = _envl_y;
- envl_z = _envl_z;
- flags = _flags;
-
- // generate default channels if none are given
- LWO::Envelope def_x, def_y, def_z;
- LWO::Key key_dummy;
- key_dummy.time = 0.f;
- if ((envl_x && envl_x->type == LWO::EnvelopeType_Scaling_X) ||
- (envl_y && envl_y->type == LWO::EnvelopeType_Scaling_Y) ||
- (envl_z && envl_z->type == LWO::EnvelopeType_Scaling_Z)) {
- key_dummy.value = 1.f;
- }
- else key_dummy.value = 0.f;
-
- if (!envl_x) {
- envl_x = &def_x;
- envl_x->keys.push_back(key_dummy);
- }
- if (!envl_y) {
- envl_y = &def_y;
- envl_y->keys.push_back(key_dummy);
- }
- if (!envl_z) {
- envl_z = &def_z;
- envl_z->keys.push_back(key_dummy);
- }
-
- // guess how many keys we'll get
- size_t reserve;
- double sr = 1.;
- if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
- if (!sample_rate)
- sr = 100.f;
- else sr = sample_rate;
- sample_delta = 1.f / sr;
-
- reserve = (size_t)(
- std::max( envl_x->keys.rbegin()->time,
- std::max( envl_y->keys.rbegin()->time, envl_z->keys.rbegin()->time )) * sr);
- }
- else reserve = std::max(envl_x->keys.size(),std::max(envl_x->keys.size(),envl_z->keys.size()));
- out.reserve(reserve+(reserve>>1));
-
- // Iterate through all three arrays at once - it's tricky, but
- // rather interesting to implement.
- double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time));
-
- cur_x = envl_x->keys.begin();
- cur_y = envl_y->keys.begin();
- cur_z = envl_z->keys.begin();
-
- end_x = end_y = end_z = false;
- while (1) {
-
- aiVectorKey fill;
-
- if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time ) {
-
- // we have a keyframe for all of them defined .. this means
- // we don't need to interpolate here.
- fill.mTime = (*cur_x).time;
-
- fill.mValue.x = (*cur_x).value;
- fill.mValue.y = (*cur_y).value;
- fill.mValue.z = (*cur_z).value;
-
- // subsample animation track
- if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
- //SubsampleAnimTrack(out,cur_x, cur_y, cur_z, d, sample_delta);
- }
- }
-
- // Find key with lowest time value
- else if ((*cur_x).time <= (*cur_y).time && !end_x) {
-
- if ((*cur_z).time <= (*cur_x).time && !end_z) {
- InterpolateTrack(out,fill,(*cur_z).time);
- }
- else {
- InterpolateTrack(out,fill,(*cur_x).time);
- }
- }
- else if ((*cur_z).time <= (*cur_y).time && !end_y) {
- InterpolateTrack(out,fill,(*cur_y).time);
- }
- else if (!end_y) {
- // welcome on the server, y
- InterpolateTrack(out,fill,(*cur_y).time);
- }
- else {
- // we have reached the end of at least 2 channels,
- // only one is remaining. Extrapolate the 2.
- if (end_y) {
- InterpolateTrack(out,fill,(end_x ? (*cur_z) : (*cur_x)).time);
- }
- else if (end_x) {
- InterpolateTrack(out,fill,(end_z ? (*cur_y) : (*cur_z)).time);
- }
- else { // if (end_z)
- InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time);
- }
- }
- lasttime = fill.mTime;
- out.push_back(fill);
-
- if (lasttime >= (*cur_x).time) {
- if (cur_x != envl_x->keys.end()-1)
- ++cur_x;
- else end_x = true;
- }
- if (lasttime >= (*cur_y).time) {
- if (cur_y != envl_y->keys.end()-1)
- ++cur_y;
- else end_y = true;
- }
- if (lasttime >= (*cur_z).time) {
- if (cur_z != envl_z->keys.end()-1)
- ++cur_z;
- else end_z = true;
- }
-
- if( end_x && end_y && end_z ) /* finished? */
- break;
- }
-
- if (flags & AI_LWO_ANIM_FLAG_START_AT_ZERO) {
- for (std::vector<aiVectorKey>::iterator it = out.begin(); it != out.end(); ++it)
- (*it).mTime -= first;
- }
+ envl_x = _envl_x;
+ envl_y = _envl_y;
+ envl_z = _envl_z;
+ flags = _flags;
+
+ // generate default channels if none are given
+ LWO::Envelope def_x, def_y, def_z;
+ LWO::Key key_dummy;
+ key_dummy.time = 0.f;
+ if ((envl_x && envl_x->type == LWO::EnvelopeType_Scaling_X) ||
+ (envl_y && envl_y->type == LWO::EnvelopeType_Scaling_Y) ||
+ (envl_z && envl_z->type == LWO::EnvelopeType_Scaling_Z)) {
+ key_dummy.value = 1.f;
+ }
+ else key_dummy.value = 0.f;
+
+ if (!envl_x) {
+ envl_x = &def_x;
+ envl_x->keys.push_back(key_dummy);
+ }
+ if (!envl_y) {
+ envl_y = &def_y;
+ envl_y->keys.push_back(key_dummy);
+ }
+ if (!envl_z) {
+ envl_z = &def_z;
+ envl_z->keys.push_back(key_dummy);
+ }
+
+ // guess how many keys we'll get
+ size_t reserve;
+ double sr = 1.;
+ if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
+ if (!sample_rate)
+ sr = 100.f;
+ else sr = sample_rate;
+ sample_delta = 1.f / sr;
+
+ reserve = (size_t)(
+ std::max( envl_x->keys.rbegin()->time,
+ std::max( envl_y->keys.rbegin()->time, envl_z->keys.rbegin()->time )) * sr);
+ }
+ else reserve = std::max(envl_x->keys.size(),std::max(envl_x->keys.size(),envl_z->keys.size()));
+ out.reserve(reserve+(reserve>>1));
+
+ // Iterate through all three arrays at once - it's tricky, but
+ // rather interesting to implement.
+ double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time));
+
+ cur_x = envl_x->keys.begin();
+ cur_y = envl_y->keys.begin();
+ cur_z = envl_z->keys.begin();
+
+ end_x = end_y = end_z = false;
+ while (1) {
+
+ aiVectorKey fill;
+
+ if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time ) {
+
+ // we have a keyframe for all of them defined .. this means
+ // we don't need to interpolate here.
+ fill.mTime = (*cur_x).time;
+
+ fill.mValue.x = (*cur_x).value;
+ fill.mValue.y = (*cur_y).value;
+ fill.mValue.z = (*cur_z).value;
+
+ // subsample animation track
+ if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) {
+ //SubsampleAnimTrack(out,cur_x, cur_y, cur_z, d, sample_delta);
+ }
+ }
+
+ // Find key with lowest time value
+ else if ((*cur_x).time <= (*cur_y).time && !end_x) {
+
+ if ((*cur_z).time <= (*cur_x).time && !end_z) {
+ InterpolateTrack(out,fill,(*cur_z).time);
+ }
+ else {
+ InterpolateTrack(out,fill,(*cur_x).time);
+ }
+ }
+ else if ((*cur_z).time <= (*cur_y).time && !end_y) {
+ InterpolateTrack(out,fill,(*cur_y).time);
+ }
+ else if (!end_y) {
+ // welcome on the server, y
+ InterpolateTrack(out,fill,(*cur_y).time);
+ }
+ else {
+ // we have reached the end of at least 2 channels,
+ // only one is remaining. Extrapolate the 2.
+ if (end_y) {
+ InterpolateTrack(out,fill,(end_x ? (*cur_z) : (*cur_x)).time);
+ }
+ else if (end_x) {
+ InterpolateTrack(out,fill,(end_z ? (*cur_y) : (*cur_z)).time);
+ }
+ else { // if (end_z)
+ InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time);
+ }
+ }
+ lasttime = fill.mTime;
+ out.push_back(fill);
+
+ if (lasttime >= (*cur_x).time) {
+ if (cur_x != envl_x->keys.end()-1)
+ ++cur_x;
+ else end_x = true;
+ }
+ if (lasttime >= (*cur_y).time) {
+ if (cur_y != envl_y->keys.end()-1)
+ ++cur_y;
+ else end_y = true;
+ }
+ if (lasttime >= (*cur_z).time) {
+ if (cur_z != envl_z->keys.end()-1)
+ ++cur_z;
+ else end_z = true;
+ }
+
+ if( end_x && end_y && end_z ) /* finished? */
+ break;
+ }
+
+ if (flags & AI_LWO_ANIM_FLAG_START_AT_ZERO) {
+ for (std::vector<aiVectorKey>::iterator it = out.begin(); it != out.end(); ++it)
+ (*it).mTime -= first;
+ }
}
// ------------------------------------------------------------------------------------------------
// Extract animation channel
void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0*/)
{
- *out = NULL;
-
-
- //FIXME: crashes if more than one component is animated at different timings, to be resolved.
-
- // If we have no envelopes, return NULL
- if (envelopes.empty()) {
- return;
- }
-
- // We won't spawn an animation channel if we don't have at least one envelope with more than one keyframe defined.
- const bool trans = ((trans_x && trans_x->keys.size() > 1) || (trans_y && trans_y->keys.size() > 1) || (trans_z && trans_z->keys.size() > 1));
- const bool rotat = ((rotat_x && rotat_x->keys.size() > 1) || (rotat_y && rotat_y->keys.size() > 1) || (rotat_z && rotat_z->keys.size() > 1));
- const bool scale = ((scale_x && scale_x->keys.size() > 1) || (scale_y && scale_y->keys.size() > 1) || (scale_z && scale_z->keys.size() > 1));
- if (!trans && !rotat && !scale)
- return;
-
- // Allocate the output animation
- aiNodeAnim* anim = *out = new aiNodeAnim();
-
- // Setup default animation setup if necessary
- if (need_to_setup) {
- UpdateAnimRangeSetup();
- need_to_setup = false;
- }
-
- // copy translation keys
- if (trans) {
- std::vector<aiVectorKey> keys;
- GetKeys(keys,trans_x,trans_y,trans_z,flags);
-
- anim->mPositionKeys = new aiVectorKey[ anim->mNumPositionKeys = keys.size() ];
- std::copy(keys.begin(),keys.end(),anim->mPositionKeys);
- }
-
- // copy rotation keys
- if (rotat) {
- std::vector<aiVectorKey> keys;
- GetKeys(keys,rotat_x,rotat_y,rotat_z,flags);
-
- anim->mRotationKeys = new aiQuatKey[ anim->mNumRotationKeys = keys.size() ];
-
- // convert heading, pitch, bank to quaternion
- // mValue.x=Heading=Rot(Y), mValue.y=Pitch=Rot(X), mValue.z=Bank=Rot(Z)
- // Lightwave's rotation order is ZXY
- aiVector3D X(1.0,0.0,0.0);
- aiVector3D Y(0.0,1.0,0.0);
- aiVector3D Z(0.0,0.0,1.0);
- for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
- aiQuatKey& qk = anim->mRotationKeys[i];
- qk.mTime = keys[i].mTime;
- qk.mValue = aiQuaternion(Y,keys[i].mValue.x)*aiQuaternion(X,keys[i].mValue.y)*aiQuaternion(Z,keys[i].mValue.z);
- }
- }
-
- // copy scaling keys
- if (scale) {
- std::vector<aiVectorKey> keys;
- GetKeys(keys,scale_x,scale_y,scale_z,flags);
-
- anim->mScalingKeys = new aiVectorKey[ anim->mNumScalingKeys = keys.size() ];
- std::copy(keys.begin(),keys.end(),anim->mScalingKeys);
- }
+ *out = NULL;
+
+
+ //FIXME: crashes if more than one component is animated at different timings, to be resolved.
+
+ // If we have no envelopes, return NULL
+ if (envelopes.empty()) {
+ return;
+ }
+
+ // We won't spawn an animation channel if we don't have at least one envelope with more than one keyframe defined.
+ const bool trans = ((trans_x && trans_x->keys.size() > 1) || (trans_y && trans_y->keys.size() > 1) || (trans_z && trans_z->keys.size() > 1));
+ const bool rotat = ((rotat_x && rotat_x->keys.size() > 1) || (rotat_y && rotat_y->keys.size() > 1) || (rotat_z && rotat_z->keys.size() > 1));
+ const bool scale = ((scale_x && scale_x->keys.size() > 1) || (scale_y && scale_y->keys.size() > 1) || (scale_z && scale_z->keys.size() > 1));
+ if (!trans && !rotat && !scale)
+ return;
+
+ // Allocate the output animation
+ aiNodeAnim* anim = *out = new aiNodeAnim();
+
+ // Setup default animation setup if necessary
+ if (need_to_setup) {
+ UpdateAnimRangeSetup();
+ need_to_setup = false;
+ }
+
+ // copy translation keys
+ if (trans) {
+ std::vector<aiVectorKey> keys;
+ GetKeys(keys,trans_x,trans_y,trans_z,flags);
+
+ anim->mPositionKeys = new aiVectorKey[ anim->mNumPositionKeys = keys.size() ];
+ std::copy(keys.begin(),keys.end(),anim->mPositionKeys);
+ }
+
+ // copy rotation keys
+ if (rotat) {
+ std::vector<aiVectorKey> keys;
+ GetKeys(keys,rotat_x,rotat_y,rotat_z,flags);
+
+ anim->mRotationKeys = new aiQuatKey[ anim->mNumRotationKeys = keys.size() ];
+
+ // convert heading, pitch, bank to quaternion
+ // mValue.x=Heading=Rot(Y), mValue.y=Pitch=Rot(X), mValue.z=Bank=Rot(Z)
+ // Lightwave's rotation order is ZXY
+ aiVector3D X(1.0,0.0,0.0);
+ aiVector3D Y(0.0,1.0,0.0);
+ aiVector3D Z(0.0,0.0,1.0);
+ for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
+ aiQuatKey& qk = anim->mRotationKeys[i];
+ qk.mTime = keys[i].mTime;
+ qk.mValue = aiQuaternion(Y,keys[i].mValue.x)*aiQuaternion(X,keys[i].mValue.y)*aiQuaternion(Z,keys[i].mValue.z);
+ }
+ }
+
+ // copy scaling keys
+ if (scale) {
+ std::vector<aiVectorKey> keys;
+ GetKeys(keys,scale_x,scale_y,scale_z,flags);
+
+ anim->mScalingKeys = new aiVectorKey[ anim->mNumScalingKeys = keys.size() ];
+ std::copy(keys.begin(),keys.end(),anim->mScalingKeys);
+ }
}
diff --git a/src/3rdparty/assimp/code/LWOAnimation.h b/src/3rdparty/assimp/code/LWOAnimation.h
index 6717aaa94..257abecdd 100644
--- a/src/3rdparty/assimp/code/LWOAnimation.h
+++ b/src/3rdparty/assimp/code/LWOAnimation.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,23 +23,23 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file LWOAnimation.h
- * @brief LWOAnimationResolver utility class
+ * @brief LWOAnimationResolver utility class
*
* This is for all lightwave-related file format, not only LWO.
* LWS isthe main purpose.
@@ -47,6 +47,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_LWO_ANIMATION_INCLUDED
#define AI_LWO_ANIMATION_INCLUDED
+#include <assimp/anim.h>
+#include <vector>
+#include <list>
+
+struct aiNodeAnim;
+
namespace Assimp {
namespace LWO {
@@ -55,28 +61,28 @@ namespace LWO {
*/
enum EnvelopeType
{
- EnvelopeType_Position_X = 0x1,
- EnvelopeType_Position_Y = 0x2,
- EnvelopeType_Position_Z = 0x3,
+ EnvelopeType_Position_X = 0x1,
+ EnvelopeType_Position_Y = 0x2,
+ EnvelopeType_Position_Z = 0x3,
- EnvelopeType_Rotation_Heading = 0x4,
- EnvelopeType_Rotation_Pitch = 0x5,
- EnvelopeType_Rotation_Bank = 0x6,
+ EnvelopeType_Rotation_Heading = 0x4,
+ EnvelopeType_Rotation_Pitch = 0x5,
+ EnvelopeType_Rotation_Bank = 0x6,
- EnvelopeType_Scaling_X = 0x7,
- EnvelopeType_Scaling_Y = 0x8,
- EnvelopeType_Scaling_Z = 0x9,
+ EnvelopeType_Scaling_X = 0x7,
+ EnvelopeType_Scaling_Y = 0x8,
+ EnvelopeType_Scaling_Z = 0x9,
- // -- currently not yet handled
- EnvelopeType_Color_R = 0xa,
- EnvelopeType_Color_G = 0xb,
- EnvelopeType_Color_B = 0xc,
+ // -- currently not yet handled
+ EnvelopeType_Color_R = 0xa,
+ EnvelopeType_Color_G = 0xb,
+ EnvelopeType_Color_B = 0xc,
- EnvelopeType_Falloff_X = 0xd,
- EnvelopeType_Falloff_Y = 0xe,
- EnvelopeType_Falloff_Z = 0xf,
+ EnvelopeType_Falloff_X = 0xd,
+ EnvelopeType_Falloff_Y = 0xe,
+ EnvelopeType_Falloff_Z = 0xf,
- EnvelopeType_Unknown
+ EnvelopeType_Unknown
};
// ---------------------------------------------------------------------------
@@ -84,7 +90,7 @@ enum EnvelopeType
*/
enum InterpolationType
{
- IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2
+ IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2
};
@@ -93,12 +99,12 @@ enum InterpolationType
*/
enum PrePostBehaviour
{
- PrePostBehaviour_Reset = 0x0,
- PrePostBehaviour_Constant = 0x1,
- PrePostBehaviour_Repeat = 0x2,
- PrePostBehaviour_Oscillate = 0x3,
- PrePostBehaviour_OffsetRepeat = 0x4,
- PrePostBehaviour_Linear = 0x5
+ PrePostBehaviour_Reset = 0x0,
+ PrePostBehaviour_Constant = 0x1,
+ PrePostBehaviour_Repeat = 0x2,
+ PrePostBehaviour_Oscillate = 0x3,
+ PrePostBehaviour_OffsetRepeat = 0x4,
+ PrePostBehaviour_Linear = 0x5
};
// ---------------------------------------------------------------------------
@@ -106,27 +112,30 @@ enum PrePostBehaviour
*/
struct Key
{
- Key()
- : inter (IT_LINE)
- {}
+ Key()
+ : time(),
+ value(),
+ inter (IT_LINE),
+ params()
+ {}
- //! Current time
- double time;
+ //! Current time
+ double time;
- //! Current value
- float value;
+ //! Current value
+ float value;
- //! How to interpolate this key with previous key?
- InterpolationType inter;
+ //! How to interpolate this key with previous key?
+ InterpolationType inter;
- //! Interpolation parameters
- float params[5];
+ //! Interpolation parameters
+ float params[5];
- // for std::find()
- operator double () {
- return time;
- }
+ // for std::find()
+ operator double () {
+ return time;
+ }
};
// ---------------------------------------------------------------------------
@@ -134,34 +143,35 @@ struct Key
*/
struct Envelope
{
- Envelope()
- : type (EnvelopeType_Unknown)
- , pre (PrePostBehaviour_Constant)
- , post (PrePostBehaviour_Constant)
-
- , old_first (0)
- , old_last (0)
- {}
+ Envelope()
+ : index()
+ , type (EnvelopeType_Unknown)
+ , pre (PrePostBehaviour_Constant)
+ , post (PrePostBehaviour_Constant)
+
+ , old_first (0)
+ , old_last (0)
+ {}
- //! Index of this envelope
- unsigned int index;
+ //! Index of this envelope
+ unsigned int index;
- //! Type of envelope
- EnvelopeType type;
+ //! Type of envelope
+ EnvelopeType type;
- //! Pre and post-behaviour
- PrePostBehaviour pre,post;
+ //! Pre and post-behaviour
+ PrePostBehaviour pre,post;
- //! Keyframes for this envelope
- std::vector<Key> keys;
+ //! Keyframes for this envelope
+ std::vector<Key> keys;
- // temporary data for AnimResolver
- size_t old_first,old_last;
+ // temporary data for AnimResolver
+ size_t old_first,old_last;
};
// ---------------------------------------------------------------------------
-//! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS
+//! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS
//! Flag for AnimResolver, subsamples the input data with the rate specified
//! by AnimResolver::SetSampleRate().
#define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1
@@ -181,153 +191,153 @@ class AnimResolver
{
public:
- // ------------------------------------------------------------------
- /** @brief Construct an AnimResolver from a given list of envelopes
- * @param envelopes Input envelopes. May be empty.
- * @param Output tick rate, per second
- * @note The input envelopes are possibly modified.
- */
- AnimResolver(std::list<Envelope>& envelopes,
- double tick);
+ // ------------------------------------------------------------------
+ /** @brief Construct an AnimResolver from a given list of envelopes
+ * @param envelopes Input envelopes. May be empty.
+ * @param Output tick rate, per second
+ * @note The input envelopes are possibly modified.
+ */
+ AnimResolver(std::list<Envelope>& envelopes,
+ double tick);
public:
- // ------------------------------------------------------------------
- /** @brief Extract the bind-pose transformation matrix.
- * @param out Receives bind-pose transformation matrix
- */
- void ExtractBindPose(aiMatrix4x4& out);
-
- // ------------------------------------------------------------------
- /** @brief Extract a node animation channel
- * @param out Receives a pointer to a newly allocated node anim.
- * If there's just one keyframe defined, *out is set to NULL and
- * no animation channel is computed.
- * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
- */
- void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0);
-
-
- // ------------------------------------------------------------------
- /** @brief Set the sampling rate for ExtractAnimChannel().
- *
- * Non-linear interpolations are subsampled with this rate (keys
- * per second). Closer sampling positions, if existent, are kept.
- * The sampling rate defaults to 0, if this value is not changed and
- * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(),
- * the class finds a suitable sample rate by itself.
- */
- void SetSampleRate(double sr) {
- sample_rate = sr;
- }
-
- // ------------------------------------------------------------------
- /** @brief Getter for SetSampleRate()
- */
- double GetSampleRate() const {
- return sample_rate;
- }
-
- // ------------------------------------------------------------------
- /** @brief Set the animation time range
- *
- * @param first Time where the animation starts, in ticks
- * @param last Time where the animation ends, in ticks
- */
- void SetAnimationRange(double _first, double _last) {
- first = _first;
- last = _last;
-
- ClearAnimRangeSetup();
- UpdateAnimRangeSetup();
- }
+ // ------------------------------------------------------------------
+ /** @brief Extract the bind-pose transformation matrix.
+ * @param out Receives bind-pose transformation matrix
+ */
+ void ExtractBindPose(aiMatrix4x4& out);
+
+ // ------------------------------------------------------------------
+ /** @brief Extract a node animation channel
+ * @param out Receives a pointer to a newly allocated node anim.
+ * If there's just one keyframe defined, *out is set to NULL and
+ * no animation channel is computed.
+ * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
+ */
+ void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0);
+
+
+ // ------------------------------------------------------------------
+ /** @brief Set the sampling rate for ExtractAnimChannel().
+ *
+ * Non-linear interpolations are subsampled with this rate (keys
+ * per second). Closer sampling positions, if existent, are kept.
+ * The sampling rate defaults to 0, if this value is not changed and
+ * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(),
+ * the class finds a suitable sample rate by itself.
+ */
+ void SetSampleRate(double sr) {
+ sample_rate = sr;
+ }
+
+ // ------------------------------------------------------------------
+ /** @brief Getter for SetSampleRate()
+ */
+ double GetSampleRate() const {
+ return sample_rate;
+ }
+
+ // ------------------------------------------------------------------
+ /** @brief Set the animation time range
+ *
+ * @param first Time where the animation starts, in ticks
+ * @param last Time where the animation ends, in ticks
+ */
+ void SetAnimationRange(double _first, double _last) {
+ first = _first;
+ last = _last;
+
+ ClearAnimRangeSetup();
+ UpdateAnimRangeSetup();
+ }
protected:
- // ------------------------------------------------------------------
- /** @brief Build linearly subsampled keys from 3 single envelopes
- * @param out Receives output keys
- * @param envl_x X-component envelope
- * @param envl_y Y-component envelope
- * @param envl_z Z-component envelope
- * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
- * @note Up to two input envelopes may be NULL
- */
- void GetKeys(std::vector<aiVectorKey>& out,
- LWO::Envelope* envl_x,
- LWO::Envelope* envl_y,
- LWO::Envelope* envl_z,
- unsigned int flags);
-
- // ------------------------------------------------------------------
- /** @brief Resolve a single animation key by applying the right
- * interpolation to it.
- * @param cur Current key
- * @param envl Envelope working on
- * @param time time to be interpolated
- * @param fill Receives the interpolated output value.
- */
- void DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
- LWO::Envelope* envl,double time, float& fill);
-
- // ------------------------------------------------------------------
- /** @brief Almost the same, except we won't handle pre/post
- * conditions here.
- * @see DoInterpolation
- */
- void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
- std::vector<LWO::Key>::const_iterator end,double time, float& fill);
-
- // ------------------------------------------------------------------
- /** @brief Interpolate 2 tracks if one is given
- *
- * @param out Receives extra output keys
- * @param key_out Primary output key
- * @param time Time to interpolate for
- */
- void InterpolateTrack(std::vector<aiVectorKey>& out,
- aiVectorKey& key_out,double time);
-
- // ------------------------------------------------------------------
- /** @brief Subsample an animation track by a given sampling rate
- *
- * @param out Receives output keys. Last key at input defines the
- * time where subsampling starts.
- * @param time Time to end subsampling at
- * @param sample_delta Time delta between two samples
- */
- void SubsampleAnimTrack(std::vector<aiVectorKey>& out,
- double time,double sample_delta);
-
- // ------------------------------------------------------------------
- /** @brief Delete all keys which we inserted to match anim setup
- */
- void ClearAnimRangeSetup();
-
- // ------------------------------------------------------------------
- /** @brief Insert extra keys to match LWO's pre and post behaviours
- * in a given time range [first...last]
- */
- void UpdateAnimRangeSetup();
+ // ------------------------------------------------------------------
+ /** @brief Build linearly subsampled keys from 3 single envelopes
+ * @param out Receives output keys
+ * @param envl_x X-component envelope
+ * @param envl_y Y-component envelope
+ * @param envl_z Z-component envelope
+ * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
+ * @note Up to two input envelopes may be NULL
+ */
+ void GetKeys(std::vector<aiVectorKey>& out,
+ LWO::Envelope* envl_x,
+ LWO::Envelope* envl_y,
+ LWO::Envelope* envl_z,
+ unsigned int flags);
+
+ // ------------------------------------------------------------------
+ /** @brief Resolve a single animation key by applying the right
+ * interpolation to it.
+ * @param cur Current key
+ * @param envl Envelope working on
+ * @param time time to be interpolated
+ * @param fill Receives the interpolated output value.
+ */
+ void DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
+ LWO::Envelope* envl,double time, float& fill);
+
+ // ------------------------------------------------------------------
+ /** @brief Almost the same, except we won't handle pre/post
+ * conditions here.
+ * @see DoInterpolation
+ */
+ void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
+ std::vector<LWO::Key>::const_iterator end,double time, float& fill);
+
+ // ------------------------------------------------------------------
+ /** @brief Interpolate 2 tracks if one is given
+ *
+ * @param out Receives extra output keys
+ * @param key_out Primary output key
+ * @param time Time to interpolate for
+ */
+ void InterpolateTrack(std::vector<aiVectorKey>& out,
+ aiVectorKey& key_out,double time);
+
+ // ------------------------------------------------------------------
+ /** @brief Subsample an animation track by a given sampling rate
+ *
+ * @param out Receives output keys. Last key at input defines the
+ * time where subsampling starts.
+ * @param time Time to end subsampling at
+ * @param sample_delta Time delta between two samples
+ */
+ void SubsampleAnimTrack(std::vector<aiVectorKey>& out,
+ double time,double sample_delta);
+
+ // ------------------------------------------------------------------
+ /** @brief Delete all keys which we inserted to match anim setup
+ */
+ void ClearAnimRangeSetup();
+
+ // ------------------------------------------------------------------
+ /** @brief Insert extra keys to match LWO's pre and post behaviours
+ * in a given time range [first...last]
+ */
+ void UpdateAnimRangeSetup();
private:
- std::list<Envelope>& envelopes;
- double sample_rate;
+ std::list<Envelope>& envelopes;
+ double sample_rate;
- LWO::Envelope* trans_x, *trans_y, *trans_z;
- LWO::Envelope* rotat_x, *rotat_y, *rotat_z;
- LWO::Envelope* scale_x, *scale_y, *scale_z;
+ LWO::Envelope* trans_x, *trans_y, *trans_z;
+ LWO::Envelope* rotat_x, *rotat_y, *rotat_z;
+ LWO::Envelope* scale_x, *scale_y, *scale_z;
- double first, last;
- bool need_to_setup;
+ double first, last;
+ bool need_to_setup;
- // temporary storage
- LWO::Envelope* envl_x, * envl_y, * envl_z;
- std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z;
- bool end_x, end_y, end_z;
+ // temporary storage
+ LWO::Envelope* envl_x, * envl_y, * envl_z;
+ std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z;
+ bool end_x, end_y, end_z;
- unsigned int flags;
- double sample_delta;
+ unsigned int flags;
+ double sample_delta;
};
} // end namespace LWO
diff --git a/src/3rdparty/assimp/code/LWOBLoader.cpp b/src/3rdparty/assimp/code/LWOBLoader.cpp
index 9776b8976..639675294 100644
--- a/src/3rdparty/assimp/code/LWOBLoader.cpp
+++ b/src/3rdparty/assimp/code/LWOBLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,24 +25,24 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file Implementation of the LWO importer class for the older LWOB
+/** @file Implementation of the LWO importer class for the older LWOB
file formats, including materials */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
// Internal headers
@@ -53,344 +53,370 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBFile()
{
- LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
- bool running = true;
- while (running)
- {
- if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
- LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- {
- throw DeadlyImportError("LWOB: Invalid chunk length");
- break;
- }
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- // vertex list
- case AI_LWO_PNTS:
- {
- if (!mCurLayer->mTempPoints.empty())
- DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
- else LoadLWOPoints(head->length);
- break;
- }
- // face list
- case AI_LWO_POLS:
- {
- if (!mCurLayer->mFaces.empty())
- DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
- else LoadLWOBPolygons(head->length);
- break;
- }
- // list of tags
- case AI_LWO_SRFS:
- {
- if (!mTags->empty())
- DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
- else LoadLWOTags(head->length);
- break;
- }
-
- // surface chunk
- case AI_LWO_SURF:
- {
- LoadLWOBSurface(head->length);
- break;
- }
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
+ bool running = true;
+ while (running)
+ {
+ if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
+ const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ {
+ throw DeadlyImportError("LWOB: Invalid chunk length");
+ break;
+ }
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ // vertex list
+ case AI_LWO_PNTS:
+ {
+ if (!mCurLayer->mTempPoints.empty())
+ DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
+ else LoadLWOPoints(head.length);
+ break;
+ }
+ // face list
+ case AI_LWO_POLS:
+ {
+
+ if (!mCurLayer->mFaces.empty())
+ DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
+ else LoadLWOBPolygons(head.length);
+ break;
+ }
+ // list of tags
+ case AI_LWO_SRFS:
+ {
+ if (!mTags->empty())
+ DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
+ else LoadLWOTags(head.length);
+ break;
+ }
+
+ // surface chunk
+ case AI_LWO_SURF:
+ {
+ LoadLWOBSurface(head.length);
+ break;
+ }
+ }
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBPolygons(unsigned int length)
{
- // first find out how many faces and vertices we'll finally need
- LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
- LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
+ // first find out how many faces and vertices we'll finally need
+ LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
+ LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
- // perform endianess conversions
+ // perform endianness conversions
#ifndef AI_BUILD_BIG_ENDIAN
- while (cursor < end)ByteSwap::Swap2(cursor++);
- cursor = (LE_NCONST uint16_t*)mFileBuffer;
+ while (cursor < end)ByteSwap::Swap2(cursor++);
+ cursor = (LE_NCONST uint16_t*)mFileBuffer;
#endif
- unsigned int iNumFaces = 0,iNumVertices = 0;
- CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
+ unsigned int iNumFaces = 0,iNumVertices = 0;
+ CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
- // allocate the output array and copy face indices
- if (iNumFaces)
- {
- cursor = (LE_NCONST uint16_t*)mFileBuffer;
+ // allocate the output array and copy face indices
+ if (iNumFaces)
+ {
+ cursor = (LE_NCONST uint16_t*)mFileBuffer;
- mCurLayer->mFaces.resize(iNumFaces);
- FaceList::iterator it = mCurLayer->mFaces.begin();
- CopyFaceIndicesLWOB(it,cursor,end);
- }
+ mCurLayer->mFaces.resize(iNumFaces);
+ FaceList::iterator it = mCurLayer->mFaces.begin();
+ CopyFaceIndicesLWOB(it,cursor,end);
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
- LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
+ LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
{
- while (cursor < end && max--)
- {
- uint16_t numIndices = *cursor++;
- verts += numIndices;faces++;
- cursor += numIndices;
- int16_t surface = *cursor++;
- if (surface < 0)
- {
- // there are detail polygons
- numIndices = *cursor++;
- CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
- }
- }
+ while (cursor < end && max--)
+ {
+ uint16_t numIndices;
+ // must have 2 shorts left for numIndices and surface
+ if (end - cursor < 2) {
+ throw DeadlyImportError("LWOB: Unexpected end of file");
+ }
+ ::memcpy(&numIndices, cursor++, 2);
+ // must have enough left for indices and surface
+ if (end - cursor < (1 + numIndices)) {
+ throw DeadlyImportError("LWOB: Unexpected end of file");
+ }
+ verts += numIndices;
+ faces++;
+ cursor += numIndices;
+ int16_t surface;
+ ::memcpy(&surface, cursor++, 2);
+ if (surface < 0)
+ {
+ // there are detail polygons
+ ::memcpy(&numIndices, cursor++, 2);
+ CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
- LE_NCONST uint16_t*& cursor,
- const uint16_t* const end,
- unsigned int max)
+ LE_NCONST uint16_t*& cursor,
+ const uint16_t* const end,
+ unsigned int max)
{
- while (cursor < end && max--)
- {
- LWO::Face& face = *it;++it;
- if((face.mNumIndices = *cursor++))
- {
- if (cursor + face.mNumIndices >= end)break;
- face.mIndices = new unsigned int[face.mNumIndices];
- for (unsigned int i = 0; i < face.mNumIndices;++i)
- {
- unsigned int & mi = face.mIndices[i] = *cursor++;
- if (mi > mCurLayer->mTempPoints.size())
- {
- DefaultLogger::get()->warn("LWOB: face index is out of range");
- mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
- }
- }
- }
- else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
- int16_t surface = *cursor++;
- if (surface < 0)
- {
- surface = -surface;
-
- // there are detail polygons.
- const uint16_t numPolygons = *cursor++;
- if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
- }
- face.surfaceIndex = surface-1;
- }
+ while (cursor < end && max--)
+ {
+ LWO::Face& face = *it;++it;
+ uint16_t numIndices;
+ ::memcpy(&numIndices, cursor++, 2);
+ face.mNumIndices = numIndices;
+ if(face.mNumIndices)
+ {
+ if (cursor + face.mNumIndices >= end)
+ {
+ break;
+ }
+ face.mIndices = new unsigned int[face.mNumIndices];
+ for (unsigned int i = 0; i < face.mNumIndices;++i)
+ {
+ unsigned int & mi = face.mIndices[i];
+ uint16_t index;
+ ::memcpy(&index, cursor++, 2);
+ mi = index;
+ if (mi > mCurLayer->mTempPoints.size())
+ {
+ DefaultLogger::get()->warn("LWOB: face index is out of range");
+ mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
+ }
+ }
+ }
+ else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
+ int16_t surface;
+ ::memcpy(&surface, cursor++, 2);
+ if (surface < 0)
+ {
+ surface = -surface;
+
+ // there are detail polygons.
+ uint16_t numPolygons;
+ ::memcpy(&numPolygons, cursor++, 2);
+ if (cursor < end)
+ {
+ CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
+ }
+ }
+ face.surfaceIndex = surface-1;
+ }
}
// ------------------------------------------------------------------------------------------------
LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size)
{
- list.push_back(LWO::Texture());
- LWO::Texture* tex = &list.back();
-
- std::string type;
- GetS0(type,size);
- const char* s = type.c_str();
-
- if(strstr(s, "Image Map"))
- {
- // Determine mapping type
- if(strstr(s, "Planar"))
- tex->mapMode = LWO::Texture::Planar;
- else if(strstr(s, "Cylindrical"))
- tex->mapMode = LWO::Texture::Cylindrical;
- else if(strstr(s, "Spherical"))
- tex->mapMode = LWO::Texture::Spherical;
- else if(strstr(s, "Cubic"))
- tex->mapMode = LWO::Texture::Cubic;
- else if(strstr(s, "Front"))
- tex->mapMode = LWO::Texture::FrontProjection;
- }
- else
- {
- // procedural or gradient, not supported
- DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type);
- }
-
- return tex;
+ list.push_back(LWO::Texture());
+ LWO::Texture* tex = &list.back();
+
+ std::string type;
+ GetS0(type,size);
+ const char* s = type.c_str();
+
+ if(strstr(s, "Image Map"))
+ {
+ // Determine mapping type
+ if(strstr(s, "Planar"))
+ tex->mapMode = LWO::Texture::Planar;
+ else if(strstr(s, "Cylindrical"))
+ tex->mapMode = LWO::Texture::Cylindrical;
+ else if(strstr(s, "Spherical"))
+ tex->mapMode = LWO::Texture::Spherical;
+ else if(strstr(s, "Cubic"))
+ tex->mapMode = LWO::Texture::Cubic;
+ else if(strstr(s, "Front"))
+ tex->mapMode = LWO::Texture::FrontProjection;
+ }
+ else
+ {
+ // procedural or gradient, not supported
+ DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type);
+ }
+
+ return tex;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBSurface(unsigned int size)
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- mSurfaces->push_back( LWO::Surface () );
- LWO::Surface& surf = mSurfaces->back();
- LWO::Texture* pTex = NULL;
-
- GetS0(surf.mName,size);
- bool runnning = true;
- while (runnning) {
- if (mFileBuffer + 6 >= end)
- break;
-
- IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- /* A single test file (sonycam.lwo) seems to have invalid surface chunks.
- * I'm assuming it's the fault of a single, unknown exporter so there are
- * probably THOUSANDS of them. Here's a dirty workaround:
- *
- * We don't break if the chunk limit is exceeded. Instead, we're computing
- * how much storage is actually left and work with this value from now on.
- */
- if (mFileBuffer + head->length > end) {
- DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
- head->length = (uint16_t) (end - mFileBuffer);
- }
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- // diffuse color
- case AI_LWO_COLR:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
- surf.mColor.r = GetU1() / 255.0f;
- surf.mColor.g = GetU1() / 255.0f;
- surf.mColor.b = GetU1() / 255.0f;
- break;
- }
- // diffuse strength ...
- case AI_LWO_DIFF:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
- surf.mDiffuseValue = GetU2() / 255.0f;
- break;
- }
- // specular strength ...
- case AI_LWO_SPEC:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
- surf.mSpecularValue = GetU2() / 255.0f;
- break;
- }
- // luminosity ...
- case AI_LWO_LUMI:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
- surf.mLuminosity = GetU2() / 255.0f;
- break;
- }
- // transparency
- case AI_LWO_TRAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
- surf.mTransparency = GetU2() / 255.0f;
- break;
- }
- // surface flags
- case AI_LWO_FLAG:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
- uint16_t flag = GetU2();
- if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
- if (flag & 0x8 ) surf.mColorHighlights = 1.f;
- if (flag & 0x100) surf.bDoubleSided = true;
- break;
- }
- // maximum smoothing angle
- case AI_LWO_SMAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
- surf.mMaximumSmoothAngle = std::fabs( GetF4() );
- break;
- }
- // glossiness
- case AI_LWO_GLOS:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
- surf.mGlossiness = (float)GetU2();
- break;
- }
- // color texture
- case AI_LWO_CTEX:
- {
- pTex = SetupNewTextureLWOB(surf.mColorTextures,
- head->length);
- break;
- }
- // diffuse texture
- case AI_LWO_DTEX:
- {
- pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
- head->length);
- break;
- }
- // specular texture
- case AI_LWO_STEX:
- {
- pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
- head->length);
- break;
- }
- // bump texture
- case AI_LWO_BTEX:
- {
- pTex = SetupNewTextureLWOB(surf.mBumpTextures,
- head->length);
- break;
- }
- // transparency texture
- case AI_LWO_TTEX:
- {
- pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
- head->length);
- break;
- }
- // texture path
- case AI_LWO_TIMG:
- {
- if (pTex) {
- GetS0(pTex->mFileName,head->length);
- }
- else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
- break;
- }
- // texture strength
- case AI_LWO_TVAL:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
- if (pTex) {
- pTex->mStrength = (float)GetU1()/ 255.f;
- }
- else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk");
- break;
- }
- // texture flags
- case AI_LWO_TFLG:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
-
- if (pTex)
- {
- const uint16_t s = GetU2();
- if (s & 1)
- pTex->majorAxis = LWO::Texture::AXIS_X;
- else if (s & 2)
- pTex->majorAxis = LWO::Texture::AXIS_Y;
- else if (s & 4)
- pTex->majorAxis = LWO::Texture::AXIS_Z;
-
- if (s & 16)
- DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture");
- }
- else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk");
- break;
- }
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ mSurfaces->push_back( LWO::Surface () );
+ LWO::Surface& surf = mSurfaces->back();
+ LWO::Texture* pTex = NULL;
+
+ GetS0(surf.mName,size);
+ bool running = true;
+ while (running) {
+ if (mFileBuffer + 6 >= end)
+ break;
+
+ IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ /* A single test file (sonycam.lwo) seems to have invalid surface chunks.
+ * I'm assuming it's the fault of a single, unknown exporter so there are
+ * probably THOUSANDS of them. Here's a dirty workaround:
+ *
+ * We don't break if the chunk limit is exceeded. Instead, we're computing
+ * how much storage is actually left and work with this value from now on.
+ */
+ if (mFileBuffer + head.length > end) {
+ DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
+ head.length = (uint16_t) (end - mFileBuffer);
+ }
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ // diffuse color
+ case AI_LWO_COLR:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
+ surf.mColor.r = GetU1() / 255.0f;
+ surf.mColor.g = GetU1() / 255.0f;
+ surf.mColor.b = GetU1() / 255.0f;
+ break;
+ }
+ // diffuse strength ...
+ case AI_LWO_DIFF:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
+ surf.mDiffuseValue = GetU2() / 255.0f;
+ break;
+ }
+ // specular strength ...
+ case AI_LWO_SPEC:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
+ surf.mSpecularValue = GetU2() / 255.0f;
+ break;
+ }
+ // luminosity ...
+ case AI_LWO_LUMI:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
+ surf.mLuminosity = GetU2() / 255.0f;
+ break;
+ }
+ // transparency
+ case AI_LWO_TRAN:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
+ surf.mTransparency = GetU2() / 255.0f;
+ break;
+ }
+ // surface flags
+ case AI_LWO_FLAG:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
+ uint16_t flag = GetU2();
+ if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
+ if (flag & 0x8 ) surf.mColorHighlights = 1.f;
+ if (flag & 0x100) surf.bDoubleSided = true;
+ break;
+ }
+ // maximum smoothing angle
+ case AI_LWO_SMAN:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
+ surf.mMaximumSmoothAngle = std::fabs( GetF4() );
+ break;
+ }
+ // glossiness
+ case AI_LWO_GLOS:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
+ surf.mGlossiness = (float)GetU2();
+ break;
+ }
+ // color texture
+ case AI_LWO_CTEX:
+ {
+ pTex = SetupNewTextureLWOB(surf.mColorTextures,
+ head.length);
+ break;
+ }
+ // diffuse texture
+ case AI_LWO_DTEX:
+ {
+ pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
+ head.length);
+ break;
+ }
+ // specular texture
+ case AI_LWO_STEX:
+ {
+ pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
+ head.length);
+ break;
+ }
+ // bump texture
+ case AI_LWO_BTEX:
+ {
+ pTex = SetupNewTextureLWOB(surf.mBumpTextures,
+ head.length);
+ break;
+ }
+ // transparency texture
+ case AI_LWO_TTEX:
+ {
+ pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
+ head.length);
+ break;
+ }
+ // texture path
+ case AI_LWO_TIMG:
+ {
+ if (pTex) {
+ GetS0(pTex->mFileName,head.length);
+ }
+ else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
+ break;
+ }
+ // texture strength
+ case AI_LWO_TVAL:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
+ if (pTex) {
+ pTex->mStrength = (float)GetU1()/ 255.f;
+ }
+ else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk");
+ break;
+ }
+ // texture flags
+ case AI_LWO_TFLG:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
+
+ if (pTex)
+ {
+ const uint16_t s = GetU2();
+ if (s & 1)
+ pTex->majorAxis = LWO::Texture::AXIS_X;
+ else if (s & 2)
+ pTex->majorAxis = LWO::Texture::AXIS_Y;
+ else if (s & 4)
+ pTex->majorAxis = LWO::Texture::AXIS_Z;
+
+ if (s & 16)
+ DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture");
+ }
+ else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk");
+ break;
+ }
+ }
+ mFileBuffer = next;
+ }
}
#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER
diff --git a/src/3rdparty/assimp/code/LWOFileData.h b/src/3rdparty/assimp/code/LWOFileData.h
index 88ca9c566..d67cf7ec8 100644
--- a/src/3rdparty/assimp/code/LWOFileData.h
+++ b/src/3rdparty/assimp/code/LWOFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Defines chunk constants used by the LWO file format
The chunks are taken from the official LightWave SDK headers.
-
+
*/
#ifndef AI_LWO_FILEDATA_INCLUDED
#define AI_LWO_FILEDATA_INCLUDED
@@ -52,7 +52,7 @@ The chunks are taken from the official LightWave SDK headers.
#include <list>
// public ASSIMP headers
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
// internal headers
#include "IFF.h"
@@ -257,47 +257,47 @@ namespace LWO {
/** \brief Data structure for a face in a LWO file
*
* \note We can't use the code in SmoothingGroups.inl here - the mesh
- * structures of 3DS/ASE and LWO are too different.
+ * structures of 3DS/ASE and LWO are too different.
*/
struct Face : public aiFace
{
- //! Default construction
- Face()
- : surfaceIndex (0)
- , smoothGroup (0)
- , type (AI_LWO_FACE)
- {}
-
- //! Construction from given type
- Face(uint32_t _type)
- : surfaceIndex (0)
- , smoothGroup (0)
- , type (_type)
- {}
-
- //! Copy construction
- Face(const Face& f) : aiFace() {
- *this = f;
- }
-
- //! Zero-based index into tags chunk
- unsigned int surfaceIndex;
-
- //! Smooth group this face is assigned to
- unsigned int smoothGroup;
-
- //! Type of face
- uint32_t type;
-
-
- //! Assignment operator
- Face& operator=(const LWO::Face& f) {
- aiFace::operator =(f);
- surfaceIndex = f.surfaceIndex;
- smoothGroup = f.smoothGroup;
- type = f.type;
- return *this;
- }
+ //! Default construction
+ Face()
+ : surfaceIndex (0)
+ , smoothGroup (0)
+ , type (AI_LWO_FACE)
+ {}
+
+ //! Construction from given type
+ explicit Face(uint32_t _type)
+ : surfaceIndex (0)
+ , smoothGroup (0)
+ , type (_type)
+ {}
+
+ //! Copy construction
+ Face(const Face& f) : aiFace() {
+ *this = f;
+ }
+
+ //! Zero-based index into tags chunk
+ unsigned int surfaceIndex;
+
+ //! Smooth group this face is assigned to
+ unsigned int smoothGroup;
+
+ //! Type of face
+ uint32_t type;
+
+
+ //! Assignment operator
+ Face& operator=(const LWO::Face& f) {
+ aiFace::operator =(f);
+ surfaceIndex = f.surfaceIndex;
+ smoothGroup = f.smoothGroup;
+ type = f.type;
+ return *this;
+ }
};
// ---------------------------------------------------------------------------
@@ -305,29 +305,29 @@ struct Face : public aiFace
*/
struct VMapEntry
{
- VMapEntry(unsigned int _dims)
- : dims(_dims)
- {}
+ explicit VMapEntry(unsigned int _dims)
+ : dims(_dims)
+ {}
- virtual ~VMapEntry() {}
+ virtual ~VMapEntry() {}
- //! allocates memory for the vertex map
- virtual void Allocate(unsigned int num)
- {
- if (!rawData.empty())
- return; // return if already allocated
+ //! allocates memory for the vertex map
+ virtual void Allocate(unsigned int num)
+ {
+ if (!rawData.empty())
+ return; // return if already allocated
- const unsigned int m = num*dims;
- rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
- rawData.resize(m,0.f);
- abAssigned.resize(num,false);
- }
+ const unsigned int m = num*dims;
+ rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
+ rawData.resize(m,0.f);
+ abAssigned.resize(num,false);
+ }
- std::string name;
- unsigned int dims;
+ std::string name;
+ unsigned int dims;
- std::vector<float> rawData;
- std::vector<bool> abAssigned;
+ std::vector<float> rawData;
+ std::vector<bool> abAssigned;
};
// ---------------------------------------------------------------------------
@@ -335,26 +335,26 @@ struct VMapEntry
*/
struct VColorChannel : public VMapEntry
{
- VColorChannel()
- : VMapEntry(4)
- {}
-
- //! need to overwrite this function - the alpha channel must
- //! be initialized to 1.0 by default
- virtual void Allocate(unsigned int num)
- {
- if (!rawData.empty())
- return; // return if already allocated
-
- unsigned int m = num*dims;
- rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
- rawData.resize(m);
-
- for (aiColor4D* p = (aiColor4D*)&rawData[0]; p < (aiColor4D*)&rawData[m-1]; ++p)
- p->a = 1.f;
-
- abAssigned.resize(num,false);
- }
+ VColorChannel()
+ : VMapEntry(4)
+ {}
+
+ //! need to overwrite this function - the alpha channel must
+ //! be initialized to 1.0 by default
+ virtual void Allocate(unsigned int num)
+ {
+ if (!rawData.empty())
+ return; // return if already allocated
+
+ unsigned int m = num*dims;
+ rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
+ rawData.resize(m);
+
+ for (aiColor4D* p = (aiColor4D*)&rawData[0]; p < (aiColor4D*)&rawData[m-1]; ++p)
+ p->a = 1.f;
+
+ abAssigned.resize(num,false);
+ }
};
// ---------------------------------------------------------------------------
@@ -362,19 +362,19 @@ struct VColorChannel : public VMapEntry
*/
struct UVChannel : public VMapEntry
{
- UVChannel()
- : VMapEntry(2)
- {}
+ UVChannel()
+ : VMapEntry(2)
+ {}
};
// ---------------------------------------------------------------------------
-/** \brief Represents a weight map
+/** \brief Represents a weight map
*/
struct WeightChannel : public VMapEntry
{
- WeightChannel()
- : VMapEntry(1)
- {}
+ WeightChannel()
+ : VMapEntry(1)
+ {}
};
// ---------------------------------------------------------------------------
@@ -382,9 +382,9 @@ struct WeightChannel : public VMapEntry
*/
struct NormalChannel : public VMapEntry
{
- NormalChannel()
- : VMapEntry(3)
- {}
+ NormalChannel()
+ : VMapEntry(3)
+ {}
};
// ---------------------------------------------------------------------------
@@ -392,99 +392,100 @@ struct NormalChannel : public VMapEntry
*/
struct Texture
{
- // we write the enum values out here to make debugging easier ...
- enum BlendType
- {
- Normal = 0,
- Subtractive = 1,
- Difference = 2,
- Multiply = 3,
- Divide = 4,
- Alpha = 5,
- TextureDispl = 6,
- Additive = 7
- };
-
- enum MappingMode
- {
- Planar = 0,
- Cylindrical = 1,
- Spherical = 2,
- Cubic = 3,
- FrontProjection = 4,
- UV = 5
- };
-
- enum Axes
- {
- AXIS_X = 0,
- AXIS_Y = 1,
- AXIS_Z = 2
- };
-
- enum Wrap
- {
- RESET = 0,
- REPEAT = 1,
- MIRROR = 2,
- EDGE = 3
- };
-
- Texture()
- : mClipIdx(UINT_MAX)
- , mStrength (1.0f)
- , mUVChannelIndex ("unknown")
- , mRealUVIndex (UINT_MAX)
- , enabled (true)
- , blendType (Additive)
- , bCanUse (true)
- , mapMode (UV)
- , majorAxis (AXIS_X)
- , wrapAmountH (1.0f)
- , wrapAmountW (1.0f)
- , wrapModeWidth (REPEAT)
- , wrapModeHeight (REPEAT)
- , ordinal ("\x00")
- {}
-
- //! File name of the texture
- std::string mFileName;
-
- //! Clip index
- unsigned int mClipIdx;
-
- //! Strength of the texture - blend factor
- float mStrength;
-
- uint32_t type; // type of the texture
-
- //! Name of the corresponding UV channel
- std::string mUVChannelIndex;
- unsigned int mRealUVIndex;
-
- //! is the texture enabled?
- bool enabled;
-
- //! blend type
- BlendType blendType;
-
- //! are we able to use the texture?
- bool bCanUse;
-
- //! mapping mode
- MappingMode mapMode;
-
- //! major axis for planar, cylindrical, spherical projections
- Axes majorAxis;
-
- //! wrap amount for cylindrical and spherical projections
- float wrapAmountH,wrapAmountW;
-
- //! wrapping mode for the texture
- Wrap wrapModeWidth,wrapModeHeight;
-
- //! ordinal string of the texture
- std::string ordinal;
+ // we write the enum values out here to make debugging easier ...
+ enum BlendType
+ {
+ Normal = 0,
+ Subtractive = 1,
+ Difference = 2,
+ Multiply = 3,
+ Divide = 4,
+ Alpha = 5,
+ TextureDispl = 6,
+ Additive = 7
+ };
+
+ enum MappingMode
+ {
+ Planar = 0,
+ Cylindrical = 1,
+ Spherical = 2,
+ Cubic = 3,
+ FrontProjection = 4,
+ UV = 5
+ };
+
+ enum Axes
+ {
+ AXIS_X = 0,
+ AXIS_Y = 1,
+ AXIS_Z = 2
+ };
+
+ enum Wrap
+ {
+ RESET = 0,
+ REPEAT = 1,
+ MIRROR = 2,
+ EDGE = 3
+ };
+
+ Texture()
+ : mClipIdx(UINT_MAX)
+ , mStrength (1.0f)
+ , type()
+ , mUVChannelIndex ("unknown")
+ , mRealUVIndex (UINT_MAX)
+ , enabled (true)
+ , blendType (Additive)
+ , bCanUse (true)
+ , mapMode (UV)
+ , majorAxis (AXIS_X)
+ , wrapAmountH (1.0f)
+ , wrapAmountW (1.0f)
+ , wrapModeWidth (REPEAT)
+ , wrapModeHeight (REPEAT)
+ , ordinal ("\x00")
+ {}
+
+ //! File name of the texture
+ std::string mFileName;
+
+ //! Clip index
+ unsigned int mClipIdx;
+
+ //! Strength of the texture - blend factor
+ float mStrength;
+
+ uint32_t type; // type of the texture
+
+ //! Name of the corresponding UV channel
+ std::string mUVChannelIndex;
+ unsigned int mRealUVIndex;
+
+ //! is the texture enabled?
+ bool enabled;
+
+ //! blend type
+ BlendType blendType;
+
+ //! are we able to use the texture?
+ bool bCanUse;
+
+ //! mapping mode
+ MappingMode mapMode;
+
+ //! major axis for planar, cylindrical, spherical projections
+ Axes majorAxis;
+
+ //! wrap amount for cylindrical and spherical projections
+ float wrapAmountH,wrapAmountW;
+
+ //! wrapping mode for the texture
+ Wrap wrapModeWidth,wrapModeHeight;
+
+ //! ordinal string of the texture
+ std::string ordinal;
};
// ---------------------------------------------------------------------------
@@ -492,28 +493,29 @@ struct Texture
*/
struct Clip
{
- enum Type
- {
- STILL, SEQ, REF, UNSUPPORTED
- } type;
+ enum Type
+ {
+ STILL, SEQ, REF, UNSUPPORTED
+ } type;
- Clip()
- : type (UNSUPPORTED)
- , idx (0)
- , negate (false)
- {}
+ Clip()
+ : type (UNSUPPORTED)
+ , clipRef()
+ , idx (0)
+ , negate (false)
+ {}
- //! path to the base texture -
- std::string path;
+ //! path to the base texture -
+ std::string path;
- //! reference to another CLIP
- unsigned int clipRef;
+ //! reference to another CLIP
+ unsigned int clipRef;
- //! index of the clip
- unsigned int idx;
+ //! index of the clip
+ unsigned int idx;
- //! Negate the clip?
- bool negate;
+ //! Negate the clip?
+ bool negate;
};
@@ -524,108 +526,108 @@ struct Clip
*/
struct Shader
{
- Shader()
- : ordinal ("\x00")
- , functionName ("unknown")
- , enabled (true)
- {}
-
- std::string ordinal;
- std::string functionName;
- bool enabled;
+ Shader()
+ : ordinal ("\x00")
+ , functionName ("unknown")
+ , enabled (true)
+ {}
+
+ std::string ordinal;
+ std::string functionName;
+ bool enabled;
};
-typedef std::list < Texture > TextureList;
-typedef std::list < Shader > ShaderList;
+typedef std::list < Texture > TextureList;
+typedef std::list < Shader > ShaderList;
// ---------------------------------------------------------------------------
/** \brief Data structure for a LWO file surface (= material)
*/
struct Surface
{
- Surface()
- : mColor (0.78431f,0.78431f,0.78431f)
- , bDoubleSided (false)
- , mDiffuseValue (1.f)
- , mSpecularValue (0.f)
- , mTransparency (0.f)
- , mGlossiness (0.4f)
- , mLuminosity (0.f)
- , mColorHighlights (0.f)
- , mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing
- , mVCMap ("")
- , mVCMapType (AI_LWO_RGBA)
- , mIOR (1.f) // vakuum
- , mBumpIntensity (1.f)
- , mWireframe (false)
- , mAdditiveTransparency (0.f)
- {}
-
- //! Name of the surface
- std::string mName;
-
- //! Color of the surface
- aiColor3D mColor;
-
- //! true for two-sided materials
- bool bDoubleSided;
-
- //! Various material parameters
- float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness,mLuminosity,mColorHighlights;
-
- //! Maximum angle between two adjacent triangles
- //! that they can be smoothed - in degrees
- float mMaximumSmoothAngle;
-
- //! Vertex color map to be used to color the surface
- std::string mVCMap;
- uint32_t mVCMapType;
-
- //! Names of the special shaders to be applied to the surface
- ShaderList mShaders;
-
- //! Textures - the first entry in the list is evaluated first
- TextureList mColorTextures, // color textures are added to both diffuse and specular texture stacks
- mDiffuseTextures,
- mSpecularTextures,
- mOpacityTextures,
- mBumpTextures,
- mGlossinessTextures,
- mReflectionTextures;
-
- //! Index of refraction
- float mIOR;
-
- //! Bump intensity scaling
- float mBumpIntensity;
-
- //! Wireframe flag
- bool mWireframe;
-
- //! Intensity of additive blending
- float mAdditiveTransparency;
+ Surface()
+ : mColor (0.78431f,0.78431f,0.78431f)
+ , bDoubleSided (false)
+ , mDiffuseValue (1.f)
+ , mSpecularValue (0.f)
+ , mTransparency (0.f)
+ , mGlossiness (0.4f)
+ , mLuminosity (0.f)
+ , mColorHighlights (0.f)
+ , mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing
+ , mVCMap ("")
+ , mVCMapType (AI_LWO_RGBA)
+ , mIOR (1.f) // vakuum
+ , mBumpIntensity (1.f)
+ , mWireframe (false)
+ , mAdditiveTransparency (0.f)
+ {}
+
+ //! Name of the surface
+ std::string mName;
+
+ //! Color of the surface
+ aiColor3D mColor;
+
+ //! true for two-sided materials
+ bool bDoubleSided;
+
+ //! Various material parameters
+ float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness,mLuminosity,mColorHighlights;
+
+ //! Maximum angle between two adjacent triangles
+ //! that they can be smoothed - in degrees
+ float mMaximumSmoothAngle;
+
+ //! Vertex color map to be used to color the surface
+ std::string mVCMap;
+ uint32_t mVCMapType;
+
+ //! Names of the special shaders to be applied to the surface
+ ShaderList mShaders;
+
+ //! Textures - the first entry in the list is evaluated first
+ TextureList mColorTextures, // color textures are added to both diffuse and specular texture stacks
+ mDiffuseTextures,
+ mSpecularTextures,
+ mOpacityTextures,
+ mBumpTextures,
+ mGlossinessTextures,
+ mReflectionTextures;
+
+ //! Index of refraction
+ float mIOR;
+
+ //! Bump intensity scaling
+ float mBumpIntensity;
+
+ //! Wireframe flag
+ bool mWireframe;
+
+ //! Intensity of additive blending
+ float mAdditiveTransparency;
};
// ---------------------------------------------------------------------------
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length,name,size) \
- if (length < size) \
- { \
- throw DeadlyImportError("LWO: "#name" chunk is too small"); \
- } \
+ if (length < size) \
+ { \
+ throw DeadlyImportError("LWO: "#name" chunk is too small"); \
+ } \
// some typedefs ... to make life with loader monsters like this easier
-typedef std::vector < aiVector3D > PointList;
-typedef std::vector < LWO::Face > FaceList;
-typedef std::vector < LWO::Surface > SurfaceList;
-typedef std::vector < std::string > TagList;
-typedef std::vector < unsigned int > TagMappingTable;
-typedef std::vector < unsigned int > ReferrerList;
-typedef std::vector < WeightChannel > WeightChannelList;
-typedef std::vector < VColorChannel > VColorChannelList;
-typedef std::vector < UVChannel > UVChannelList;
-typedef std::vector < Clip > ClipList;
-typedef std::vector < Envelope > EnvelopeList;
+typedef std::vector < aiVector3D > PointList;
+typedef std::vector < LWO::Face > FaceList;
+typedef std::vector < LWO::Surface > SurfaceList;
+typedef std::vector < std::string > TagList;
+typedef std::vector < unsigned int > TagMappingTable;
+typedef std::vector < unsigned int > ReferrerList;
+typedef std::vector < WeightChannel > WeightChannelList;
+typedef std::vector < VColorChannel > VColorChannelList;
+typedef std::vector < UVChannel > UVChannelList;
+typedef std::vector < Clip > ClipList;
+typedef std::vector < Envelope > EnvelopeList;
typedef std::vector < unsigned int > SortedRep;
// ---------------------------------------------------------------------------
@@ -633,63 +635,63 @@ typedef std::vector < unsigned int > SortedRep;
*/
struct Layer
{
- Layer()
- : mFaceIDXOfs (0)
- , mPointIDXOfs (0)
- , mParent (0x0)
- , mIndex (0xffff)
- , skip (false)
- {}
+ Layer()
+ : mFaceIDXOfs (0)
+ , mPointIDXOfs (0)
+ , mParent (0x0)
+ , mIndex (0xffff)
+ , skip (false)
+ {}
- /** Temporary point list from the file */
- PointList mTempPoints;
+ /** Temporary point list from the file */
+ PointList mTempPoints;
- /** Lists for every point the index of another point
- that has been copied from *this* point or UINT_MAX if
- no copy of the point has been made */
- ReferrerList mPointReferrers;
+ /** Lists for every point the index of another point
+ that has been copied from *this* point or UINT_MAX if
+ no copy of the point has been made */
+ ReferrerList mPointReferrers;
- /** Weight channel list from the file */
- WeightChannelList mWeightChannels;
+ /** Weight channel list from the file */
+ WeightChannelList mWeightChannels;
- /** Subdivision weight channel list from the file */
- WeightChannelList mSWeightChannels;
+ /** Subdivision weight channel list from the file */
+ WeightChannelList mSWeightChannels;
- /** Vertex color list from the file */
- VColorChannelList mVColorChannels;
+ /** Vertex color list from the file */
+ VColorChannelList mVColorChannels;
- /** UV channel list from the file */
- UVChannelList mUVChannels;
+ /** UV channel list from the file */
+ UVChannelList mUVChannels;
- /** Normal vector channel from the file */
- NormalChannel mNormals;
+ /** Normal vector channel from the file */
+ NormalChannel mNormals;
- /** Temporary face list from the file*/
- FaceList mFaces;
+ /** Temporary face list from the file*/
+ FaceList mFaces;
- /** Current face indexing offset from the beginning of the buffers*/
- unsigned int mFaceIDXOfs;
+ /** Current face indexing offset from the beginning of the buffers*/
+ unsigned int mFaceIDXOfs;
- /** Current point indexing offset from the beginning of the buffers*/
- unsigned int mPointIDXOfs;
+ /** Current point indexing offset from the beginning of the buffers*/
+ unsigned int mPointIDXOfs;
- /** Parent index */
- uint16_t mParent;
+ /** Parent index */
+ uint16_t mParent;
- /** Index of the layer */
- uint16_t mIndex;
+ /** Index of the layer */
+ uint16_t mIndex;
- /** Name of the layer */
- std::string mName;
+ /** Name of the layer */
+ std::string mName;
- /** Pivot point of the layer */
- aiVector3D mPivot;
+ /** Pivot point of the layer */
+ aiVector3D mPivot;
- /** Skip this layer? */
- bool skip;
+ /** Skip this layer? */
+ bool skip;
};
-typedef std::list<LWO::Layer> LayerList;
+typedef std::list<LWO::Layer> LayerList;
}}
diff --git a/src/3rdparty/assimp/code/LWOLoader.cpp b/src/3rdparty/assimp/code/LWOLoader.cpp
index b23a9fe6e..222ec8e2c 100644
--- a/src/3rdparty/assimp/code/LWOLoader.cpp
+++ b/src/3rdparty/assimp/code/LWOLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,1399 +43,1436 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the LWO importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
// internal headers
#include "LWOLoader.h"
#include "StringComparison.h"
#include "SGSpatialSort.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
#include "ProcessHelper.h"
#include "ConvertToLHProcess.h"
+#include <assimp/IOSystem.hpp>
+#include <memory>
+#include <sstream>
+#include <iomanip>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "LightWave/Modo Object Importer",
- "",
- "",
- "http://www.newtek.com/lightwave.html\nhttp://www.luxology.com/modo/",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "lwo lxo"
+ "LightWave/Modo Object Importer",
+ "",
+ "",
+ "http://www.newtek.com/lightwave.html\nhttp://www.luxology.com/modo/",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "lwo lxo"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
LWOImporter::LWOImporter()
+ : mIsLWO2(),
+ mIsLXOB(),
+ mLayers(),
+ mCurLayer(),
+ mTags(),
+ mMapping(),
+ mSurfaces(),
+ mFileBuffer(),
+ fileSize(),
+ pScene(),
+ configSpeedFlag(),
+ configLayerIndex(),
+ hasNamedLayer()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
LWOImporter::~LWOImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "lwo" || extension == "lxo") {
- return true;
- }
-
- // if check for extension is not enough, check for the magic tokens
- if (!extension.length() || checkSig) {
- uint32_t tokens[3];
- tokens[0] = AI_LWO_FOURCC_LWOB;
- tokens[1] = AI_LWO_FOURCC_LWO2;
- tokens[2] = AI_LWO_FOURCC_LXOB;
- return CheckMagicToken(pIOHandler,pFile,tokens,3,8);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "lwo" || extension == "lxo") {
+ return true;
+ }
+
+ // if check for extension is not enough, check for the magic tokens
+ if (!extension.length() || checkSig) {
+ uint32_t tokens[3];
+ tokens[0] = AI_LWO_FOURCC_LWOB;
+ tokens[1] = AI_LWO_FOURCC_LWO2;
+ tokens[2] = AI_LWO_FOURCC_LXOB;
+ return CheckMagicToken(pIOHandler,pFile,tokens,3,8);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void LWOImporter::SetupProperties(const Importer* pImp)
{
- configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false);
- configLayerIndex = pImp->GetPropertyInteger (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,UINT_MAX);
- configLayerName = pImp->GetPropertyString (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,"");
+ configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false);
+ configLayerIndex = pImp->GetPropertyInteger (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,UINT_MAX);
+ configLayerName = pImp->GetPropertyString (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,"");
}
// ------------------------------------------------------------------------------------------------
// Get list of file extensions
const aiImporterDesc* LWOImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void LWOImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene,
- IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void LWOImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene,
+ IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open LWO file " + pFile + ".");
-
- if((this->fileSize = (unsigned int)file->FileSize()) < 12)
- throw DeadlyImportError("LWO: The file is too small to contain the IFF header");
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector< uint8_t > mBuffer(fileSize);
- file->Read( &mBuffer[0], 1, fileSize);
- this->pScene = pScene;
-
- // Determine the type of the file
- uint32_t fileType;
- const char* sz = IFF::ReadHeader(&mBuffer[0],fileType);
- if (sz)throw DeadlyImportError(sz);
-
- mFileBuffer = &mBuffer[0] + 12;
- fileSize -= 12;
-
- // Initialize some members with their default values
- hasNamedLayer = false;
-
- // Create temporary storage on the stack but store pointers to it in the class
- // instance. Therefore everything will be destructed properly if an exception
- // is thrown and we needn't take care of that.
- LayerList _mLayers;
- SurfaceList _mSurfaces;
- TagList _mTags;
- TagMappingTable _mMapping;
-
- mLayers = &_mLayers;
- mTags = &_mTags;
- mMapping = &_mMapping;
- mSurfaces = &_mSurfaces;
-
- // Allocate a default layer (layer indices are 1-based from now)
- mLayers->push_back(Layer());
- mCurLayer = &mLayers->back();
- mCurLayer->mName = "<LWODefault>";
- mCurLayer->mIndex = -1;
-
- // old lightwave file format (prior to v6)
- if (AI_LWO_FOURCC_LWOB == fileType) {
- DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)");
-
- mIsLWO2 = false;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open LWO file " + pFile + ".");
+
+ if((this->fileSize = (unsigned int)file->FileSize()) < 12)
+ throw DeadlyImportError("LWO: The file is too small to contain the IFF header");
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector< uint8_t > mBuffer(fileSize);
+ file->Read( &mBuffer[0], 1, fileSize);
+ this->pScene = pScene;
+
+ // Determine the type of the file
+ uint32_t fileType;
+ const char* sz = IFF::ReadHeader(&mBuffer[0],fileType);
+ if (sz)throw DeadlyImportError(sz);
+
+ mFileBuffer = &mBuffer[0] + 12;
+ fileSize -= 12;
+
+ // Initialize some members with their default values
+ hasNamedLayer = false;
+
+ // Create temporary storage on the stack but store pointers to it in the class
+ // instance. Therefore everything will be destructed properly if an exception
+ // is thrown and we needn't take care of that.
+ LayerList _mLayers;
+ SurfaceList _mSurfaces;
+ TagList _mTags;
+ TagMappingTable _mMapping;
+
+ mLayers = &_mLayers;
+ mTags = &_mTags;
+ mMapping = &_mMapping;
+ mSurfaces = &_mSurfaces;
+
+ // Allocate a default layer (layer indices are 1-based from now)
+ mLayers->push_back(Layer());
+ mCurLayer = &mLayers->back();
+ mCurLayer->mName = "<LWODefault>";
+ mCurLayer->mIndex = -1;
+
+ // old lightwave file format (prior to v6)
+ if (AI_LWO_FOURCC_LWOB == fileType) {
+ DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)");
+
+ mIsLWO2 = false;
mIsLXOB = false;
- LoadLWOBFile();
- }
- // New lightwave format
- else if (AI_LWO_FOURCC_LWO2 == fileType) {
+ LoadLWOBFile();
+ }
+ // New lightwave format
+ else if (AI_LWO_FOURCC_LWO2 == fileType) {
mIsLXOB = false;
- DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)");
- }
- // MODO file format
- else if (AI_LWO_FOURCC_LXOB == fileType) {
+ DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)");
+ }
+ // MODO file format
+ else if (AI_LWO_FOURCC_LXOB == fileType) {
mIsLXOB = true;
- DefaultLogger::get()->info("LWO file format: LXOB (Modo)");
- }
- // we don't know this format
- else
- {
- char szBuff[5];
- szBuff[0] = (char)(fileType >> 24u);
- szBuff[1] = (char)(fileType >> 16u);
- szBuff[2] = (char)(fileType >> 8u);
- szBuff[3] = (char)(fileType);
- szBuff[4] = '\0';
- throw DeadlyImportError(std::string("Unknown LWO sub format: ") + szBuff);
- }
-
- if (AI_LWO_FOURCC_LWOB != fileType) {
- mIsLWO2 = true;
- LoadLWO2File();
-
- // The newer lightwave format allows the user to configure the
- // loader that just one layer is used. If this is the case
- // we need to check now whether the requested layer has been found.
- if (UINT_MAX != configLayerIndex) {
- unsigned int layerCount = 0;
- for(std::list<LWO::Layer>::iterator itLayers=mLayers->begin(); itLayers!=mLayers->end(); itLayers++)
- if (!itLayers->skip)
- layerCount++;
- if (layerCount!=2)
- throw DeadlyImportError("LWO2: The requested layer was not found");
- }
-
- if (configLayerName.length() && !hasNamedLayer) {
- throw DeadlyImportError("LWO2: Unable to find the requested layer: "
- + configLayerName);
- }
- }
-
- // now, as we have loaded all data, we can resolve cross-referenced tags and clips
- ResolveTags();
- ResolveClips();
-
- // now process all layers and build meshes and nodes
- std::vector<aiMesh*> apcMeshes;
- std::map<uint16_t, aiNode*> apcNodes;
-
- apcMeshes.reserve(mLayers->size()*std::min(((unsigned int)mSurfaces->size()/2u), 1u));
-
- unsigned int iDefaultSurface = UINT_MAX; // index of the default surface
- for (LayerList::iterator lit = mLayers->begin(), lend = mLayers->end();lit != lend;++lit) {
- LWO::Layer& layer = *lit;
- if (layer.skip)
- continue;
-
- // I don't know whether there could be dummy layers, but it would be possible
- const unsigned int meshStart = (unsigned int)apcMeshes.size();
- if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) {
-
- // now sort all faces by the surfaces assigned to them
- std::vector<SortedRep> pSorted(mSurfaces->size()+1);
-
- unsigned int i = 0;
- for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();it != end;++it,++i) {
- // Check whether we support this face's type
- if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH &&
- (*it).type != AI_LWO_BONE && (*it).type != AI_LWO_SUBD) {
- continue;
- }
-
- unsigned int idx = (*it).surfaceIndex;
- if (idx >= mTags->size())
- {
- DefaultLogger::get()->warn("LWO: Invalid face surface index");
- idx = UINT_MAX;
- }
- if(UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx])) {
- if (UINT_MAX == iDefaultSurface) {
- iDefaultSurface = (unsigned int)mSurfaces->size();
- mSurfaces->push_back(LWO::Surface());
- LWO::Surface& surf = mSurfaces->back();
- surf.mColor.r = surf.mColor.g = surf.mColor.b = 0.6f;
- surf.mName = "LWODefaultSurface";
- }
- idx = iDefaultSurface;
- }
- pSorted[idx].push_back(i);
- }
- if (UINT_MAX == iDefaultSurface) {
- pSorted.erase(pSorted.end()-1);
- }
- for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) {
- SortedRep& sorted = pSorted[i];
- if (sorted.empty())
- continue;
-
- // generate the mesh
- aiMesh* mesh = new aiMesh();
- apcMeshes.push_back(mesh);
- mesh->mNumFaces = (unsigned int)sorted.size();
-
- // count the number of vertices
- SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
- for (;it != end;++it) {
- mesh->mNumVertices += layer.mFaces[*it].mNumIndices;
- }
-
- aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
- mesh->mMaterialIndex = i;
-
- // find out which vertex color channels and which texture coordinate
- // channels are really required by the material attached to this mesh
- unsigned int vUVChannelIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS];
+ DefaultLogger::get()->info("LWO file format: LXOB (Modo)");
+ }
+ // we don't know this format
+ else
+ {
+ char szBuff[5];
+ szBuff[0] = (char)(fileType >> 24u);
+ szBuff[1] = (char)(fileType >> 16u);
+ szBuff[2] = (char)(fileType >> 8u);
+ szBuff[3] = (char)(fileType);
+ szBuff[4] = '\0';
+ throw DeadlyImportError(std::string("Unknown LWO sub format: ") + szBuff);
+ }
+
+ if (AI_LWO_FOURCC_LWOB != fileType) {
+ mIsLWO2 = true;
+ LoadLWO2File();
+
+ // The newer lightwave format allows the user to configure the
+ // loader that just one layer is used. If this is the case
+ // we need to check now whether the requested layer has been found.
+ if (UINT_MAX != configLayerIndex) {
+ unsigned int layerCount = 0;
+ for(std::list<LWO::Layer>::iterator itLayers=mLayers->begin(); itLayers!=mLayers->end(); ++itLayers)
+ if (!itLayers->skip)
+ layerCount++;
+ if (layerCount!=2)
+ throw DeadlyImportError("LWO2: The requested layer was not found");
+ }
+
+ if (configLayerName.length() && !hasNamedLayer) {
+ throw DeadlyImportError("LWO2: Unable to find the requested layer: "
+ + configLayerName);
+ }
+ }
+
+ // now, as we have loaded all data, we can resolve cross-referenced tags and clips
+ ResolveTags();
+ ResolveClips();
+
+ // now process all layers and build meshes and nodes
+ std::vector<aiMesh*> apcMeshes;
+ std::map<uint16_t, aiNode*> apcNodes;
+
+ apcMeshes.reserve(mLayers->size()*std::min(((unsigned int)mSurfaces->size()/2u), 1u));
+
+ unsigned int iDefaultSurface = UINT_MAX; // index of the default surface
+ for (LWO::Layer &layer : *mLayers) {
+ if (layer.skip)
+ continue;
+
+ // I don't know whether there could be dummy layers, but it would be possible
+ const unsigned int meshStart = (unsigned int)apcMeshes.size();
+ if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) {
+
+ // now sort all faces by the surfaces assigned to them
+ std::vector<SortedRep> pSorted(mSurfaces->size()+1);
+
+ unsigned int i = 0;
+ for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();it != end;++it,++i) {
+ // Check whether we support this face's type
+ if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH &&
+ (*it).type != AI_LWO_BONE && (*it).type != AI_LWO_SUBD) {
+ continue;
+ }
+
+ unsigned int idx = (*it).surfaceIndex;
+ if (idx >= mTags->size())
+ {
+ DefaultLogger::get()->warn("LWO: Invalid face surface index");
+ idx = UINT_MAX;
+ }
+ if(UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx])) {
+ if (UINT_MAX == iDefaultSurface) {
+ iDefaultSurface = (unsigned int)mSurfaces->size();
+ mSurfaces->push_back(LWO::Surface());
+ LWO::Surface& surf = mSurfaces->back();
+ surf.mColor.r = surf.mColor.g = surf.mColor.b = 0.6f;
+ surf.mName = "LWODefaultSurface";
+ }
+ idx = iDefaultSurface;
+ }
+ pSorted[idx].push_back(i);
+ }
+ if (UINT_MAX == iDefaultSurface) {
+ pSorted.erase(pSorted.end()-1);
+ }
+ for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) {
+ SortedRep& sorted = pSorted[i];
+ if (sorted.empty())
+ continue;
+
+ // generate the mesh
+ aiMesh* mesh = new aiMesh();
+ apcMeshes.push_back(mesh);
+ mesh->mNumFaces = (unsigned int)sorted.size();
+
+ // count the number of vertices
+ SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
+ for (;it != end;++it) {
+ mesh->mNumVertices += layer.mFaces[*it].mNumIndices;
+ }
+
+ aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
+ mesh->mMaterialIndex = i;
+
+ // find out which vertex color channels and which texture coordinate
+ // channels are really required by the material attached to this mesh
+ unsigned int vUVChannelIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS];
#ifdef ASSIMP_BUILD_DEBUG
- for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) {
- vUVChannelIndices[mui] = UINT_MAX;
- }
- for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui ) {
- vVColorIndices[mui] = UINT_MAX;
- }
+ for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) {
+ vUVChannelIndices[mui] = UINT_MAX;
+ }
+ for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui ) {
+ vVColorIndices[mui] = UINT_MAX;
+ }
#endif
- FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices);
- FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices);
-
- // allocate storage for UV and CV channels
- aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) {
- if (UINT_MAX == vUVChannelIndices[mui]) {
- break;
- }
-
- pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
-
- // LightWave doesn't support more than 2 UV components (?)
- mesh->mNumUVComponents[0] = 2;
- }
-
- if (layer.mNormals.name.length())
- nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
-
- aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
- for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) {
- if (UINT_MAX == vVColorIndices[mui]) {
- break;
- }
- pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices];
- }
-
- // we would not need this extra array, but the code is much cleaner if we use it
- std::vector<unsigned int>& smoothingGroups = layer.mPointReferrers;
- smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end());
- smoothingGroups.resize(mesh->mNumFaces,0);
-
- // now convert all faces
- unsigned int vert = 0;
- std::vector<unsigned int>::iterator outIt = smoothingGroups.begin();
- for (it = sorted.begin(); it != end;++it,++outIt) {
- const LWO::Face& face = layer.mFaces[*it];
- *outIt = face.smoothGroup;
-
- // copy all vertices
- for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) {
- unsigned int idx = face.mIndices[q];
- *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/;
-
- // process UV coordinates
- for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) {
- if (UINT_MAX == vUVChannelIndices[w]) {
- break;
- }
- aiVector3D*& pp = pvUV[w];
- const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx];
- pp->x = src.x;
- pp->y = src.y;
- pp++;
- }
-
- // process normals (MODO extension)
- if (nrm) {
- *nrm = ((aiVector3D*)&layer.mNormals.rawData[0])[idx];
- nrm->z *= -1.f;
- ++nrm;
- }
-
- // process vertex colors
- for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) {
- if (UINT_MAX == vVColorIndices[w]) {
- break;
- }
- *pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx];
-
- // If a RGB color map is explicitly requested delete the
- // alpha channel - it could theoretically be != 1.
- if(_mSurfaces[i].mVCMapType == AI_LWO_RGB)
- pvVC[w]->a = 1.f;
-
- pvVC[w]++;
- }
+ FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices);
+ FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices);
+
+ // allocate storage for UV and CV channels
+ aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) {
+ if (UINT_MAX == vUVChannelIndices[mui]) {
+ break;
+ }
+
+ pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
+
+ // LightWave doesn't support more than 2 UV components (?)
+ mesh->mNumUVComponents[0] = 2;
+ }
+
+ if (layer.mNormals.name.length())
+ nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+
+ aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
+ for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) {
+ if (UINT_MAX == vVColorIndices[mui]) {
+ break;
+ }
+ pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices];
+ }
+
+ // we would not need this extra array, but the code is much cleaner if we use it
+ std::vector<unsigned int>& smoothingGroups = layer.mPointReferrers;
+ smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end());
+ smoothingGroups.resize(mesh->mNumFaces,0);
+
+ // now convert all faces
+ unsigned int vert = 0;
+ std::vector<unsigned int>::iterator outIt = smoothingGroups.begin();
+ for (it = sorted.begin(); it != end;++it,++outIt) {
+ const LWO::Face& face = layer.mFaces[*it];
+ *outIt = face.smoothGroup;
+
+ // copy all vertices
+ for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) {
+ unsigned int idx = face.mIndices[q];
+ *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/;
+
+ // process UV coordinates
+ for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) {
+ if (UINT_MAX == vUVChannelIndices[w]) {
+ break;
+ }
+ aiVector3D*& pp = pvUV[w];
+ const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx];
+ pp->x = src.x;
+ pp->y = src.y;
+ pp++;
+ }
+
+ // process normals (MODO extension)
+ if (nrm) {
+ *nrm = ((aiVector3D*)&layer.mNormals.rawData[0])[idx];
+ nrm->z *= -1.f;
+ ++nrm;
+ }
+
+ // process vertex colors
+ for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) {
+ if (UINT_MAX == vVColorIndices[w]) {
+ break;
+ }
+ *pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx];
+
+ // If a RGB color map is explicitly requested delete the
+ // alpha channel - it could theoretically be != 1.
+ if(_mSurfaces[i].mVCMapType == AI_LWO_RGB)
+ pvVC[w]->a = 1.f;
+
+ pvVC[w]++;
+ }
#if 0
- // process vertex weights. We can't properly reconstruct the whole skeleton for now,
- // but we can create dummy bones for all weight channels which we have.
- for (unsigned int w = 0; w < layer.mWeightChannels.size();++w)
- {
- }
+ // process vertex weights. We can't properly reconstruct the whole skeleton for now,
+ // but we can create dummy bones for all weight channels which we have.
+ for (unsigned int w = 0; w < layer.mWeightChannels.size();++w)
+ {
+ }
#endif
- face.mIndices[q] = vert;
- }
- pf->mIndices = face.mIndices;
- pf->mNumIndices = face.mNumIndices;
- unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted
- pf++;
- }
-
- if (!mesh->mNormals) {
- // Compute normal vectors for the mesh - we can't use our GenSmoothNormal-
- // Step here since it wouldn't handle smoothing groups correctly for LWO.
- // So we use a separate implementation.
- ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
- }
- else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there");
- ++p;
- }
- }
-
- // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
- unsigned int num = apcMeshes.size() - meshStart;
- if (layer.mName != "<LWODefault>" || num > 0) {
- aiNode* pcNode = new aiNode();
- apcNodes[layer.mIndex] = pcNode;
- pcNode->mName.Set(layer.mName);
- pcNode->mParent = (aiNode*)&layer;
- pcNode->mNumMeshes = num;
-
- if (pcNode->mNumMeshes) {
- pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
- for (unsigned int p = 0; p < pcNode->mNumMeshes;++p)
- pcNode->mMeshes[p] = p + meshStart;
- }
- }
- }
-
- if (apcNodes.empty() || apcMeshes.empty())
- throw DeadlyImportError("LWO: No meshes loaded");
-
- // The RemoveRedundantMaterials step will clean this up later
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
- for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) {
- aiMaterial* pcMat = new aiMaterial();
- pScene->mMaterials[mat] = pcMat;
- ConvertMaterial((*mSurfaces)[mat],pcMat);
- }
-
- // copy the meshes to the output structure
- pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ];
- ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*));
-
- // generate the final node graph
- GenerateNodeGraph(apcNodes);
+ face.mIndices[q] = vert;
+ }
+ pf->mIndices = face.mIndices;
+ pf->mNumIndices = face.mNumIndices;
+ unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted
+ pf++;
+ }
+
+ if (!mesh->mNormals) {
+ // Compute normal vectors for the mesh - we can't use our GenSmoothNormal-
+ // Step here since it wouldn't handle smoothing groups correctly for LWO.
+ // So we use a separate implementation.
+ ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
+ }
+ else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there");
+ ++p;
+ }
+ }
+
+ // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
+ unsigned int num = apcMeshes.size() - meshStart;
+ if (layer.mName != "<LWODefault>" || num > 0) {
+ aiNode* pcNode = new aiNode();
+ apcNodes[layer.mIndex] = pcNode;
+ pcNode->mName.Set(layer.mName);
+ pcNode->mParent = (aiNode*)&layer;
+ pcNode->mNumMeshes = num;
+
+ if (pcNode->mNumMeshes) {
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+ for (unsigned int p = 0; p < pcNode->mNumMeshes;++p)
+ pcNode->mMeshes[p] = p + meshStart;
+ }
+ }
+ }
+
+ if (apcNodes.empty() || apcMeshes.empty())
+ throw DeadlyImportError("LWO: No meshes loaded");
+
+ // The RemoveRedundantMaterials step will clean this up later
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()];
+ for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) {
+ aiMaterial* pcMat = new aiMaterial();
+ pScene->mMaterials[mat] = pcMat;
+ ConvertMaterial((*mSurfaces)[mat],pcMat);
+ }
+
+ // copy the meshes to the output structure
+ pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ];
+ ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*));
+
+ // generate the final node graph
+ GenerateNodeGraph(apcNodes);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
- const LWO::Surface& surface)
+ const LWO::Surface& surface)
{
- // Allocate output storage
- mesh->mNormals = new aiVector3D[mesh->mNumVertices];
-
- // First generate per-face normals
- aiVector3D* out;
- std::vector<aiVector3D> faceNormals;
-
- // ... in some cases that's already enough
- if (!surface.mMaximumSmoothAngle)
- out = mesh->mNormals;
- else {
- faceNormals.resize(mesh->mNumVertices);
- out = &faceNormals[0];
- }
-
- aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces;
- for (; begin != end; ++begin) {
- aiFace& face = *begin;
-
- if(face.mNumIndices < 3) {
- continue;
- }
-
- // LWO doc: "the normal is defined as the cross product of the first and last edges"
- aiVector3D* pV1 = mesh->mVertices + face.mIndices[0];
- aiVector3D* pV2 = mesh->mVertices + face.mIndices[1];
- aiVector3D* pV3 = mesh->mVertices + face.mIndices[face.mNumIndices-1];
-
- aiVector3D vNor = ((*pV2 - *pV1) ^(*pV3 - *pV1)).Normalize();
- for (unsigned int i = 0; i < face.mNumIndices;++i)
- out[face.mIndices[i]] = vNor;
- }
- if (!surface.mMaximumSmoothAngle)return;
- const float posEpsilon = ComputePositionEpsilon(mesh);
-
- // Now generate the spatial sort tree
- SGSpatialSort sSort;
- std::vector<unsigned int>::const_iterator it = smoothingGroups.begin();
- for( begin = mesh->mFaces; begin != end; ++begin, ++it)
- {
- aiFace& face = *begin;
- for (unsigned int i = 0; i < face.mNumIndices;++i)
- {
- unsigned int tt = face.mIndices[i];
- sSort.Add(mesh->mVertices[tt],tt,*it);
- }
- }
- // Sort everything - this takes O(nlogn) time
- sSort.Prepare();
- std::vector<unsigned int> poResult;
- poResult.reserve(20);
-
- // Generate vertex normals. We have O(logn) for the binary lookup, which we need
- // for n elements, thus the EXPECTED complexity is O(nlogn)
- if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) {
- const float fLimit = std::cos(surface.mMaximumSmoothAngle);
-
- for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
- const aiFace& face = *begin;
- unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
- for (; beginIdx != endIdx; ++beginIdx)
- {
- unsigned int idx = *beginIdx;
- sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
- std::vector<unsigned int>::const_iterator a, end = poResult.end();
-
- aiVector3D vNormals;
- for (a = poResult.begin();a != end;++a) {
- const aiVector3D& v = faceNormals[*a];
- if (v * faceNormals[idx] < fLimit)
- continue;
- vNormals += v;
- }
- mesh->mNormals[idx] = vNormals.Normalize();
- }
- }
- }
- // faster code path in case there is no smooth angle
- else {
- std::vector<bool> vertexDone(mesh->mNumVertices,false);
- for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
- const aiFace& face = *begin;
- unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
- for (; beginIdx != endIdx; ++beginIdx)
- {
- unsigned int idx = *beginIdx;
- if (vertexDone[idx])
- continue;
- sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
- std::vector<unsigned int>::const_iterator a, end = poResult.end();
-
- aiVector3D vNormals;
- for (a = poResult.begin();a != end;++a) {
- const aiVector3D& v = faceNormals[*a];
- vNormals += v;
- }
- vNormals.Normalize();
- for (a = poResult.begin();a != end;++a) {
- mesh->mNormals[*a] = vNormals;
- vertexDone[*a] = true;
- }
- }
- }
- }
+ // Allocate output storage
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+
+ // First generate per-face normals
+ aiVector3D* out;
+ std::vector<aiVector3D> faceNormals;
+
+ // ... in some cases that's already enough
+ if (!surface.mMaximumSmoothAngle)
+ out = mesh->mNormals;
+ else {
+ faceNormals.resize(mesh->mNumVertices);
+ out = &faceNormals[0];
+ }
+
+ aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces;
+ for (; begin != end; ++begin) {
+ aiFace& face = *begin;
+
+ if(face.mNumIndices < 3) {
+ continue;
+ }
+
+ // LWO doc: "the normal is defined as the cross product of the first and last edges"
+ aiVector3D* pV1 = mesh->mVertices + face.mIndices[0];
+ aiVector3D* pV2 = mesh->mVertices + face.mIndices[1];
+ aiVector3D* pV3 = mesh->mVertices + face.mIndices[face.mNumIndices-1];
+
+ aiVector3D vNor = ((*pV2 - *pV1) ^(*pV3 - *pV1)).Normalize();
+ for (unsigned int i = 0; i < face.mNumIndices;++i)
+ out[face.mIndices[i]] = vNor;
+ }
+ if (!surface.mMaximumSmoothAngle)return;
+ const float posEpsilon = ComputePositionEpsilon(mesh);
+
+ // Now generate the spatial sort tree
+ SGSpatialSort sSort;
+ std::vector<unsigned int>::const_iterator it = smoothingGroups.begin();
+ for( begin = mesh->mFaces; begin != end; ++begin, ++it)
+ {
+ aiFace& face = *begin;
+ for (unsigned int i = 0; i < face.mNumIndices;++i)
+ {
+ unsigned int tt = face.mIndices[i];
+ sSort.Add(mesh->mVertices[tt],tt,*it);
+ }
+ }
+ // Sort everything - this takes O(nlogn) time
+ sSort.Prepare();
+ std::vector<unsigned int> poResult;
+ poResult.reserve(20);
+
+ // Generate vertex normals. We have O(logn) for the binary lookup, which we need
+ // for n elements, thus the EXPECTED complexity is O(nlogn)
+ if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) {
+ const float fLimit = std::cos(surface.mMaximumSmoothAngle);
+
+ for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
+ const aiFace& face = *begin;
+ unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
+ for (; beginIdx != endIdx; ++beginIdx)
+ {
+ unsigned int idx = *beginIdx;
+ sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
+ std::vector<unsigned int>::const_iterator a, end = poResult.end();
+
+ aiVector3D vNormals;
+ for (a = poResult.begin();a != end;++a) {
+ const aiVector3D& v = faceNormals[*a];
+ if (v * faceNormals[idx] < fLimit)
+ continue;
+ vNormals += v;
+ }
+ mesh->mNormals[idx] = vNormals.Normalize();
+ }
+ }
+ }
+ // faster code path in case there is no smooth angle
+ else {
+ std::vector<bool> vertexDone(mesh->mNumVertices,false);
+ for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
+ const aiFace& face = *begin;
+ unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
+ for (; beginIdx != endIdx; ++beginIdx)
+ {
+ unsigned int idx = *beginIdx;
+ if (vertexDone[idx])
+ continue;
+ sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
+ std::vector<unsigned int>::const_iterator a, end = poResult.end();
+
+ aiVector3D vNormals;
+ for (a = poResult.begin();a != end;++a) {
+ const aiVector3D& v = faceNormals[*a];
+ vNormals += v;
+ }
+ vNormals.Normalize();
+ for (a = poResult.begin();a != end;++a) {
+ mesh->mNormals[*a] = vNormals;
+ vertexDone[*a] = true;
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes)
{
- // now generate the final nodegraph - generate a root node and attach children
- aiNode* root = pScene->mRootNode = new aiNode();
- root->mName.Set("<LWORoot>");
-
- //Set parent of all children, inserting pivots
- //std::cout << "Set parent of all children" << std::endl;
- std::map<uint16_t, aiNode*> mapPivot;
- for (std::map<uint16_t,aiNode*>::iterator itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
-
- //Get the parent index
- LWO::Layer* nodeLayer = (LWO::Layer*)(itapcNodes->second->mParent);
- uint16_t parentIndex = nodeLayer->mParent;
-
- //Create pivot node, store it into the pivot map, and set the parent as the pivot
- aiNode* pivotNode = new aiNode();
- pivotNode->mName.Set("Pivot-"+std::string(itapcNodes->second->mName.data));
- mapPivot[-(itapcNodes->first+2)] = pivotNode;
- itapcNodes->second->mParent = pivotNode;
-
- //Look for the parent node to attach the pivot to
- if (apcNodes.find(parentIndex) != apcNodes.end()) {
- pivotNode->mParent = apcNodes[parentIndex];
- } else {
- //If not, attach to the root node
- pivotNode->mParent = root;
- }
-
- //Set the node and the pivot node transformation
- itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
- itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
- itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
- pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
- pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
- pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
- }
-
- //Merge pivot map into node map
- //std::cout << "Merge pivot map into node map" << std::endl;
- for (std::map<uint16_t, aiNode*>::iterator itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) {
- apcNodes[itMapPivot->first] = itMapPivot->second;
- }
-
- //Set children of all parents
- apcNodes[-1] = root;
- for (std::map<uint16_t,aiNode*>::iterator itMapParentNodes = apcNodes.begin(); itMapParentNodes != apcNodes.end(); ++itMapParentNodes) {
- for (std::map<uint16_t,aiNode*>::iterator itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) {
- if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) {
- ++(itMapParentNodes->second->mNumChildren);
- }
- }
- if (itMapParentNodes->second->mNumChildren) {
- itMapParentNodes->second->mChildren = new aiNode* [ itMapParentNodes->second->mNumChildren ];
- uint16_t p = 0;
- for (std::map<uint16_t,aiNode*>::iterator itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) {
- if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) {
- itMapParentNodes->second->mChildren[p++] = itMapChildNodes->second;
- }
- }
- }
- }
-
- if (!pScene->mRootNode->mNumChildren)
- throw DeadlyImportError("LWO: Unable to build a valid node graph");
-
- // Remove a single root node with no meshes assigned to it ...
- if (1 == pScene->mRootNode->mNumChildren) {
- aiNode* pc = pScene->mRootNode->mChildren[0];
- pc->mParent = pScene->mRootNode->mChildren[0] = NULL;
- delete pScene->mRootNode;
- pScene->mRootNode = pc;
- }
-
- // convert the whole stuff to RH with CCW winding
- MakeLeftHandedProcess maker;
- maker.Execute(pScene);
-
- FlipWindingOrderProcess flipper;
- flipper.Execute(pScene);
+ // now generate the final nodegraph - generate a root node and attach children
+ aiNode* root = pScene->mRootNode = new aiNode();
+ root->mName.Set("<LWORoot>");
+
+ //Set parent of all children, inserting pivots
+ //std::cout << "Set parent of all children" << std::endl;
+ std::map<uint16_t, aiNode*> mapPivot;
+ for (std::map<uint16_t,aiNode*>::iterator itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
+
+ //Get the parent index
+ LWO::Layer* nodeLayer = (LWO::Layer*)(itapcNodes->second->mParent);
+ uint16_t parentIndex = nodeLayer->mParent;
+
+ //Create pivot node, store it into the pivot map, and set the parent as the pivot
+ aiNode* pivotNode = new aiNode();
+ pivotNode->mName.Set("Pivot-"+std::string(itapcNodes->second->mName.data));
+ mapPivot[-(itapcNodes->first+2)] = pivotNode;
+ itapcNodes->second->mParent = pivotNode;
+
+ //Look for the parent node to attach the pivot to
+ if (apcNodes.find(parentIndex) != apcNodes.end()) {
+ pivotNode->mParent = apcNodes[parentIndex];
+ } else {
+ //If not, attach to the root node
+ pivotNode->mParent = root;
+ }
+
+ //Set the node and the pivot node transformation
+ itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
+ itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
+ itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
+ pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
+ pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
+ pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
+ }
+
+ //Merge pivot map into node map
+ //std::cout << "Merge pivot map into node map" << std::endl;
+ for (std::map<uint16_t, aiNode*>::iterator itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) {
+ apcNodes[itMapPivot->first] = itMapPivot->second;
+ }
+
+ //Set children of all parents
+ apcNodes[-1] = root;
+ for (std::map<uint16_t,aiNode*>::iterator itMapParentNodes = apcNodes.begin(); itMapParentNodes != apcNodes.end(); ++itMapParentNodes) {
+ for (std::map<uint16_t,aiNode*>::iterator itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) {
+ if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) {
+ ++(itMapParentNodes->second->mNumChildren);
+ }
+ }
+ if (itMapParentNodes->second->mNumChildren) {
+ itMapParentNodes->second->mChildren = new aiNode* [ itMapParentNodes->second->mNumChildren ];
+ uint16_t p = 0;
+ for (std::map<uint16_t,aiNode*>::iterator itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) {
+ if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) {
+ itMapParentNodes->second->mChildren[p++] = itMapChildNodes->second;
+ }
+ }
+ }
+ }
+
+ if (!pScene->mRootNode->mNumChildren)
+ throw DeadlyImportError("LWO: Unable to build a valid node graph");
+
+ // Remove a single root node with no meshes assigned to it ...
+ if (1 == pScene->mRootNode->mNumChildren) {
+ aiNode* pc = pScene->mRootNode->mChildren[0];
+ pc->mParent = pScene->mRootNode->mChildren[0] = NULL;
+ delete pScene->mRootNode;
+ pScene->mRootNode = pc;
+ }
+
+ // convert the whole stuff to RH with CCW winding
+ MakeLeftHandedProcess maker;
+ maker.Execute(pScene);
+
+ FlipWindingOrderProcess flipper;
+ flipper.Execute(pScene);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::ResolveTags()
{
- // --- this function is used for both LWO2 and LWOB
- mMapping->resize(mTags->size(), UINT_MAX);
- for (unsigned int a = 0; a < mTags->size();++a) {
+ // --- this function is used for both LWO2 and LWOB
+ mMapping->resize(mTags->size(), UINT_MAX);
+ for (unsigned int a = 0; a < mTags->size();++a) {
- const std::string& c = (*mTags)[a];
- for (unsigned int i = 0; i < mSurfaces->size();++i) {
+ const std::string& c = (*mTags)[a];
+ for (unsigned int i = 0; i < mSurfaces->size();++i) {
- const std::string& d = (*mSurfaces)[i].mName;
- if (!ASSIMP_stricmp(c,d)) {
+ const std::string& d = (*mSurfaces)[i].mName;
+ if (!ASSIMP_stricmp(c,d)) {
- (*mMapping)[a] = i;
- break;
- }
- }
- }
+ (*mMapping)[a] = i;
+ break;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::ResolveClips()
{
- for( unsigned int i = 0; i < mClips.size();++i) {
-
- Clip& clip = mClips[i];
- if (Clip::REF == clip.type) {
-
- if (clip.clipRef >= mClips.size()) {
- DefaultLogger::get()->error("LWO2: Clip referrer index is out of range");
- clip.clipRef = 0;
- }
-
- Clip& dest = mClips[clip.clipRef];
- if (Clip::REF == dest.type) {
- DefaultLogger::get()->error("LWO2: Clip references another clip reference");
- clip.type = Clip::UNSUPPORTED;
- }
-
- else {
- clip.path = dest.path;
- clip.type = dest.type;
- }
- }
- }
+ for( unsigned int i = 0; i < mClips.size();++i) {
+
+ Clip& clip = mClips[i];
+ if (Clip::REF == clip.type) {
+
+ if (clip.clipRef >= mClips.size()) {
+ DefaultLogger::get()->error("LWO2: Clip referrer index is out of range");
+ clip.clipRef = 0;
+ }
+
+ Clip& dest = mClips[clip.clipRef];
+ if (Clip::REF == dest.type) {
+ DefaultLogger::get()->error("LWO2: Clip references another clip reference");
+ clip.type = Clip::UNSUPPORTED;
+ }
+
+ else {
+ clip.path = dest.path;
+ clip.type = dest.type;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::AdjustTexturePath(std::string& out)
{
- // --- this function is used for both LWO2 and LWOB
- if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) {
-
- // remove the (sequence) and append 000
- DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored");
- out = out.substr(0,out.length()-10) + "000";
- }
-
- // format: drive:path/file - we just need to insert a slash after the drive
- std::string::size_type n = out.find_first_of(':');
- if (std::string::npos != n) {
- out.insert(n+1,"/");
- }
+ // --- this function is used for both LWO2 and LWOB
+ if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) {
+
+ // remove the (sequence) and append 000
+ DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored");
+ out = out.substr(0,out.length()-10) + "000";
+ }
+
+ // format: drive:path/file - we just need to insert a slash after the drive
+ std::string::size_type n = out.find_first_of(':');
+ if (std::string::npos != n) {
+ out.insert(n+1,"/");
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOTags(unsigned int size)
{
- // --- this function is used for both LWO2 and LWOB
-
- const char* szCur = (const char*)mFileBuffer, *szLast = szCur;
- const char* const szEnd = szLast+size;
- while (szCur < szEnd)
- {
- if (!(*szCur))
- {
- const size_t len = (size_t)(szCur-szLast);
- // FIX: skip empty-sized tags
- if (len)
- mTags->push_back(std::string(szLast,len));
- szCur += (len&0x1 ? 1 : 2);
- szLast = szCur;
- }
- szCur++;
- }
+ // --- this function is used for both LWO2 and LWOB
+
+ const char* szCur = (const char*)mFileBuffer, *szLast = szCur;
+ const char* const szEnd = szLast+size;
+ while (szCur < szEnd)
+ {
+ if (!(*szCur))
+ {
+ const size_t len = (size_t)(szCur-szLast);
+ // FIX: skip empty-sized tags
+ if (len)
+ mTags->push_back(std::string(szLast,len));
+ szCur += (len&0x1 ? 1 : 2);
+ szLast = szCur;
+ }
+ szCur++;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOPoints(unsigned int length)
{
- // --- this function is used for both LWO2 and LWOB but for
- // LWO2 we need to allocate 25% more storage - it could be we'll
- // need to duplicate some points later.
- unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
- if (mIsLWO2)
- {
- mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) );
- mCurLayer->mTempPoints.resize ( regularSize );
-
- // initialize all point referrers with the default values
- mCurLayer->mPointReferrers.reserve ( regularSize + (regularSize>>2u) );
- mCurLayer->mPointReferrers.resize ( regularSize, UINT_MAX );
- }
- else mCurLayer->mTempPoints.resize( regularSize );
-
- // perform endianess conversions
+ // --- this function is used for both LWO2 and LWOB but for
+ // LWO2 we need to allocate 25% more storage - it could be we'll
+ // need to duplicate some points later.
+ const size_t vertexLen = 12;
+ if ((length % vertexLen) != 0)
+ {
+ throw DeadlyImportError( "LWO2: Points chunk length is not multiple of vertexLen (12)");
+ }
+ unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
+ if (mIsLWO2)
+ {
+ mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) );
+ mCurLayer->mTempPoints.resize ( regularSize );
+
+ // initialize all point referrers with the default values
+ mCurLayer->mPointReferrers.reserve ( regularSize + (regularSize>>2u) );
+ mCurLayer->mPointReferrers.resize ( regularSize, UINT_MAX );
+ }
+ else mCurLayer->mTempPoints.resize( regularSize );
+
+ // perform endianness conversions
#ifndef AI_BUILD_BIG_ENDIAN
- for (unsigned int i = 0; i < length>>2;++i)
- ByteSwap::Swap4( mFileBuffer + (i << 2));
+ for (unsigned int i = 0; i < length>>2;++i)
+ ByteSwap::Swap4( mFileBuffer + (i << 2));
#endif
- ::memcpy(&mCurLayer->mTempPoints[0],mFileBuffer,length);
+ ::memcpy(&mCurLayer->mTempPoints[0],mFileBuffer,length);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Polygons(unsigned int length)
{
- LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
- const uint32_t type = GetU4();
-
- // Determine the type of the polygons
- switch (type)
- {
- // read unsupported stuff too (although we wont process it)
- case AI_LWO_MBAL:
- DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)");
- break;
- case AI_LWO_CURV:
- DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
- break;
-
- // These are ok with no restrictions
- case AI_LWO_PTCH:
- case AI_LWO_FACE:
- case AI_LWO_BONE:
- case AI_LWO_SUBD:
- break;
- default:
-
- // hm!? wtf is this? ok ...
- DefaultLogger::get()->error("LWO2: Ignoring unknown polygon type.");
- break;
- }
-
- // first find out how many faces and vertices we'll finally need
- uint16_t* cursor= (uint16_t*)mFileBuffer;
-
- unsigned int iNumFaces = 0,iNumVertices = 0;
- CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
-
- // allocate the output array and copy face indices
- if (iNumFaces) {
- cursor = (uint16_t*)mFileBuffer;
-
- mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
- FaceList::iterator it = mCurLayer->mFaces.begin();
- CopyFaceIndicesLWO2(it,cursor,end);
- }
+ LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
+ const uint32_t type = GetU4();
+
+ // Determine the type of the polygons
+ switch (type)
+ {
+ // read unsupported stuff too (although we wont process it)
+ case AI_LWO_MBAL:
+ DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)");
+ break;
+ case AI_LWO_CURV:
+ DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
+ break;
+
+ // These are ok with no restrictions
+ case AI_LWO_PTCH:
+ case AI_LWO_FACE:
+ case AI_LWO_BONE:
+ case AI_LWO_SUBD:
+ break;
+ default:
+
+ // hm!? wtf is this? ok ...
+ DefaultLogger::get()->error("LWO2: Ignoring unknown polygon type.");
+ break;
+ }
+
+ // first find out how many faces and vertices we'll finally need
+ uint16_t* cursor= (uint16_t*)mFileBuffer;
+
+ unsigned int iNumFaces = 0,iNumVertices = 0;
+ CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
+
+ // allocate the output array and copy face indices
+ if (iNumFaces)
+ {
+ cursor = (uint16_t*)mFileBuffer;
+
+ mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
+ FaceList::iterator it = mCurLayer->mFaces.begin();
+ CopyFaceIndicesLWO2(it,cursor,end);
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& faces,
- uint16_t*& cursor, const uint16_t* const end, unsigned int max)
+ uint16_t*& cursor, const uint16_t* const end, unsigned int max)
{
- while (cursor < end && max--)
- {
- AI_LSWAP2P(cursor);
- uint16_t numIndices = *cursor++;
- numIndices &= 0x03FF;
- verts += numIndices;++faces;
-
- for(uint16_t i = 0; i < numIndices; i++)
- ReadVSizedIntLWO2((uint8_t*&)cursor);
- }
+ while (cursor < end && max--)
+ {
+ uint16_t numIndices;
+ ::memcpy(&numIndices, cursor++, 2);
+ AI_LSWAP2(numIndices);
+ numIndices &= 0x03FF;
+
+ verts += numIndices;
+ ++faces;
+
+ for(uint16_t i = 0; i < numIndices; i++)
+ {
+ ReadVSizedIntLWO2((uint8_t*&)cursor);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
- uint16_t*& cursor,
- const uint16_t* const end)
+ uint16_t*& cursor,
+ const uint16_t* const end)
{
- while (cursor < end) {
-
- LWO::Face& face = *it++;;
- if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ {
- face.mIndices = new unsigned int[face.mNumIndices];
- for(unsigned int i = 0; i < face.mNumIndices; i++)
- {
- face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs;
- if(face.mIndices[i] > mCurLayer->mTempPoints.size())
- {
- DefaultLogger::get()->warn("LWO2: Failure evaluating face record, index is out of range");
- face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1;
- }
- }
- }
- else throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices");
- }
+ while (cursor < end)
+ {
+ LWO::Face& face = *it++;
+ uint16_t numIndices;
+ ::memcpy(&numIndices, cursor++, 2);
+ AI_LSWAP2(numIndices);
+ face.mNumIndices = numIndices & 0x03FF;
+
+ if(face.mNumIndices) /* byte swapping has already been done */
+ {
+ face.mIndices = new unsigned int[face.mNumIndices];
+ for(unsigned int i = 0; i < face.mNumIndices; i++)
+ {
+ face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs;
+ if(face.mIndices[i] > mCurLayer->mTempPoints.size())
+ {
+ DefaultLogger::get()->warn("LWO2: Failure evaluating face record, index is out of range");
+ face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1;
+ }
+ }
+ }
+ else throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices");
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
{
- LE_NCONST uint8_t* const end = mFileBuffer+length;
+ LE_NCONST uint8_t* const end = mFileBuffer+length;
- AI_LWO_VALIDATE_CHUNK_LENGTH(length,PTAG,4);
- uint32_t type = GetU4();
+ AI_LWO_VALIDATE_CHUNK_LENGTH(length,PTAG,4);
+ uint32_t type = GetU4();
- if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
- return;
+ if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
+ return;
- while (mFileBuffer < end) {
+ while (mFileBuffer < end)
+ {
+ unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
+ unsigned int j = GetU2();
- unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
- unsigned int j = GetU2();
-
- if (i >= mCurLayer->mFaces.size()) {
- DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range");
- continue;
- }
+ if (i >= mCurLayer->mFaces.size()) {
+ DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range");
+ continue;
+ }
- switch (type) {
+ switch (type) {
- case AI_LWO_SURF:
- mCurLayer->mFaces[i].surfaceIndex = j;
- break;
- case AI_LWO_SMGP: /* is that really used? */
- mCurLayer->mFaces[i].smoothGroup = j;
- break;
- };
- }
+ case AI_LWO_SURF:
+ mCurLayer->mFaces[i].surfaceIndex = j;
+ break;
+ case AI_LWO_SMGP: /* is that really used? */
+ mCurLayer->mFaces[i].smoothGroup = j;
+ break;
+ };
+ }
}
// ------------------------------------------------------------------------------------------------
template <class T>
VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly)
{
- for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end; ++it) {
- if ((*it).name == name) {
- if (!perPoly) {
- DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names");
- }
- return &(*it);
- }
- }
- list.push_back( T() );
- VMapEntry* p = &list.back();
- p->name = name;
- return p;
+ for (auto & elem : list) {
+ if (elem.name == name) {
+ if (!perPoly) {
+ DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names");
+ }
+ return &elem;
+ }
+ }
+ list.push_back( T() );
+ VMapEntry* p = &list.back();
+ p->name = name;
+ return p;
}
// ------------------------------------------------------------------------------------------------
template <class T>
inline void CreateNewEntry(T& chan, unsigned int srcIdx)
{
- if (!chan.name.length())
- return;
+ if (!chan.name.length())
+ return;
- chan.abAssigned[srcIdx] = true;
- chan.abAssigned.resize(chan.abAssigned.size()+1,false);
+ chan.abAssigned[srcIdx] = true;
+ chan.abAssigned.resize(chan.abAssigned.size()+1,false);
- for (unsigned int a = 0; a < chan.dims;++a)
- chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]);
+ for (unsigned int a = 0; a < chan.dims;++a)
+ chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]);
}
// ------------------------------------------------------------------------------------------------
template <class T>
inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
{
- for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end;++it) {
- CreateNewEntry( *it, srcIdx );
- }
+ for (auto &elem : list) {
+ CreateNewEntry( elem, srcIdx );
+ }
}
// ------------------------------------------------------------------------------------------------
-inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
- unsigned int idx, float* data)
+inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
+ unsigned int idx, float* data)
{
- ai_assert(NULL != data);
- LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
- unsigned int i;
-
- base->abAssigned[idx] = true;
- for (i = 0; i < numRead;++i) {
- base->rawData[idx*base->dims+i]= data[i];
- }
-
- if (UINT_MAX != (i = refList[idx])) {
- DoRecursiveVMAPAssignment(base,numRead,i,data);
- }
+ ai_assert(NULL != data);
+ LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
+ unsigned int i;
+
+ if (idx >= base->abAssigned.size()) {
+ throw DeadlyImportError("Bad index");
+ }
+ base->abAssigned[idx] = true;
+ for (i = 0; i < numRead;++i) {
+ base->rawData[idx*base->dims+i]= data[i];
+ }
+
+ if (UINT_MAX != (i = refList[idx])) {
+ DoRecursiveVMAPAssignment(base,numRead,i,data);
+ }
}
// ------------------------------------------------------------------------------------------------
inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx)
{
- if(UINT_MAX == refList[srcIdx]) {
- refList[srcIdx] = destIdx;
- return;
- }
- AddToSingleLinkedList(refList,refList[srcIdx],destIdx);
+ if(UINT_MAX == refList[srcIdx]) {
+ refList[srcIdx] = destIdx;
+ return;
+ }
+ AddToSingleLinkedList(refList,refList[srcIdx],destIdx);
}
// ------------------------------------------------------------------------------------------------
// Load LWO2 vertex map
void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
{
- LE_NCONST uint8_t* const end = mFileBuffer+length;
-
- AI_LWO_VALIDATE_CHUNK_LENGTH(length,VMAP,6);
- unsigned int type = GetU4();
- unsigned int dims = GetU2();
-
- VMapEntry* base;
-
- // read the name of the vertex map
- std::string name;
- GetS0(name,length);
-
- switch (type)
- {
- case AI_LWO_TXUV:
- if (dims != 2) {
- DefaultLogger::get()->warn("LWO2: Skipping UV channel \'"
- + name + "\' with !2 components");
- return;
- }
- base = FindEntry(mCurLayer->mUVChannels,name,perPoly);
- break;
- case AI_LWO_WGHT:
- case AI_LWO_MNVW:
- if (dims != 1) {
- DefaultLogger::get()->warn("LWO2: Skipping Weight Channel \'"
- + name + "\' with !1 components");
- return;
- }
- base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels
- : mCurLayer->mSWeightChannels),name,perPoly);
- break;
- case AI_LWO_RGB:
- case AI_LWO_RGBA:
- if (dims != 3 && dims != 4) {
- DefaultLogger::get()->warn("LWO2: Skipping Color Map \'"
- + name + "\' with a dimension > 4 or < 3");
- return;
- }
- base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
- break;
-
- case AI_LWO_MODO_NORM:
- /* This is a non-standard extension chunk used by Luxology's MODO.
- * It stores per-vertex normals. This VMAP exists just once, has
- * 3 dimensions and is btw extremely beautiful.
- */
- if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length())
- return;
-
- DefaultLogger::get()->info("Processing non-standard extension: MODO VMAP.NORM.vert_normals");
-
- mCurLayer->mNormals.name = name;
- base = & mCurLayer->mNormals;
- break;
-
- case AI_LWO_PICK: /* these VMAPs are just silently dropped */
- case AI_LWO_MORF:
- case AI_LWO_SPOT:
- return;
-
- default:
- if (name == "APS.Level") {
- // XXX handle this (seems to be subdivision-related).
- }
- DefaultLogger::get()->warn("LWO2: Skipping unknown VMAP/VMAD channel \'" + name + "\'");
- return;
- };
- base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
-
- // now read all entries in the map
- type = std::min(dims,base->dims);
- const unsigned int diff = (dims - type)<<2u;
-
- LWO::FaceList& list = mCurLayer->mFaces;
- LWO::PointList& pointList = mCurLayer->mTempPoints;
- LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
-
- float temp[4];
-
- const unsigned int numPoints = (unsigned int)pointList.size();
- const unsigned int numFaces = (unsigned int)list.size();
-
- while (mFileBuffer < end) {
-
- unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
- if (idx >= numPoints) {
- DefaultLogger::get()->warn("LWO2: Failure evaluating VMAP/VMAD entry \'" + name + "\', vertex index is out of range");
- mFileBuffer += base->dims<<2u;
- continue;
- }
- if (perPoly) {
- unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
- if (base->abAssigned[idx]) {
- // we have already a VMAP entry for this vertex - thus
- // we need to duplicate the corresponding polygon.
- if (polyIdx >= numFaces) {
- DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', polygon index is out of range");
- mFileBuffer += base->dims<<2u;
- continue;
- }
-
- LWO::Face& src = list[polyIdx];
-
- // generate a new unique vertex for the corresponding index - but only
- // if we can find the index in the face
- bool had = false;
- for (unsigned int i = 0; i < src.mNumIndices;++i) {
-
- unsigned int srcIdx = src.mIndices[i], tmp = idx;
- do {
- if (tmp == srcIdx)
- break;
- }
- while ((tmp = refList[tmp]) != UINT_MAX);
- if (tmp == UINT_MAX) {
- continue;
- }
-
- had = true;
- refList.resize(refList.size()+1, UINT_MAX);
-
- idx = (unsigned int)pointList.size();
- src.mIndices[i] = (unsigned int)pointList.size();
-
- // store the index of the new vertex in the old vertex
- // so we get a single linked list we can traverse in
- // only one direction
- AddToSingleLinkedList(refList,srcIdx,src.mIndices[i]);
- pointList.push_back(pointList[srcIdx]);
-
- CreateNewEntry(mCurLayer->mVColorChannels, srcIdx );
- CreateNewEntry(mCurLayer->mUVChannels, srcIdx );
- CreateNewEntry(mCurLayer->mWeightChannels, srcIdx );
- CreateNewEntry(mCurLayer->mSWeightChannels, srcIdx );
- CreateNewEntry(mCurLayer->mNormals, srcIdx );
- }
- if (!had) {
- DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', vertex index wasn't found in that polygon");
- ai_assert(had);
- }
- }
- }
- for (unsigned int l = 0; l < type;++l)
- temp[l] = GetF4();
-
- DoRecursiveVMAPAssignment(base,type,idx, temp);
- mFileBuffer += diff;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer+length;
+
+ AI_LWO_VALIDATE_CHUNK_LENGTH(length,VMAP,6);
+ unsigned int type = GetU4();
+ unsigned int dims = GetU2();
+
+ VMapEntry* base;
+
+ // read the name of the vertex map
+ std::string name;
+ GetS0(name,length);
+
+ switch (type)
+ {
+ case AI_LWO_TXUV:
+ if (dims != 2) {
+ DefaultLogger::get()->warn("LWO2: Skipping UV channel \'"
+ + name + "\' with !2 components");
+ return;
+ }
+ base = FindEntry(mCurLayer->mUVChannels,name,perPoly);
+ break;
+ case AI_LWO_WGHT:
+ case AI_LWO_MNVW:
+ if (dims != 1) {
+ DefaultLogger::get()->warn("LWO2: Skipping Weight Channel \'"
+ + name + "\' with !1 components");
+ return;
+ }
+ base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels
+ : mCurLayer->mSWeightChannels),name,perPoly);
+ break;
+ case AI_LWO_RGB:
+ case AI_LWO_RGBA:
+ if (dims != 3 && dims != 4) {
+ DefaultLogger::get()->warn("LWO2: Skipping Color Map \'"
+ + name + "\' with a dimension > 4 or < 3");
+ return;
+ }
+ base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
+ break;
+
+ case AI_LWO_MODO_NORM:
+ /* This is a non-standard extension chunk used by Luxology's MODO.
+ * It stores per-vertex normals. This VMAP exists just once, has
+ * 3 dimensions and is btw extremely beautiful.
+ */
+ if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length())
+ return;
+
+ DefaultLogger::get()->info("Processing non-standard extension: MODO VMAP.NORM.vert_normals");
+
+ mCurLayer->mNormals.name = name;
+ base = & mCurLayer->mNormals;
+ break;
+
+ case AI_LWO_PICK: /* these VMAPs are just silently dropped */
+ case AI_LWO_MORF:
+ case AI_LWO_SPOT:
+ return;
+
+ default:
+ if (name == "APS.Level") {
+ // XXX handle this (seems to be subdivision-related).
+ }
+ DefaultLogger::get()->warn("LWO2: Skipping unknown VMAP/VMAD channel \'" + name + "\'");
+ return;
+ };
+ base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
+
+ // now read all entries in the map
+ type = std::min(dims,base->dims);
+ const unsigned int diff = (dims - type)<<2u;
+
+ LWO::FaceList& list = mCurLayer->mFaces;
+ LWO::PointList& pointList = mCurLayer->mTempPoints;
+ LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
+
+ float temp[4];
+
+ const unsigned int numPoints = (unsigned int)pointList.size();
+ const unsigned int numFaces = (unsigned int)list.size();
+
+ while (mFileBuffer < end) {
+
+ unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
+ if (idx >= numPoints) {
+ DefaultLogger::get()->warn("LWO2: Failure evaluating VMAP/VMAD entry \'" + name + "\', vertex index is out of range");
+ mFileBuffer += base->dims<<2u;
+ continue;
+ }
+ if (perPoly) {
+ unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
+ if (base->abAssigned[idx]) {
+ // we have already a VMAP entry for this vertex - thus
+ // we need to duplicate the corresponding polygon.
+ if (polyIdx >= numFaces) {
+ DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', polygon index is out of range");
+ mFileBuffer += base->dims<<2u;
+ continue;
+ }
+
+ LWO::Face& src = list[polyIdx];
+
+ // generate a new unique vertex for the corresponding index - but only
+ // if we can find the index in the face
+ bool had = false;
+ for (unsigned int i = 0; i < src.mNumIndices;++i) {
+
+ unsigned int srcIdx = src.mIndices[i], tmp = idx;
+ do {
+ if (tmp == srcIdx)
+ break;
+ }
+ while ((tmp = refList[tmp]) != UINT_MAX);
+ if (tmp == UINT_MAX) {
+ continue;
+ }
+
+ had = true;
+ refList.resize(refList.size()+1, UINT_MAX);
+
+ idx = (unsigned int)pointList.size();
+ src.mIndices[i] = (unsigned int)pointList.size();
+
+ // store the index of the new vertex in the old vertex
+ // so we get a single linked list we can traverse in
+ // only one direction
+ AddToSingleLinkedList(refList,srcIdx,src.mIndices[i]);
+ pointList.push_back(pointList[srcIdx]);
+
+ CreateNewEntry(mCurLayer->mVColorChannels, srcIdx );
+ CreateNewEntry(mCurLayer->mUVChannels, srcIdx );
+ CreateNewEntry(mCurLayer->mWeightChannels, srcIdx );
+ CreateNewEntry(mCurLayer->mSWeightChannels, srcIdx );
+ CreateNewEntry(mCurLayer->mNormals, srcIdx );
+ }
+ if (!had) {
+ DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', vertex index wasn't found in that polygon");
+ ai_assert(had);
+ }
+ }
+ }
+ for (unsigned int l = 0; l < type;++l)
+ temp[l] = GetF4();
+
+ DoRecursiveVMAPAssignment(base,type,idx, temp);
+ mFileBuffer += diff;
+ }
}
// ------------------------------------------------------------------------------------------------
// Load LWO2 clip
void LWOImporter::LoadLWO2Clip(unsigned int length)
{
- AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10);
-
- mClips.push_back(LWO::Clip());
- LWO::Clip& clip = mClips.back();
-
- // first - get the index of the clip
- clip.idx = GetU4();
-
- IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
- switch (head->type)
- {
- case AI_LWO_STIL:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
-
- // "Normal" texture
- GetS0(clip.path,head->length);
- clip.type = Clip::STILL;
- break;
-
- case AI_LWO_ISEQ:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16);
- // Image sequence. We'll later take the first.
- {
- uint8_t digits = GetU1(); mFileBuffer++;
- int16_t offset = GetU2(); mFileBuffer+=4;
- int16_t start = GetU2(); mFileBuffer+=4;
-
- std::string s;
- std::ostringstream ss;
- GetS0(s,head->length);
-
- head->length -= (unsigned int)s.length()+1;
- ss << s;
- ss << std::setw(digits) << offset + start;
- GetS0(s,head->length);
- ss << s;
- clip.path = ss.str();
- clip.type = Clip::SEQ;
- }
- break;
-
- case AI_LWO_STCC:
- DefaultLogger::get()->warn("LWO2: Color shifted images are not supported");
- break;
-
- case AI_LWO_ANIM:
- DefaultLogger::get()->warn("LWO2: Animated textures are not supported");
- break;
-
- case AI_LWO_XREF:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4);
-
- // Just a cross-reference to another CLIp
- clip.type = Clip::REF;
- clip.clipRef = GetU4();
- break;
-
- case AI_LWO_NEGA:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2);
- clip.negate = (0 != GetU2());
- break;
-
- default:
- DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk");
- }
+ AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10);
+
+ mClips.push_back(LWO::Clip());
+ LWO::Clip& clip = mClips.back();
+
+ // first - get the index of the clip
+ clip.idx = GetU4();
+
+ IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+ switch (head.type)
+ {
+ case AI_LWO_STIL:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
+
+ // "Normal" texture
+ GetS0(clip.path,head.length);
+ clip.type = Clip::STILL;
+ break;
+
+ case AI_LWO_ISEQ:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16);
+ // Image sequence. We'll later take the first.
+ {
+ uint8_t digits = GetU1(); mFileBuffer++;
+ int16_t offset = GetU2(); mFileBuffer+=4;
+ int16_t start = GetU2(); mFileBuffer+=4;
+
+ std::string s;
+ std::ostringstream ss;
+ GetS0(s,head.length);
+
+ head.length -= (uint16_t)s.length()+1;
+ ss << s;
+ ss << std::setw(digits) << offset + start;
+ GetS0(s,head.length);
+ ss << s;
+ clip.path = ss.str();
+ clip.type = Clip::SEQ;
+ }
+ break;
+
+ case AI_LWO_STCC:
+ DefaultLogger::get()->warn("LWO2: Color shifted images are not supported");
+ break;
+
+ case AI_LWO_ANIM:
+ DefaultLogger::get()->warn("LWO2: Animated textures are not supported");
+ break;
+
+ case AI_LWO_XREF:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4);
+
+ // Just a cross-reference to another CLIp
+ clip.type = Clip::REF;
+ clip.clipRef = GetU4();
+ break;
+
+ case AI_LWO_NEGA:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2);
+ clip.negate = (0 != GetU2());
+ break;
+
+ default:
+ DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk");
+ }
}
// ------------------------------------------------------------------------------------------------
// Load envelope description
void LWOImporter::LoadLWO2Envelope(unsigned int length)
{
- LE_NCONST uint8_t* const end = mFileBuffer + length;
- AI_LWO_VALIDATE_CHUNK_LENGTH(length,ENVL,4);
+ LE_NCONST uint8_t* const end = mFileBuffer + length;
+ AI_LWO_VALIDATE_CHUNK_LENGTH(length,ENVL,4);
- mEnvelopes.push_back(LWO::Envelope());
- LWO::Envelope& envelope = mEnvelopes.back();
+ mEnvelopes.push_back(LWO::Envelope());
+ LWO::Envelope& envelope = mEnvelopes.back();
- // Get the index of the envelope
- envelope.index = ReadVSizedIntLWO2(mFileBuffer);
+ // Get the index of the envelope
+ envelope.index = ReadVSizedIntLWO2(mFileBuffer);
- // It looks like there might be an extra U4 right after the index,
- // at least in modo (LXOB) files: we'll ignore it if it's zero,
- // otherwise it represents the start of a subchunk, so we backtrack.
- if (mIsLXOB)
- {
+ // It looks like there might be an extra U4 right after the index,
+ // at least in modo (LXOB) files: we'll ignore it if it's zero,
+ // otherwise it represents the start of a subchunk, so we backtrack.
+ if (mIsLXOB)
+ {
uint32_t extra = GetU4();
if (extra)
{
mFileBuffer -= 4;
}
- }
-
- // ... and read all subchunks
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid envelope chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- // Type & representation of the envelope
- case AI_LWO_TYPE:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2);
- mFileBuffer++; // skip user format
-
- // Determine type of envelope
- envelope.type = (LWO::EnvelopeType)*mFileBuffer;
- ++mFileBuffer;
- break;
-
- // precondition
- case AI_LWO_PRE:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2);
- envelope.pre = (LWO::PrePostBehaviour)GetU2();
- break;
-
- // postcondition
- case AI_LWO_POST:
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2);
- envelope.post = (LWO::PrePostBehaviour)GetU2();
- break;
-
- // keyframe
- case AI_LWO_KEY:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8);
-
- envelope.keys.push_back(LWO::Key());
- LWO::Key& key = envelope.keys.back();
-
- key.time = GetF4();
- key.value = GetF4();
- break;
- }
-
- // interval interpolation
- case AI_LWO_SPAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4);
- if (envelope.keys.size()<2)
- DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
- else {
- LWO::Key& key = envelope.keys.back();
- switch (GetU4())
- {
- case AI_LWO_STEP:
- key.inter = LWO::IT_STEP;break;
- case AI_LWO_LINE:
- key.inter = LWO::IT_LINE;break;
- case AI_LWO_TCB:
- key.inter = LWO::IT_TCB;break;
- case AI_LWO_HERM:
- key.inter = LWO::IT_HERM;break;
- case AI_LWO_BEZI:
- key.inter = LWO::IT_BEZI;break;
- case AI_LWO_BEZ2:
- key.inter = LWO::IT_BEZ2;break;
- default:
- DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode");
- };
-
- // todo ... read params
- }
- break;
- }
-
- default:
- DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk");
- }
- // regardless how much we did actually read, go to the next chunk
- mFileBuffer = next;
- }
+ }
+
+ // ... and read all subchunks
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid envelope chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ // Type & representation of the envelope
+ case AI_LWO_TYPE:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2);
+ mFileBuffer++; // skip user format
+
+ // Determine type of envelope
+ envelope.type = (LWO::EnvelopeType)*mFileBuffer;
+ ++mFileBuffer;
+ break;
+
+ // precondition
+ case AI_LWO_PRE:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2);
+ envelope.pre = (LWO::PrePostBehaviour)GetU2();
+ break;
+
+ // postcondition
+ case AI_LWO_POST:
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2);
+ envelope.post = (LWO::PrePostBehaviour)GetU2();
+ break;
+
+ // keyframe
+ case AI_LWO_KEY:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8);
+
+ envelope.keys.push_back(LWO::Key());
+ LWO::Key& key = envelope.keys.back();
+
+ key.time = GetF4();
+ key.value = GetF4();
+ break;
+ }
+
+ // interval interpolation
+ case AI_LWO_SPAN:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
+ if (envelope.keys.size()<2)
+ DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
+ else {
+ LWO::Key& key = envelope.keys.back();
+ switch (GetU4())
+ {
+ case AI_LWO_STEP:
+ key.inter = LWO::IT_STEP;break;
+ case AI_LWO_LINE:
+ key.inter = LWO::IT_LINE;break;
+ case AI_LWO_TCB:
+ key.inter = LWO::IT_TCB;break;
+ case AI_LWO_HERM:
+ key.inter = LWO::IT_HERM;break;
+ case AI_LWO_BEZI:
+ key.inter = LWO::IT_BEZI;break;
+ case AI_LWO_BEZ2:
+ key.inter = LWO::IT_BEZ2;break;
+ default:
+ DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode");
+ };
+
+ // todo ... read params
+ }
+ break;
+ }
+
+ default:
+ DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk");
+ }
+ // regardless how much we did actually read, go to the next chunk
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
// Load file - master function
void LWOImporter::LoadLWO2File()
{
- bool skip = false;
-
- LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
- while (true)
- {
- if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
- IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- {
- throw DeadlyImportError("LWO2: Chunk length points behind the file");
- break;
- }
- uint8_t* const next = mFileBuffer+head->length;
- unsigned int iUnnamed = 0;
-
- if(!head->length) {
- mFileBuffer = next;
- continue;
- }
-
- switch (head->type)
- {
- // new layer
- case AI_LWO_LAYR:
- {
- // add a new layer to the list ....
- mLayers->push_back ( LWO::Layer() );
- LWO::Layer& layer = mLayers->back();
- mCurLayer = &layer;
-
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
-
- // layer index.
- layer.mIndex = GetU2();
-
- // Continue loading this layer or ignore it? Check the layer index property
- if (UINT_MAX != configLayerIndex && (configLayerIndex-1) != layer.mIndex) {
- skip = true;
- }
- else skip = false;
-
- // pivot point
- mFileBuffer += 2; /* unknown */
- mCurLayer->mPivot.x = GetF4();
- mCurLayer->mPivot.y = GetF4();
- mCurLayer->mPivot.z = GetF4();
- GetS0(layer.mName,head->length-16);
-
- // if the name is empty, generate a default name
- if (layer.mName.empty()) {
- char buffer[128]; // should be sufficiently large
- ::sprintf(buffer,"Layer_%i", iUnnamed++);
- layer.mName = buffer;
- }
-
- // load this layer or ignore it? Check the layer name property
- if (configLayerName.length() && configLayerName != layer.mName) {
- skip = true;
- }
- else hasNamedLayer = true;
-
- // optional: parent of this layer
- if (mFileBuffer + 2 <= next)
- layer.mParent = GetU2();
- else layer.mParent = -1;
-
- // Set layer skip parameter
- layer.skip = skip;
-
- break;
- }
-
- // vertex list
- case AI_LWO_PNTS:
- {
- if (skip)
- break;
-
- unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
- LoadLWOPoints(head->length);
- mCurLayer->mPointIDXOfs = old;
- break;
- }
- // vertex tags
- case AI_LWO_VMAD:
- if (mCurLayer->mFaces.empty())
- {
- DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk");
- break;
- }
- // --- intentionally no break here
- case AI_LWO_VMAP:
- {
- if (skip)
- break;
-
- if (mCurLayer->mTempPoints.empty())
- DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
- else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
- break;
- }
- // face list
- case AI_LWO_POLS:
- {
- if (skip)
- break;
-
- unsigned int old = (unsigned int)mCurLayer->mFaces.size();
- LoadLWO2Polygons(head->length);
- mCurLayer->mFaceIDXOfs = old;
- break;
- }
- // polygon tags
- case AI_LWO_PTAG:
- {
- if (skip)
- break;
-
- if (mCurLayer->mFaces.empty())
- DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
- else LoadLWO2PolygonTags(head->length);
- break;
- }
- // list of tags
- case AI_LWO_TAGS:
- {
- if (!mTags->empty())
- DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
- else LoadLWOTags(head->length);
- break;
- }
-
- // surface chunk
- case AI_LWO_SURF:
- {
- LoadLWO2Surface(head->length);
- break;
- }
-
- // clip chunk
- case AI_LWO_CLIP:
- {
- LoadLWO2Clip(head->length);
- break;
- }
-
- // envelope chunk
- case AI_LWO_ENVL:
- {
- LoadLWO2Envelope(head->length);
- break;
- }
- }
- mFileBuffer = next;
- }
+ bool skip = false;
+
+ LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
+ while (true)
+ {
+ if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
+ const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ {
+ throw DeadlyImportError("LWO2: Chunk length points behind the file");
+ break;
+ }
+ uint8_t* const next = mFileBuffer+head.length;
+ unsigned int iUnnamed = 0;
+
+ if(!head.length) {
+ mFileBuffer = next;
+ continue;
+ }
+
+ switch (head.type)
+ {
+ // new layer
+ case AI_LWO_LAYR:
+ {
+ // add a new layer to the list ....
+ mLayers->push_back ( LWO::Layer() );
+ LWO::Layer& layer = mLayers->back();
+ mCurLayer = &layer;
+
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
+
+ // layer index.
+ layer.mIndex = GetU2();
+
+ // Continue loading this layer or ignore it? Check the layer index property
+ if (UINT_MAX != configLayerIndex && (configLayerIndex-1) != layer.mIndex) {
+ skip = true;
+ }
+ else skip = false;
+
+ // pivot point
+ mFileBuffer += 2; /* unknown */
+ mCurLayer->mPivot.x = GetF4();
+ mCurLayer->mPivot.y = GetF4();
+ mCurLayer->mPivot.z = GetF4();
+ GetS0(layer.mName,head.length-16);
+
+ // if the name is empty, generate a default name
+ if (layer.mName.empty()) {
+ char buffer[128]; // should be sufficiently large
+ ::ai_snprintf(buffer, 128, "Layer_%i", iUnnamed++);
+ layer.mName = buffer;
+ }
+
+ // load this layer or ignore it? Check the layer name property
+ if (configLayerName.length() && configLayerName != layer.mName) {
+ skip = true;
+ }
+ else hasNamedLayer = true;
+
+ // optional: parent of this layer
+ if (mFileBuffer + 2 <= next)
+ layer.mParent = GetU2();
+ else layer.mParent = -1;
+
+ // Set layer skip parameter
+ layer.skip = skip;
+
+ break;
+ }
+
+ // vertex list
+ case AI_LWO_PNTS:
+ {
+ if (skip)
+ break;
+
+ unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
+ LoadLWOPoints(head.length);
+ mCurLayer->mPointIDXOfs = old;
+ break;
+ }
+ // vertex tags
+ case AI_LWO_VMAD:
+ if (mCurLayer->mFaces.empty())
+ {
+ DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk");
+ break;
+ }
+ // --- intentionally no break here
+ case AI_LWO_VMAP:
+ {
+ if (skip)
+ break;
+
+ if (mCurLayer->mTempPoints.empty())
+ DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
+ else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
+ break;
+ }
+ // face list
+ case AI_LWO_POLS:
+ {
+ if (skip)
+ break;
+
+ unsigned int old = (unsigned int)mCurLayer->mFaces.size();
+ LoadLWO2Polygons(head.length);
+ mCurLayer->mFaceIDXOfs = old;
+ break;
+ }
+ // polygon tags
+ case AI_LWO_PTAG:
+ {
+ if (skip)
+ break;
+
+ if (mCurLayer->mFaces.empty())
+ DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
+ else LoadLWO2PolygonTags(head.length);
+ break;
+ }
+ // list of tags
+ case AI_LWO_TAGS:
+ {
+ if (!mTags->empty())
+ DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
+ else LoadLWOTags(head.length);
+ break;
+ }
+
+ // surface chunk
+ case AI_LWO_SURF:
+ {
+ LoadLWO2Surface(head.length);
+ break;
+ }
+
+ // clip chunk
+ case AI_LWO_CLIP:
+ {
+ LoadLWO2Clip(head.length);
+ break;
+ }
+
+ // envelope chunk
+ case AI_LWO_ENVL:
+ {
+ LoadLWO2Envelope(head.length);
+ break;
+ }
+ }
+ mFileBuffer = next;
+ }
}
#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER
diff --git a/src/3rdparty/assimp/code/LWOLoader.h b/src/3rdparty/assimp/code/LWOLoader.h
index fc89e5f56..09d66cf24 100644
--- a/src/3rdparty/assimp/code/LWOLoader.h
+++ b/src/3rdparty/assimp/code/LWOLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,16 +42,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_LWOLOADER_H_INCLUDED
#define AI_LWOLOADER_H_INCLUDED
-#include "../include/assimp/types.h"
-#include "../include/assimp/DefaultLogger.hpp"
+#include <assimp/types.h>
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
#include "LWOFileData.h"
#include "BaseImporter.h"
struct aiTexture;
struct aiNode;
+struct aiMaterial;
-namespace Assimp {
+namespace Assimp {
using namespace LWO;
// ---------------------------------------------------------------------------
@@ -67,408 +69,414 @@ using namespace LWO;
class LWOImporter : public BaseImporter
{
public:
- LWOImporter();
- ~LWOImporter();
+ LWOImporter();
+ ~LWOImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- // Get list of supported extensions
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ // Get list of supported extensions
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- // -------------------------------------------------------------------
- /** Loads a LWO file in the older LWOB format (LW < 6)
- */
- void LoadLWOBFile();
-
- // -------------------------------------------------------------------
- /** Loads a LWO file in the newer LWO2 format (LW >= 6)
- */
- void LoadLWO2File();
-
-
- // -------------------------------------------------------------------
- /** Parsing functions used for all file format versions
- */
- inline void GetS0(std::string& out,unsigned int max);
- inline float GetF4();
- inline uint32_t GetU4();
- inline uint16_t GetU2();
- inline uint8_t GetU1();
-
-
- // -------------------------------------------------------------------
- /** Loads a surface chunk from an LWOB file
- * @param size Maximum size to be read, in bytes.
- */
- void LoadLWOBSurface(unsigned int size);
-
- // -------------------------------------------------------------------
- /** Loads a surface chunk from an LWO2 file
- * @param size Maximum size to be read, in bytes.
- */
- void LoadLWO2Surface(unsigned int size);
-
- // -------------------------------------------------------------------
- /** Loads a texture block from a LWO2 file.
- * @param size Maximum size to be read, in bytes.
- * @param head Header of the SUF.BLOK header
- */
- void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head,
- unsigned int size );
-
- // -------------------------------------------------------------------
- /** Loads a shader block from a LWO2 file.
- * @param size Maximum size to be read, in bytes.
- * @param head Header of the SUF.BLOK header
- */
- void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head,
- unsigned int size );
-
- // -------------------------------------------------------------------
- /** Loads an image map from a LWO2 file
- * @param size Maximum size to be read, in bytes.
- * @param tex Texture object to be filled
- */
- void LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex );
- void LoadLWO2Gradient(unsigned int size, LWO::Texture& tex );
- void LoadLWO2Procedural(unsigned int size, LWO::Texture& tex );
-
- // loads the header - used by thethree functions above
- void LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex );
-
- // -------------------------------------------------------------------
- /** Loads the LWO tag list from the file
- * @param size Maximum size to be read, in bytes.
- */
- void LoadLWOTags(unsigned int size);
-
- // -------------------------------------------------------------------
- /** Load polygons from a POLS chunk
- * @param length Size of the chunk
- */
- void LoadLWO2Polygons(unsigned int length);
- void LoadLWOBPolygons(unsigned int length);
-
- // -------------------------------------------------------------------
- /** Load polygon tags from a PTAG chunk
- * @param length Size of the chunk
- */
- void LoadLWO2PolygonTags(unsigned int length);
-
- // -------------------------------------------------------------------
- /** Load a vertex map from a VMAP/VMAD chunk
- * @param length Size of the chunk
- * @param perPoly Operate on per-polygon base?
- */
- void LoadLWO2VertexMap(unsigned int length, bool perPoly);
-
- // -------------------------------------------------------------------
- /** Load polygons from a PNTS chunk
- * @param length Size of the chunk
- */
- void LoadLWOPoints(unsigned int length);
-
- // -------------------------------------------------------------------
- /** Load a clip from a CLIP chunk
- * @param length Size of the chunk
- */
- void LoadLWO2Clip(unsigned int length);
-
- // -------------------------------------------------------------------
- /** Load an envelope from an EVL chunk
- * @param length Size of the chunk
- */
- void LoadLWO2Envelope(unsigned int length);
-
- // -------------------------------------------------------------------
- /** Count vertices and faces in a LWOB/LWO2 file
- */
- void CountVertsAndFacesLWO2(unsigned int& verts,
- unsigned int& faces,
- uint16_t*& cursor,
- const uint16_t* const end,
- unsigned int max = UINT_MAX);
-
- void CountVertsAndFacesLWOB(unsigned int& verts,
- unsigned int& faces,
- LE_NCONST uint16_t*& cursor,
- const uint16_t* const end,
- unsigned int max = UINT_MAX);
-
- // -------------------------------------------------------------------
- /** Read vertices and faces in a LWOB/LWO2 file
- */
- void CopyFaceIndicesLWO2(LWO::FaceList::iterator& it,
- uint16_t*& cursor,
- const uint16_t* const end);
-
- // -------------------------------------------------------------------
- void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it,
- LE_NCONST uint16_t*& cursor,
- const uint16_t* const end,
- unsigned int max = UINT_MAX);
-
- // -------------------------------------------------------------------
- /** Resolve the tag and surface lists that have been loaded.
- * Generates the mMapping table.
- */
- void ResolveTags();
-
- // -------------------------------------------------------------------
- /** Resolve the clip list that has been loaded.
- * Replaces clip references with real clips.
- */
- void ResolveClips();
-
- // -------------------------------------------------------------------
- /** Add a texture list to an output material description.
- *
- * @param pcMat Output material
- * @param in Input texture list
- * @param type Type identifier of the texture list
- */
- bool HandleTextures(aiMaterial* pcMat, const TextureList& in,
- aiTextureType type);
-
- // -------------------------------------------------------------------
- /** Adjust a texture path
- */
- void AdjustTexturePath(std::string& out);
-
- // -------------------------------------------------------------------
- /** Convert a LWO surface description to an ASSIMP material
- */
- void ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat);
-
-
- // -------------------------------------------------------------------
- /** Get a list of all UV/VC channels required by a specific surface.
- *
- * @param surf Working surface
- * @param layer Working layer
- * @param out Output list. The members are indices into the
- * UV/VC channel lists of the layer
- */
- void FindUVChannels(/*const*/ LWO::Surface& surf,
- LWO::SortedRep& sorted,
- /*const*/ LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
-
- // -------------------------------------------------------------------
- char FindUVChannels(LWO::TextureList& list,
- LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next);
-
- // -------------------------------------------------------------------
- void FindVCChannels(const LWO::Surface& surf,
- LWO::SortedRep& sorted,
- const LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
-
- // -------------------------------------------------------------------
- /** Generate the final node graph
- * Unused nodes are deleted.
- * @param apcNodes Flat list of nodes
- */
- void GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes);
-
- // -------------------------------------------------------------------
- /** Add children to a node
- * @param node Node to become a father
- * @param parent Index of the node
- * @param apcNodes Flat list of nodes - used nodes are set to NULL.
- */
- void AddChildren(aiNode* node, uint16_t parent,
- std::vector<aiNode*>& apcNodes);
-
- // -------------------------------------------------------------------
- /** Read a variable sized integer
- * @param inout Input and output buffer
- */
- int ReadVSizedIntLWO2(uint8_t*& inout);
-
- // -------------------------------------------------------------------
- /** Assign a value from a VMAP to a vertex and all vertices
- * attached to it.
- * @param base VMAP destination data
- * @param numRead Number of float's to be read
- * @param idx Absolute index of the first vertex
- * @param data Value of the VMAP to be assigned - read numRead
- * floats from this array.
- */
- void DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
- unsigned int idx, float* data);
-
- // -------------------------------------------------------------------
- /** Compute normal vectors for a mesh
- * @param mesh Input mesh
- * @param smoothingGroups Smoothing-groups-per-face array
- * @param surface Surface for the mesh
- */
- void ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
- const LWO::Surface& surface);
-
-
- // -------------------------------------------------------------------
- /** Setup a new texture after the corresponding chunk was
- * encountered in the file.
- * @param list Texture list
- * @param size Maximum number of bytes to be read
- * @return Pointer to new texture
- */
- LWO::Texture* SetupNewTextureLWOB(LWO::TextureList& list,
- unsigned int size);
+ // -------------------------------------------------------------------
+ /** Loads a LWO file in the older LWOB format (LW < 6)
+ */
+ void LoadLWOBFile();
+
+ // -------------------------------------------------------------------
+ /** Loads a LWO file in the newer LWO2 format (LW >= 6)
+ */
+ void LoadLWO2File();
+
+
+ // -------------------------------------------------------------------
+ /** Parsing functions used for all file format versions
+ */
+ inline void GetS0(std::string& out,unsigned int max);
+ inline float GetF4();
+ inline uint32_t GetU4();
+ inline uint16_t GetU2();
+ inline uint8_t GetU1();
+
+
+ // -------------------------------------------------------------------
+ /** Loads a surface chunk from an LWOB file
+ * @param size Maximum size to be read, in bytes.
+ */
+ void LoadLWOBSurface(unsigned int size);
+
+ // -------------------------------------------------------------------
+ /** Loads a surface chunk from an LWO2 file
+ * @param size Maximum size to be read, in bytes.
+ */
+ void LoadLWO2Surface(unsigned int size);
+
+ // -------------------------------------------------------------------
+ /** Loads a texture block from a LWO2 file.
+ * @param size Maximum size to be read, in bytes.
+ * @param head Header of the SUF.BLOK header
+ */
+ void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head,
+ unsigned int size );
+
+ // -------------------------------------------------------------------
+ /** Loads a shader block from a LWO2 file.
+ * @param size Maximum size to be read, in bytes.
+ * @param head Header of the SUF.BLOK header
+ */
+ void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head,
+ unsigned int size );
+
+ // -------------------------------------------------------------------
+ /** Loads an image map from a LWO2 file
+ * @param size Maximum size to be read, in bytes.
+ * @param tex Texture object to be filled
+ */
+ void LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex );
+ void LoadLWO2Gradient(unsigned int size, LWO::Texture& tex );
+ void LoadLWO2Procedural(unsigned int size, LWO::Texture& tex );
+
+ // loads the header - used by thethree functions above
+ void LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex );
+
+ // -------------------------------------------------------------------
+ /** Loads the LWO tag list from the file
+ * @param size Maximum size to be read, in bytes.
+ */
+ void LoadLWOTags(unsigned int size);
+
+ // -------------------------------------------------------------------
+ /** Load polygons from a POLS chunk
+ * @param length Size of the chunk
+ */
+ void LoadLWO2Polygons(unsigned int length);
+ void LoadLWOBPolygons(unsigned int length);
+
+ // -------------------------------------------------------------------
+ /** Load polygon tags from a PTAG chunk
+ * @param length Size of the chunk
+ */
+ void LoadLWO2PolygonTags(unsigned int length);
+
+ // -------------------------------------------------------------------
+ /** Load a vertex map from a VMAP/VMAD chunk
+ * @param length Size of the chunk
+ * @param perPoly Operate on per-polygon base?
+ */
+ void LoadLWO2VertexMap(unsigned int length, bool perPoly);
+
+ // -------------------------------------------------------------------
+ /** Load polygons from a PNTS chunk
+ * @param length Size of the chunk
+ */
+ void LoadLWOPoints(unsigned int length);
+
+ // -------------------------------------------------------------------
+ /** Load a clip from a CLIP chunk
+ * @param length Size of the chunk
+ */
+ void LoadLWO2Clip(unsigned int length);
+
+ // -------------------------------------------------------------------
+ /** Load an envelope from an EVL chunk
+ * @param length Size of the chunk
+ */
+ void LoadLWO2Envelope(unsigned int length);
+
+ // -------------------------------------------------------------------
+ /** Count vertices and faces in a LWOB/LWO2 file
+ */
+ void CountVertsAndFacesLWO2(unsigned int& verts,
+ unsigned int& faces,
+ uint16_t*& cursor,
+ const uint16_t* const end,
+ unsigned int max = UINT_MAX);
+
+ void CountVertsAndFacesLWOB(unsigned int& verts,
+ unsigned int& faces,
+ LE_NCONST uint16_t*& cursor,
+ const uint16_t* const end,
+ unsigned int max = UINT_MAX);
+
+ // -------------------------------------------------------------------
+ /** Read vertices and faces in a LWOB/LWO2 file
+ */
+ void CopyFaceIndicesLWO2(LWO::FaceList::iterator& it,
+ uint16_t*& cursor,
+ const uint16_t* const end);
+
+ // -------------------------------------------------------------------
+ void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it,
+ LE_NCONST uint16_t*& cursor,
+ const uint16_t* const end,
+ unsigned int max = UINT_MAX);
+
+ // -------------------------------------------------------------------
+ /** Resolve the tag and surface lists that have been loaded.
+ * Generates the mMapping table.
+ */
+ void ResolveTags();
+
+ // -------------------------------------------------------------------
+ /** Resolve the clip list that has been loaded.
+ * Replaces clip references with real clips.
+ */
+ void ResolveClips();
+
+ // -------------------------------------------------------------------
+ /** Add a texture list to an output material description.
+ *
+ * @param pcMat Output material
+ * @param in Input texture list
+ * @param type Type identifier of the texture list
+ */
+ bool HandleTextures(aiMaterial* pcMat, const TextureList& in,
+ aiTextureType type);
+
+ // -------------------------------------------------------------------
+ /** Adjust a texture path
+ */
+ void AdjustTexturePath(std::string& out);
+
+ // -------------------------------------------------------------------
+ /** Convert a LWO surface description to an ASSIMP material
+ */
+ void ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat);
+
+
+ // -------------------------------------------------------------------
+ /** Get a list of all UV/VC channels required by a specific surface.
+ *
+ * @param surf Working surface
+ * @param layer Working layer
+ * @param out Output list. The members are indices into the
+ * UV/VC channel lists of the layer
+ */
+ void FindUVChannels(/*const*/ LWO::Surface& surf,
+ LWO::SortedRep& sorted,
+ /*const*/ LWO::Layer& layer,
+ unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
+
+ // -------------------------------------------------------------------
+ char FindUVChannels(LWO::TextureList& list,
+ LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next);
+
+ // -------------------------------------------------------------------
+ void FindVCChannels(const LWO::Surface& surf,
+ LWO::SortedRep& sorted,
+ const LWO::Layer& layer,
+ unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
+
+ // -------------------------------------------------------------------
+ /** Generate the final node graph
+ * Unused nodes are deleted.
+ * @param apcNodes Flat list of nodes
+ */
+ void GenerateNodeGraph(std::map<uint16_t,aiNode*>& apcNodes);
+
+ // -------------------------------------------------------------------
+ /** Add children to a node
+ * @param node Node to become a father
+ * @param parent Index of the node
+ * @param apcNodes Flat list of nodes - used nodes are set to NULL.
+ */
+ void AddChildren(aiNode* node, uint16_t parent,
+ std::vector<aiNode*>& apcNodes);
+
+ // -------------------------------------------------------------------
+ /** Read a variable sized integer
+ * @param inout Input and output buffer
+ */
+ int ReadVSizedIntLWO2(uint8_t*& inout);
+
+ // -------------------------------------------------------------------
+ /** Assign a value from a VMAP to a vertex and all vertices
+ * attached to it.
+ * @param base VMAP destination data
+ * @param numRead Number of float's to be read
+ * @param idx Absolute index of the first vertex
+ * @param data Value of the VMAP to be assigned - read numRead
+ * floats from this array.
+ */
+ void DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
+ unsigned int idx, float* data);
+
+ // -------------------------------------------------------------------
+ /** Compute normal vectors for a mesh
+ * @param mesh Input mesh
+ * @param smoothingGroups Smoothing-groups-per-face array
+ * @param surface Surface for the mesh
+ */
+ void ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
+ const LWO::Surface& surface);
+
+
+ // -------------------------------------------------------------------
+ /** Setup a new texture after the corresponding chunk was
+ * encountered in the file.
+ * @param list Texture list
+ * @param size Maximum number of bytes to be read
+ * @return Pointer to new texture
+ */
+ LWO::Texture* SetupNewTextureLWOB(LWO::TextureList& list,
+ unsigned int size);
protected:
- /** true if the file is a LWO2 file*/
- bool mIsLWO2;
+ /** true if the file is a LWO2 file*/
+ bool mIsLWO2;
- /** true if the file is a LXOB file*/
- bool mIsLXOB;
+ /** true if the file is a LXOB file*/
+ bool mIsLXOB;
- /** Temporary list of layers from the file */
- LayerList* mLayers;
+ /** Temporary list of layers from the file */
+ LayerList* mLayers;
- /** Pointer to the current layer */
- LWO::Layer* mCurLayer;
+ /** Pointer to the current layer */
+ LWO::Layer* mCurLayer;
- /** Temporary tag list from the file */
- TagList* mTags;
+ /** Temporary tag list from the file */
+ TagList* mTags;
- /** Mapping table to convert from tag to surface indices.
- UINT_MAX indicates that a no corresponding surface is available */
- TagMappingTable* mMapping;
+ /** Mapping table to convert from tag to surface indices.
+ UINT_MAX indicates that a no corresponding surface is available */
+ TagMappingTable* mMapping;
- /** Temporary surface list from the file */
- SurfaceList* mSurfaces;
+ /** Temporary surface list from the file */
+ SurfaceList* mSurfaces;
- /** Temporary clip list from the file */
- ClipList mClips;
+ /** Temporary clip list from the file */
+ ClipList mClips;
- /** Temporary envelope list from the file */
- EnvelopeList mEnvelopes;
+ /** Temporary envelope list from the file */
+ EnvelopeList mEnvelopes;
- /** file buffer */
- uint8_t* mFileBuffer;
+ /** file buffer */
+ uint8_t* mFileBuffer;
- /** Size of the file, in bytes */
- unsigned int fileSize;
+ /** Size of the file, in bytes */
+ unsigned int fileSize;
- /** Output scene */
- aiScene* pScene;
+ /** Output scene */
+ aiScene* pScene;
- /** Configuration option: speed flag set? */
- bool configSpeedFlag;
+ /** Configuration option: speed flag set? */
+ bool configSpeedFlag;
- /** Configuration option: index of layer to be loaded */
- unsigned int configLayerIndex;
+ /** Configuration option: index of layer to be loaded */
+ unsigned int configLayerIndex;
- /** Configuration option: name of layer to be loaded */
- std::string configLayerName;
+ /** Configuration option: name of layer to be loaded */
+ std::string configLayerName;
- /** True if we have a named layer */
- bool hasNamedLayer;
+ /** True if we have a named layer */
+ bool hasNamedLayer;
};
// ------------------------------------------------------------------------------------------------
inline float LWOImporter::GetF4()
{
- float f = *((float*)mFileBuffer);mFileBuffer += 4;
- AI_LSWAP4(f);
- return f;
+ float f;
+ ::memcpy(&f, mFileBuffer, 4);
+ mFileBuffer += 4;
+ AI_LSWAP4(f);
+ return f;
}
// ------------------------------------------------------------------------------------------------
inline uint32_t LWOImporter::GetU4()
{
- uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4;
- AI_LSWAP4(f);
- return f;
+ uint32_t f;
+ ::memcpy(&f, mFileBuffer, 4);
+ mFileBuffer += 4;
+ AI_LSWAP4(f);
+ return f;
}
// ------------------------------------------------------------------------------------------------
inline uint16_t LWOImporter::GetU2()
{
- uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2;
- AI_LSWAP2(f);
- return f;
+ uint16_t f;
+ ::memcpy(&f, mFileBuffer, 2);
+ mFileBuffer += 2;
+ AI_LSWAP2(f);
+ return f;
}
// ------------------------------------------------------------------------------------------------
inline uint8_t LWOImporter::GetU1()
{
- return *mFileBuffer++;
+ return *mFileBuffer++;
}
// ------------------------------------------------------------------------------------------------
inline int LWOImporter::ReadVSizedIntLWO2(uint8_t*& inout)
{
- int i;
- int c = *inout;inout++;
- if(c != 0xFF)
- {
- i = c << 8;
- c = *inout;inout++;
- i |= c;
- }
- else
- {
- c = *inout;inout++;
- i = c << 16;
- c = *inout;inout++;
- i |= c << 8;
- c = *inout;inout++;
- i |= c;
- }
- return i;
+ int i;
+ int c = *inout;inout++;
+ if(c != 0xFF)
+ {
+ i = c << 8;
+ c = *inout;inout++;
+ i |= c;
+ }
+ else
+ {
+ c = *inout;inout++;
+ i = c << 16;
+ c = *inout;inout++;
+ i |= c << 8;
+ c = *inout;inout++;
+ i |= c;
+ }
+ return i;
}
// ------------------------------------------------------------------------------------------------
inline void LWOImporter::GetS0(std::string& out,unsigned int max)
{
- unsigned int iCursor = 0;
- const char*sz = (const char*)mFileBuffer;
- while (*mFileBuffer)
- {
- if (++iCursor > max)
- {
- DefaultLogger::get()->warn("LWO: Invalid file, string is is too long");
- break;
- }
- ++mFileBuffer;
- }
- size_t len = (size_t) ((const char*)mFileBuffer-sz);
- out = std::string(sz,len);
- mFileBuffer += (len&0x1 ? 1 : 2);
+ unsigned int iCursor = 0;
+ const char*sz = (const char*)mFileBuffer;
+ while (*mFileBuffer)
+ {
+ if (++iCursor > max)
+ {
+ DefaultLogger::get()->warn("LWO: Invalid file, string is is too long");
+ break;
+ }
+ ++mFileBuffer;
+ }
+ size_t len = (size_t) ((const char*)mFileBuffer-sz);
+ out = std::string(sz,len);
+ mFileBuffer += (len&0x1 ? 1 : 2);
}
diff --git a/src/3rdparty/assimp/code/LWOMaterial.cpp b/src/3rdparty/assimp/code/LWOMaterial.cpp
index 70da0d675..24a2458cf 100644
--- a/src/3rdparty/assimp/code/LWOMaterial.cpp
+++ b/src/3rdparty/assimp/code/LWOMaterial.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -42,12 +42,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the material oart of the LWO importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
// internal headers
#include "LWOLoader.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
+
using namespace Assimp;
@@ -55,844 +56,842 @@ using namespace Assimp;
template <class T>
T lerp(const T& one, const T& two, float val)
{
- return one + (two-one)*val;
+ return one + (two-one)*val;
}
// ------------------------------------------------------------------------------------------------
// Convert a lightwave mapping mode to our's
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
{
- switch (in)
- {
- case LWO::Texture::REPEAT:
- return aiTextureMapMode_Wrap;
-
- case LWO::Texture::MIRROR:
- return aiTextureMapMode_Mirror;
-
- case LWO::Texture::RESET:
- DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
-
- // fall though here
- case LWO::Texture::EDGE:
- return aiTextureMapMode_Clamp;
- }
- return (aiTextureMapMode)0;
+ switch (in)
+ {
+ case LWO::Texture::REPEAT:
+ return aiTextureMapMode_Wrap;
+
+ case LWO::Texture::MIRROR:
+ return aiTextureMapMode_Mirror;
+
+ case LWO::Texture::RESET:
+ DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
+
+ // fall though here
+ case LWO::Texture::EDGE:
+ return aiTextureMapMode_Clamp;
+ }
+ return (aiTextureMapMode)0;
}
// ------------------------------------------------------------------------------------------------
bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type)
{
- ai_assert(NULL != pcMat);
-
- unsigned int cur = 0, temp = 0;
- aiString s;
- bool ret = false;
-
- for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) {
- if (!(*it).enabled || !(*it).bCanUse)
- continue;
- ret = true;
-
- // Convert lightwave's mapping modes to ours. We let them
- // as they are, the GenUVcoords step will compute UV
- // channels if they're not there.
-
- aiTextureMapping mapping;
- switch ((*it).mapMode)
- {
- case LWO::Texture::Planar:
- mapping = aiTextureMapping_PLANE;
- break;
- case LWO::Texture::Cylindrical:
- mapping = aiTextureMapping_CYLINDER;
- break;
- case LWO::Texture::Spherical:
- mapping = aiTextureMapping_SPHERE;
- break;
- case LWO::Texture::Cubic:
- mapping = aiTextureMapping_BOX;
- break;
- case LWO::Texture::FrontProjection:
- DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
- mapping = aiTextureMapping_OTHER;
- break;
- case LWO::Texture::UV:
- {
- if( UINT_MAX == (*it).mRealUVIndex ) {
- // We have no UV index for this texture, so we can't display it
- continue;
- }
-
- // add the UV source index
- temp = (*it).mRealUVIndex;
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
-
- mapping = aiTextureMapping_UV;
- }
- break;
- default:
- ai_assert(false);
- };
-
- if (mapping != aiTextureMapping_UV) {
- // Setup the main axis
- aiVector3D v;
- switch ((*it).majorAxis) {
- case Texture::AXIS_X:
- v = aiVector3D(1.f,0.f,0.f);
- break;
- case Texture::AXIS_Y:
- v = aiVector3D(0.f,1.f,0.f);
- break;
- default: // case Texture::AXIS_Z:
- v = aiVector3D(0.f,0.f,1.f);
- break;
- }
-
- pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
-
- // Setup UV scalings for cylindric and spherical projections
- if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
- aiUVTransform trafo;
- trafo.mScaling.x = (*it).wrapAmountW;
- trafo.mScaling.y = (*it).wrapAmountH;
-
- BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5);
- pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
- }
- DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
- }
-
- // The older LWOB format does not use indirect references to clips.
- // The file name of a texture is directly specified in the tex chunk.
- if (mIsLWO2) {
- // find the corresponding clip (take the last one if multiple
- // share the same index)
- ClipList::iterator end = mClips.end(), candidate = end;
- temp = (*it).mClipIdx;
- for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
- if ((*clip).idx == temp) {
- candidate = clip;
- }
-
- }
- if (candidate == end) {
- DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
- temp = 0;
-
- // fixme: apparently some LWO files shipping with Doom3 don't
- // have clips at all ... check whether that's true or whether
- // it's a bug in the loader.
-
- s.Set("$texture.png");
-
- //continue;
- }
- else {
- if (Clip::UNSUPPORTED == (*candidate).type) {
- DefaultLogger::get()->error("LWO2: Clip type is not supported");
- continue;
- }
- AdjustTexturePath((*candidate).path);
- s.Set((*candidate).path);
-
- // Additional image settings
- int flags = 0;
- if ((*candidate).negate) {
- flags |= aiTextureFlags_Invert;
- }
- pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
- }
- }
- else
- {
- std::string ss = (*it).mFileName;
- if (!ss.length()) {
- DefaultLogger::get()->error("LWOB: Empty file name");
- continue;
- }
- AdjustTexturePath(ss);
- s.Set(ss);
- }
- pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
-
- // add the blend factor
- pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
-
- // add the blend operation
- switch ((*it).blendType)
- {
- case LWO::Texture::Normal:
- case LWO::Texture::Multiply:
- temp = (unsigned int)aiTextureOp_Multiply;
- break;
-
- case LWO::Texture::Subtractive:
- case LWO::Texture::Difference:
- temp = (unsigned int)aiTextureOp_Subtract;
- break;
-
- case LWO::Texture::Divide:
- temp = (unsigned int)aiTextureOp_Divide;
- break;
-
- case LWO::Texture::Additive:
- temp = (unsigned int)aiTextureOp_Add;
- break;
-
- default:
- temp = (unsigned int)aiTextureOp_Multiply;
- DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
-
- }
- // Setup texture operation
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
-
- // setup the mapping mode
- pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
-
- // add the u-wrapping
- temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
-
- // add the v-wrapping
- temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
-
- ++cur;
- }
- return ret;
+ ai_assert(NULL != pcMat);
+
+ unsigned int cur = 0, temp = 0;
+ aiString s;
+ bool ret = false;
+
+ for (const auto &texture : in) {
+ if (!texture.enabled || !texture.bCanUse)
+ continue;
+ ret = true;
+
+ // Convert lightwave's mapping modes to ours. We let them
+ // as they are, the GenUVcoords step will compute UV
+ // channels if they're not there.
+
+ aiTextureMapping mapping;
+ switch (texture.mapMode)
+ {
+ case LWO::Texture::Planar:
+ mapping = aiTextureMapping_PLANE;
+ break;
+ case LWO::Texture::Cylindrical:
+ mapping = aiTextureMapping_CYLINDER;
+ break;
+ case LWO::Texture::Spherical:
+ mapping = aiTextureMapping_SPHERE;
+ break;
+ case LWO::Texture::Cubic:
+ mapping = aiTextureMapping_BOX;
+ break;
+ case LWO::Texture::FrontProjection:
+ DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
+ mapping = aiTextureMapping_OTHER;
+ break;
+ case LWO::Texture::UV:
+ {
+ if( UINT_MAX == texture.mRealUVIndex ) {
+ // We have no UV index for this texture, so we can't display it
+ continue;
+ }
+
+ // add the UV source index
+ temp = texture.mRealUVIndex;
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
+
+ mapping = aiTextureMapping_UV;
+ }
+ break;
+ default:
+ ai_assert(false);
+ };
+
+ if (mapping != aiTextureMapping_UV) {
+ // Setup the main axis
+ aiVector3D v;
+ switch (texture.majorAxis) {
+ case Texture::AXIS_X:
+ v = aiVector3D(1.f,0.f,0.f);
+ break;
+ case Texture::AXIS_Y:
+ v = aiVector3D(0.f,1.f,0.f);
+ break;
+ default: // case Texture::AXIS_Z:
+ v = aiVector3D(0.f,0.f,1.f);
+ break;
+ }
+
+ pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
+
+ // Setup UV scalings for cylindric and spherical projections
+ if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
+ aiUVTransform trafo;
+ trafo.mScaling.x = texture.wrapAmountW;
+ trafo.mScaling.y = texture.wrapAmountH;
+
+ static_assert(sizeof(aiUVTransform)/sizeof(float) == 5, "sizeof(aiUVTransform)/sizeof(float) == 5");
+ pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
+ }
+ DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
+ }
+
+ // The older LWOB format does not use indirect references to clips.
+ // The file name of a texture is directly specified in the tex chunk.
+ if (mIsLWO2) {
+ // find the corresponding clip (take the last one if multiple
+ // share the same index)
+ ClipList::iterator end = mClips.end(), candidate = end;
+ temp = texture.mClipIdx;
+ for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
+ if ((*clip).idx == temp) {
+ candidate = clip;
+ }
+
+ }
+ if (candidate == end) {
+ DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
+ temp = 0;
+
+ // fixme: apparently some LWO files shipping with Doom3 don't
+ // have clips at all ... check whether that's true or whether
+ // it's a bug in the loader.
+
+ s.Set("$texture.png");
+
+ //continue;
+ }
+ else {
+ if (Clip::UNSUPPORTED == (*candidate).type) {
+ DefaultLogger::get()->error("LWO2: Clip type is not supported");
+ continue;
+ }
+ AdjustTexturePath((*candidate).path);
+ s.Set((*candidate).path);
+
+ // Additional image settings
+ int flags = 0;
+ if ((*candidate).negate) {
+ flags |= aiTextureFlags_Invert;
+ }
+ pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
+ }
+ }
+ else
+ {
+ std::string ss = texture.mFileName;
+ if (!ss.length()) {
+ DefaultLogger::get()->error("LWOB: Empty file name");
+ continue;
+ }
+ AdjustTexturePath(ss);
+ s.Set(ss);
+ }
+ pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
+
+ // add the blend factor
+ pcMat->AddProperty<float>(&texture.mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
+
+ // add the blend operation
+ switch (texture.blendType)
+ {
+ case LWO::Texture::Normal:
+ case LWO::Texture::Multiply:
+ temp = (unsigned int)aiTextureOp_Multiply;
+ break;
+
+ case LWO::Texture::Subtractive:
+ case LWO::Texture::Difference:
+ temp = (unsigned int)aiTextureOp_Subtract;
+ break;
+
+ case LWO::Texture::Divide:
+ temp = (unsigned int)aiTextureOp_Divide;
+ break;
+
+ case LWO::Texture::Additive:
+ temp = (unsigned int)aiTextureOp_Add;
+ break;
+
+ default:
+ temp = (unsigned int)aiTextureOp_Multiply;
+ DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
+
+ }
+ // Setup texture operation
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
+
+ // setup the mapping mode
+ pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
+
+ // add the u-wrapping
+ temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
+
+ // add the v-wrapping
+ temp = (unsigned int)GetMapMode(texture.wrapModeHeight);
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
+
+ ++cur;
+ }
+ return ret;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
{
- // copy the name of the surface
- aiString st;
- st.Set(surf.mName);
- pcMat->AddProperty(&st,AI_MATKEY_NAME);
-
- const int i = surf.bDoubleSided ? 1 : 0;
- pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
-
- // add the refraction index and the bump intensity
- pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
- pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
-
- aiShadingMode m;
- if (surf.mSpecularValue && surf.mGlossiness)
- {
- float fGloss;
- if (mIsLWO2) {
- fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
- }
- else
- {
- if (16.0f >= surf.mGlossiness)
- fGloss = 6.0f;
- else if (64.0f >= surf.mGlossiness)
- fGloss = 20.0f;
- else if (256.0f >= surf.mGlossiness)
- fGloss = 50.0f;
- else fGloss = 80.0f;
- }
-
- pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
- pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
- m = aiShadingMode_Phong;
- }
- else m = aiShadingMode_Gouraud;
-
- // specular color
- aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
- pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
- pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
-
- // emissive color
- // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
- clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
-
- // opacity ... either additive or default-blended, please
- if (0.f != surf.mAdditiveTransparency) {
-
- const int add = aiBlendMode_Additive;
- pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
- }
-
- else if (10e10f != surf.mTransparency) {
- const int def = aiBlendMode_Default;
- const float f = 1.0f-surf.mTransparency;
- pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
- }
-
-
- // ADD TEXTURES to the material
- // TODO: find out how we can handle COLOR textures correctly...
- bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
- b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
- HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
- HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
- HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
- HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
- HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
-
- // Now we need to know which shader to use .. iterate through the shader list of
- // the surface and search for a name which we know ...
- for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it) {
- //if (!(*it).enabled)continue;
-
- if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader") {
- DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
-
- m = aiShadingMode_Toon;
- break;
- }
- else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel") {
- DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
-
- m = aiShadingMode_Fresnel;
- break;
- }
- else
- {
- DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName);
- }
- }
- if (surf.mMaximumSmoothAngle <= 0.0f)
- m = aiShadingMode_Flat;
- pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
-
- // (the diffuse value is just a scaling factor)
- // If a diffuse texture is set, we set this value to 1.0
- clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
- clr.r *= surf.mDiffuseValue;
- clr.g *= surf.mDiffuseValue;
- clr.b *= surf.mDiffuseValue;
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ // copy the name of the surface
+ aiString st;
+ st.Set(surf.mName);
+ pcMat->AddProperty(&st,AI_MATKEY_NAME);
+
+ const int i = surf.bDoubleSided ? 1 : 0;
+ pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
+
+ // add the refraction index and the bump intensity
+ pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
+ pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
+
+ aiShadingMode m;
+ if (surf.mSpecularValue && surf.mGlossiness)
+ {
+ float fGloss;
+ if (mIsLWO2) {
+ fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
+ }
+ else
+ {
+ if (16.0f >= surf.mGlossiness)
+ fGloss = 6.0f;
+ else if (64.0f >= surf.mGlossiness)
+ fGloss = 20.0f;
+ else if (256.0f >= surf.mGlossiness)
+ fGloss = 50.0f;
+ else fGloss = 80.0f;
+ }
+
+ pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
+ pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
+ m = aiShadingMode_Phong;
+ }
+ else m = aiShadingMode_Gouraud;
+
+ // specular color
+ aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
+ pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
+ pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
+
+ // emissive color
+ // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
+ clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
+ pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
+
+ // opacity ... either additive or default-blended, please
+ if (0.f != surf.mAdditiveTransparency) {
+
+ const int add = aiBlendMode_Additive;
+ pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
+ }
+
+ else if (10e10f != surf.mTransparency) {
+ const int def = aiBlendMode_Default;
+ const float f = 1.0f-surf.mTransparency;
+ pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
+ }
+
+
+ // ADD TEXTURES to the material
+ // TODO: find out how we can handle COLOR textures correctly...
+ bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
+ b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
+ HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
+ HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
+ HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
+ HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
+ HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
+
+ // Now we need to know which shader to use .. iterate through the shader list of
+ // the surface and search for a name which we know ...
+ for (const auto &shader : surf.mShaders) {
+ if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") {
+ DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
+
+ m = aiShadingMode_Toon;
+ break;
+ }
+ else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
+ DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
+
+ m = aiShadingMode_Fresnel;
+ break;
+ }
+ else
+ {
+ DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + shader.functionName);
+ }
+ }
+ if (surf.mMaximumSmoothAngle <= 0.0f)
+ m = aiShadingMode_Flat;
+ pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
+
+ // (the diffuse value is just a scaling factor)
+ // If a diffuse texture is set, we set this value to 1.0
+ clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
+ clr.r *= surf.mDiffuseValue;
+ clr.g *= surf.mDiffuseValue;
+ clr.b *= surf.mDiffuseValue;
+ pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
}
// ------------------------------------------------------------------------------------------------
char LWOImporter::FindUVChannels(LWO::TextureList& list,
- LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
+ LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
{
- char ret = 0;
- for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it) {
-
- // Ignore textures with non-UV mappings for the moment.
- if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV) {
- continue;
- }
-
- if ((*it).mUVChannelIndex == uv.name) {
- ret = 1;
-
- // got it.
- if ((*it).mRealUVIndex == UINT_MAX || (*it).mRealUVIndex == next)
- {
- (*it).mRealUVIndex = next;
- }
- else {
- // channel mismatch. need to duplicate the material.
- DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
-
- // TODO
- }
- }
- }
- return ret;
+ char ret = 0;
+ for (auto &texture : list) {
+
+ // Ignore textures with non-UV mappings for the moment.
+ if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) {
+ continue;
+ }
+
+ if (texture.mUVChannelIndex == uv.name) {
+ ret = 1;
+
+ // got it.
+ if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next)
+ {
+ texture.mRealUVIndex = next;
+ }
+ else {
+ // channel mismatch. need to duplicate the material.
+ DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
+
+ // TODO
+ }
+ }
+ }
+ return ret;
}
// ------------------------------------------------------------------------------------------------
-void LWOImporter::FindUVChannels(LWO::Surface& surf,
- LWO::SortedRep& sorted,LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
+void LWOImporter::FindUVChannels(LWO::Surface& surf,
+ LWO::SortedRep& sorted,LWO::Layer& layer,
+ unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
{
- unsigned int next = 0, extra = 0, num_extra = 0;
-
- // Check whether we have an UV entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
- LWO::UVChannel& uv = layer.mUVChannels[i];
-
- for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
-
- LWO::Face& face = layer.mFaces[*it];
-
- for (unsigned int n = 0; n < face.mNumIndices; ++n) {
- unsigned int idx = face.mIndices[n];
-
- if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
-
- if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
-
- DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
- "this mesh reached. Skipping channel \'" + uv.name + "\'");
-
- }
- else {
- // Search through all textures assigned to 'surf' and look for this UV channel
- char had = 0;
- had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
- had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
- had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
- had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
- had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
- had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
- had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
-
- // We have a texture referencing this UV channel so we have to take special care
- // and are willing to drop unreferenced channels in favour of it.
- if (had != 0) {
- if (num_extra) {
-
- for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
- out[a+1] = out[a];
- }
- }
- ++extra;
- out[next++] = i;
- }
- // Bäh ... seems not to be used at all. Push to end if enough space is available.
- else {
- out[extra++] = i;
- ++num_extra;
- }
- }
- it = sorted.end()-1;
- break;
- }
- }
- }
- }
- if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
- out[extra] = UINT_MAX;
- }
+ unsigned int next = 0, extra = 0, num_extra = 0;
+
+ // Check whether we have an UV entry != 0 for one of the faces in 'sorted'
+ for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
+ LWO::UVChannel& uv = layer.mUVChannels[i];
+
+ for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
+
+ LWO::Face& face = layer.mFaces[*it];
+
+ for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+ unsigned int idx = face.mIndices[n];
+
+ if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
+
+ if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+
+ DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
+ "this mesh reached. Skipping channel \'" + uv.name + "\'");
+
+ }
+ else {
+ // Search through all textures assigned to 'surf' and look for this UV channel
+ char had = 0;
+ had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
+
+ // We have a texture referencing this UV channel so we have to take special care
+ // and are willing to drop unreferenced channels in favour of it.
+ if (had != 0) {
+ if (num_extra) {
+
+ for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
+ out[a+1] = out[a];
+ }
+ }
+ ++extra;
+ out[next++] = i;
+ }
+ // B�h ... seems not to be used at all. Push to end if enough space is available.
+ else {
+ out[extra++] = i;
+ ++num_extra;
+ }
+ }
+ it = sorted.end()-1;
+ break;
+ }
+ }
+ }
+ }
+ if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+ out[extra] = UINT_MAX;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
+ unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
{
- unsigned int next = 0;
-
- // Check whether we have an vc entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
- const LWO::VColorChannel& vc = layer.mVColorChannels[i];
-
- if (surf.mVCMap == vc.name) {
- // The vertex color map is explicitely requested by the surface so we need to take special care of it
- for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
- out[a+1] = out[a];
- }
- out[0] = i;
- ++next;
- }
- else {
-
- for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
- const LWO::Face& face = layer.mFaces[*it];
-
- for (unsigned int n = 0; n < face.mNumIndices; ++n) {
- unsigned int idx = face.mIndices[n];
-
- if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
- if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
-
- DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
- "this mesh reached. Skipping channel \'" + vc.name + "\'");
-
- }
- else {
- out[next++] = i;
- }
- it = sorted.end()-1;
- break;
- }
- }
- }
- }
- }
- if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
- out[next] = UINT_MAX;
- }
+ unsigned int next = 0;
+
+ // Check whether we have an vc entry != 0 for one of the faces in 'sorted'
+ for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
+ const LWO::VColorChannel& vc = layer.mVColorChannels[i];
+
+ if (surf.mVCMap == vc.name) {
+ // The vertex color map is explicitely requested by the surface so we need to take special care of it
+ for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
+ out[a+1] = out[a];
+ }
+ out[0] = i;
+ ++next;
+ }
+ else {
+
+ for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
+ const LWO::Face& face = layer.mFaces[*it];
+
+ for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+ unsigned int idx = face.mIndices[n];
+
+ if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
+ if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
+
+ DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
+ "this mesh reached. Skipping channel \'" + vc.name + "\'");
+
+ }
+ else {
+ out[next++] = i;
+ }
+ it = sorted.end()-1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
+ out[next] = UINT_MAX;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_PROJ:
- tex.mapMode = (Texture::MappingMode)GetU2();
- break;
- case AI_LWO_WRAP:
- tex.wrapModeWidth = (Texture::Wrap)GetU2();
- tex.wrapModeHeight = (Texture::Wrap)GetU2();
- break;
- case AI_LWO_AXIS:
- tex.majorAxis = (Texture::Axes)GetU2();
- break;
- case AI_LWO_IMAG:
- tex.mClipIdx = GetU2();
- break;
- case AI_LWO_VMAP:
- GetS0(tex.mUVChannelIndex,head->length);
- break;
- case AI_LWO_WRPH:
- tex.wrapAmountH = GetF4();
- break;
- case AI_LWO_WRPW:
- tex.wrapAmountW = GetF4();
- break;
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_PROJ:
+ tex.mapMode = (Texture::MappingMode)GetU2();
+ break;
+ case AI_LWO_WRAP:
+ tex.wrapModeWidth = (Texture::Wrap)GetU2();
+ tex.wrapModeHeight = (Texture::Wrap)GetU2();
+ break;
+ case AI_LWO_AXIS:
+ tex.majorAxis = (Texture::Axes)GetU2();
+ break;
+ case AI_LWO_IMAG:
+ tex.mClipIdx = GetU2();
+ break;
+ case AI_LWO_VMAP:
+ GetS0(tex.mUVChannelIndex,head.length);
+ break;
+ case AI_LWO_WRPH:
+ tex.wrapAmountH = GetF4();
+ break;
+ case AI_LWO_WRPW:
+ tex.wrapAmountW = GetF4();
+ break;
+ }
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
{
- // --- not supported at the moment
- DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
- tex.bCanUse = false;
+ // --- not supported at the moment
+ DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
+ tex.bCanUse = false;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex )
{
- // --- not supported at the moment
- DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
- tex.bCanUse = false;
+ // --- not supported at the moment
+ DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
+ tex.bCanUse = false;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- // get the ordinal string
- GetS0( tex.ordinal, size);
-
- // we could crash later if this is an empty string ...
- if (!tex.ordinal.length())
- {
- DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
- tex.ordinal = "\x00";
- }
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid texture header chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_CHAN:
- tex.type = GetU4();
- break;
- case AI_LWO_ENAB:
- tex.enabled = GetU2() ? true : false;
- break;
- case AI_LWO_OPAC:
- tex.blendType = (Texture::BlendType)GetU2();
- tex.mStrength = GetF4();
- break;
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ // get the ordinal string
+ GetS0( tex.ordinal, size);
+
+ // we could crash later if this is an empty string ...
+ if (!tex.ordinal.length())
+ {
+ DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+ tex.ordinal = "\x00";
+ }
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid texture header chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_CHAN:
+ tex.type = GetU4();
+ break;
+ case AI_LWO_ENAB:
+ tex.enabled = GetU2() ? true : false;
+ break;
+ case AI_LWO_OPAC:
+ tex.blendType = (Texture::BlendType)GetU2();
+ tex.mStrength = GetF4();
+ break;
+ }
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
{
- ai_assert(!mSurfaces->empty());
- LWO::Surface& surf = mSurfaces->back();
- LWO::Texture tex;
-
- // load the texture header
- LoadLWO2TextureHeader(head->length,tex);
- size -= head->length + 6;
-
- // now get the exact type of the texture
- switch (head->type)
- {
- case AI_LWO_PROC:
- LoadLWO2Procedural(size,tex);
- break;
- case AI_LWO_GRAD:
- LoadLWO2Gradient(size,tex);
- break;
- case AI_LWO_IMAP:
- LoadLWO2ImageMap(size,tex);
- }
-
- // get the destination channel
- TextureList* listRef = NULL;
- switch (tex.type)
- {
- case AI_LWO_COLR:
- listRef = &surf.mColorTextures;break;
- case AI_LWO_DIFF:
- listRef = &surf.mDiffuseTextures;break;
- case AI_LWO_SPEC:
- listRef = &surf.mSpecularTextures;break;
- case AI_LWO_GLOS:
- listRef = &surf.mGlossinessTextures;break;
- case AI_LWO_BUMP:
- listRef = &surf.mBumpTextures;break;
- case AI_LWO_TRAN:
- listRef = &surf.mOpacityTextures;break;
- case AI_LWO_REFL:
- listRef = &surf.mReflectionTextures;break;
- default:
- DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
- return;
- }
-
- // now attach the texture to the parent surface - sort by ordinal string
- for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
- if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- listRef->insert(it,tex);
- return;
- }
- }
- listRef->push_back(tex);
+ ai_assert(!mSurfaces->empty());
+ LWO::Surface& surf = mSurfaces->back();
+ LWO::Texture tex;
+
+ // load the texture header
+ LoadLWO2TextureHeader(head->length,tex);
+ size -= head->length + 6;
+
+ // now get the exact type of the texture
+ switch (head->type)
+ {
+ case AI_LWO_PROC:
+ LoadLWO2Procedural(size,tex);
+ break;
+ case AI_LWO_GRAD:
+ LoadLWO2Gradient(size,tex);
+ break;
+ case AI_LWO_IMAP:
+ LoadLWO2ImageMap(size,tex);
+ }
+
+ // get the destination channel
+ TextureList* listRef = NULL;
+ switch (tex.type)
+ {
+ case AI_LWO_COLR:
+ listRef = &surf.mColorTextures;break;
+ case AI_LWO_DIFF:
+ listRef = &surf.mDiffuseTextures;break;
+ case AI_LWO_SPEC:
+ listRef = &surf.mSpecularTextures;break;
+ case AI_LWO_GLOS:
+ listRef = &surf.mGlossinessTextures;break;
+ case AI_LWO_BUMP:
+ listRef = &surf.mBumpTextures;break;
+ case AI_LWO_TRAN:
+ listRef = &surf.mOpacityTextures;break;
+ case AI_LWO_REFL:
+ listRef = &surf.mReflectionTextures;break;
+ default:
+ DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
+ return;
+ }
+
+ // now attach the texture to the parent surface - sort by ordinal string
+ for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
+ if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
+ listRef->insert(it,tex);
+ return;
+ }
+ }
+ listRef->push_back(tex);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- ai_assert(!mSurfaces->empty());
- LWO::Surface& surf = mSurfaces->back();
- LWO::Shader shader;
-
- // get the ordinal string
- GetS0( shader.ordinal, size);
-
- // we could crash later if this is an empty string ...
- if (!shader.ordinal.length())
- {
- DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
- shader.ordinal = "\x00";
- }
-
- // read the header
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid shader header chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_ENAB:
- shader.enabled = GetU2() ? true : false;
- break;
-
- case AI_LWO_FUNC:
- GetS0( shader.functionName, head->length );
- }
- mFileBuffer = next;
- }
-
- // now attach the shader to the parent surface - sort by ordinal string
- for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
- if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- surf.mShaders.insert(it,shader);
- return;
- }
- }
- surf.mShaders.push_back(shader);
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ ai_assert(!mSurfaces->empty());
+ LWO::Surface& surf = mSurfaces->back();
+ LWO::Shader shader;
+
+ // get the ordinal string
+ GetS0( shader.ordinal, size);
+
+ // we could crash later if this is an empty string ...
+ if (!shader.ordinal.length())
+ {
+ DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+ shader.ordinal = "\x00";
+ }
+
+ // read the header
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid shader header chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_ENAB:
+ shader.enabled = GetU2() ? true : false;
+ break;
+
+ case AI_LWO_FUNC:
+ GetS0( shader.functionName, head.length );
+ }
+ mFileBuffer = next;
+ }
+
+ // now attach the shader to the parent surface - sort by ordinal string
+ for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
+ if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
+ surf.mShaders.insert(it,shader);
+ return;
+ }
+ }
+ surf.mShaders.push_back(shader);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Surface(unsigned int size)
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- mSurfaces->push_back( LWO::Surface () );
- LWO::Surface& surf = mSurfaces->back();
-
- GetS0(surf.mName,size);
-
- // check whether this surface was derived from any other surface
- std::string derived;
- GetS0(derived,(unsigned int)(end - mFileBuffer));
- if (derived.length()) {
- // yes, find this surface
- for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
- if ((*it).mName == derived) {
- // we have it ...
- surf = *it;
- derived.clear();break;
- }
- }
- if (derived.size())
- DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
- }
-
- while (true)
- {
- if (mFileBuffer + 6 >= end)
- break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid surface chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- // diffuse color
- case AI_LWO_COLR:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
- surf.mColor.r = GetF4();
- surf.mColor.g = GetF4();
- surf.mColor.b = GetF4();
- break;
- }
- // diffuse strength ... hopefully
- case AI_LWO_DIFF:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
- surf.mDiffuseValue = GetF4();
- break;
- }
- // specular strength ... hopefully
- case AI_LWO_SPEC:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
- surf.mSpecularValue = GetF4();
- break;
- }
- // transparency
- case AI_LWO_TRAN:
- {
- // transparency explicitly disabled?
- if (surf.mTransparency == 10e10f)
- break;
-
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
- surf.mTransparency = GetF4();
- break;
- }
- // additive transparency
- case AI_LWO_ADTR:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4);
- surf.mAdditiveTransparency = GetF4();
- break;
- }
- // wireframe mode
- case AI_LWO_LINE:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
- if (GetU2() & 0x1)
- surf.mWireframe = true;
- break;
- }
- // glossiness
- case AI_LWO_GLOS:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
- surf.mGlossiness = GetF4();
- break;
- }
- // bump intensity
- case AI_LWO_BUMP:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
- surf.mBumpIntensity = GetF4();
- break;
- }
- // color highlights
- case AI_LWO_CLRH:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
- surf.mColorHighlights = GetF4();
- break;
- }
- // index of refraction
- case AI_LWO_RIND:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
- surf.mIOR = GetF4();
- break;
- }
- // polygon sidedness
- case AI_LWO_SIDE:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
- surf.bDoubleSided = (3 == GetU2());
- break;
- }
- // maximum smoothing angle
- case AI_LWO_SMAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
- surf.mMaximumSmoothAngle = fabs( GetF4() );
- break;
- }
- // vertex color channel to be applied to the surface
- case AI_LWO_VCOL:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
- surf.mDiffuseValue *= GetF4(); // strength
- ReadVSizedIntLWO2(mFileBuffer); // skip envelope
- surf.mVCMapType = GetU4(); // type of the channel
-
- // name of the channel
- GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
- break;
- }
- // surface bock entry
- case AI_LWO_BLOK:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
- LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
-
- switch (head2->type)
- {
- case AI_LWO_PROC:
- case AI_LWO_GRAD:
- case AI_LWO_IMAP:
- LoadLWO2TextureBlock(head2, head->length);
- break;
- case AI_LWO_SHDR:
- LoadLWO2ShaderBlock(head2, head->length);
- break;
-
- default:
- DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
- };
-
- break;
- }
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ mSurfaces->push_back( LWO::Surface () );
+ LWO::Surface& surf = mSurfaces->back();
+
+ GetS0(surf.mName,size);
+
+ // check whether this surface was derived from any other surface
+ std::string derived;
+ GetS0(derived,(unsigned int)(end - mFileBuffer));
+ if (derived.length()) {
+ // yes, find this surface
+ for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
+ if ((*it).mName == derived) {
+ // we have it ...
+ surf = *it;
+ derived.clear();break;
+ }
+ }
+ if (derived.size())
+ DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
+ }
+
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)
+ break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid surface chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ // diffuse color
+ case AI_LWO_COLR:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
+ surf.mColor.r = GetF4();
+ surf.mColor.g = GetF4();
+ surf.mColor.b = GetF4();
+ break;
+ }
+ // diffuse strength ... hopefully
+ case AI_LWO_DIFF:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
+ surf.mDiffuseValue = GetF4();
+ break;
+ }
+ // specular strength ... hopefully
+ case AI_LWO_SPEC:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
+ surf.mSpecularValue = GetF4();
+ break;
+ }
+ // transparency
+ case AI_LWO_TRAN:
+ {
+ // transparency explicitly disabled?
+ if (surf.mTransparency == 10e10f)
+ break;
+
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
+ surf.mTransparency = GetF4();
+ break;
+ }
+ // additive transparency
+ case AI_LWO_ADTR:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
+ surf.mAdditiveTransparency = GetF4();
+ break;
+ }
+ // wireframe mode
+ case AI_LWO_LINE:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
+ if (GetU2() & 0x1)
+ surf.mWireframe = true;
+ break;
+ }
+ // glossiness
+ case AI_LWO_GLOS:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
+ surf.mGlossiness = GetF4();
+ break;
+ }
+ // bump intensity
+ case AI_LWO_BUMP:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
+ surf.mBumpIntensity = GetF4();
+ break;
+ }
+ // color highlights
+ case AI_LWO_CLRH:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
+ surf.mColorHighlights = GetF4();
+ break;
+ }
+ // index of refraction
+ case AI_LWO_RIND:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
+ surf.mIOR = GetF4();
+ break;
+ }
+ // polygon sidedness
+ case AI_LWO_SIDE:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
+ surf.bDoubleSided = (3 == GetU2());
+ break;
+ }
+ // maximum smoothing angle
+ case AI_LWO_SMAN:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
+ surf.mMaximumSmoothAngle = fabs( GetF4() );
+ break;
+ }
+ // vertex color channel to be applied to the surface
+ case AI_LWO_VCOL:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
+ surf.mDiffuseValue *= GetF4(); // strength
+ ReadVSizedIntLWO2(mFileBuffer); // skip envelope
+ surf.mVCMapType = GetU4(); // type of the channel
+
+ // name of the channel
+ GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
+ break;
+ }
+ // surface bock entry
+ case AI_LWO_BLOK:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
+ IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
+
+ switch (head2.type)
+ {
+ case AI_LWO_PROC:
+ case AI_LWO_GRAD:
+ case AI_LWO_IMAP:
+ LoadLWO2TextureBlock(&head2, head.length);
+ break;
+ case AI_LWO_SHDR:
+ LoadLWO2ShaderBlock(&head2, head.length);
+ break;
+
+ default:
+ DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
+ };
+
+ break;
+ }
+ }
+ mFileBuffer = next;
+ }
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
diff --git a/src/3rdparty/assimp/code/LWSLoader.cpp b/src/3rdparty/assimp/code/LWSLoader.cpp
index 20d62569c..a81c15a6e 100644
--- a/src/3rdparty/assimp/code/LWSLoader.cpp
+++ b/src/3rdparty/assimp/code/LWSLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,25 +25,25 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file LWSLoader.cpp
- * @brief Implementation of the LWS importer class
+ * @brief Implementation of the LWS importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER
#include "LWSLoader.h"
@@ -55,288 +55,298 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SkeletonMeshBuilder.h"
#include "ConvertToLHProcess.h"
#include "Importer.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+#include <memory>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "LightWave Scene Importer",
- "",
- "",
- "http://www.newtek.com/lightwave.html=",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "lws mot"
+ "LightWave Scene Importer",
+ "",
+ "",
+ "http://www.newtek.com/lightwave.html=",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "lws mot"
};
// ------------------------------------------------------------------------------------------------
// Recursive parsing of LWS files
void LWS::Element::Parse (const char*& buffer)
{
- for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
-
- // begin of a new element with children
- bool sub = false;
- if (*buffer == '{') {
- ++buffer;
- SkipSpaces(&buffer);
- sub = true;
- }
- else if (*buffer == '}')
- return;
-
- children.push_back(Element());
-
- // copy data line - read token per token
-
- const char* cur = buffer;
- while (!IsSpaceOrNewLine(*buffer)) ++buffer;
- children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur));
- SkipSpaces(&buffer);
-
- if (children.back().tokens[0] == "Plugin")
- {
- DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data");
-
- // strange stuff inside Plugin/Endplugin blocks. Needn't
- // follow LWS syntax, so we skip over it
- for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
- if (!::strncmp(buffer,"EndPlugin",9)) {
- //SkipLine(&buffer);
- break;
- }
- }
- continue;
- }
-
- cur = buffer;
- while (!IsLineEnd(*buffer)) ++buffer;
- children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur));
-
- // parse more elements recursively
- if (sub)
- children.back().Parse(buffer);
- }
+ for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
+
+ // begin of a new element with children
+ bool sub = false;
+ if (*buffer == '{') {
+ ++buffer;
+ SkipSpaces(&buffer);
+ sub = true;
+ }
+ else if (*buffer == '}')
+ return;
+
+ children.push_back(Element());
+
+ // copy data line - read token per token
+
+ const char* cur = buffer;
+ while (!IsSpaceOrNewLine(*buffer)) ++buffer;
+ children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur));
+ SkipSpaces(&buffer);
+
+ if (children.back().tokens[0] == "Plugin")
+ {
+ DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data");
+
+ // strange stuff inside Plugin/Endplugin blocks. Needn't
+ // follow LWS syntax, so we skip over it
+ for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) {
+ if (!::strncmp(buffer,"EndPlugin",9)) {
+ //SkipLine(&buffer);
+ break;
+ }
+ }
+ continue;
+ }
+
+ cur = buffer;
+ while (!IsLineEnd(*buffer)) ++buffer;
+ children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur));
+
+ // parse more elements recursively
+ if (sub)
+ children.back().Parse(buffer);
+ }
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
LWSImporter::LWSImporter()
-: noSkeletonMesh()
+ : configSpeedFlag(),
+ io(),
+ first(),
+ last(),
+ fps(),
+ noSkeletonMesh()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
LWSImporter::~LWSImporter()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "lws" || extension == "mot")
- return true;
-
- // if check for extension is not enough, check for the magic tokens LWSC and LWMO
- if (!extension.length() || checkSig) {
- uint32_t tokens[2];
- tokens[0] = AI_MAKE_MAGIC("LWSC");
- tokens[1] = AI_MAKE_MAGIC("LWMO");
- return CheckMagicToken(pIOHandler,pFile,tokens,2);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "lws" || extension == "mot")
+ return true;
+
+ // if check for extension is not enough, check for the magic tokens LWSC and LWMO
+ if (!extension.length() || checkSig) {
+ uint32_t tokens[2];
+ tokens[0] = AI_MAKE_MAGIC("LWSC");
+ tokens[1] = AI_MAKE_MAGIC("LWMO");
+ return CheckMagicToken(pIOHandler,pFile,tokens,2);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get list of file extensions
const aiImporterDesc* LWSImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void LWSImporter::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_FAVOUR_SPEED
- configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+ // AI_CONFIG_FAVOUR_SPEED
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
- // AI_CONFIG_IMPORT_LWS_ANIM_START
- first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START,
- 150392 /* magic hack */);
+ // AI_CONFIG_IMPORT_LWS_ANIM_START
+ first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START,
+ 150392 /* magic hack */);
- // AI_CONFIG_IMPORT_LWS_ANIM_END
- last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END,
- 150392 /* magic hack */);
+ // AI_CONFIG_IMPORT_LWS_ANIM_END
+ last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END,
+ 150392 /* magic hack */);
- if (last < first) {
- std::swap(last,first);
- }
+ if (last < first) {
+ std::swap(last,first);
+ }
- noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+ noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
}
// ------------------------------------------------------------------------------------------------
// Read an envelope description
void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
{
- if (dad.children.empty()) {
- DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty");
- return;
- }
-
- // reserve enough storage
- std::list< LWS::Element >::const_iterator it = dad.children.begin();;
- fill.keys.reserve(strtoul10(it->tokens[1].c_str()));
-
- for (++it; it != dad.children.end(); ++it) {
- const char* c = (*it).tokens[1].c_str();
-
- if ((*it).tokens[0] == "Key") {
- fill.keys.push_back(LWO::Key());
- LWO::Key& key = fill.keys.back();
-
- float f;
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c,key.value);
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c,f);
-
- key.time = f;
-
- unsigned int span = strtoul10(c,&c), num = 0;
- switch (span) {
-
- case 0:
- key.inter = LWO::IT_TCB;
- num = 5;
- break;
- case 1:
- case 2:
- key.inter = LWO::IT_HERM;
- num = 5;
- break;
- case 3:
- key.inter = LWO::IT_LINE;
- num = 0;
- break;
- case 4:
- key.inter = LWO::IT_STEP;
- num = 0;
- break;
- case 5:
- key.inter = LWO::IT_BEZ2;
- num = 4;
- break;
- default:
- DefaultLogger::get()->error("LWS: Unknown span type");
- }
- for (unsigned int i = 0; i < num;++i) {
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c,key.params[i]);
- }
- }
- else if ((*it).tokens[0] == "Behaviors") {
- SkipSpaces(&c);
- fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c);
- SkipSpaces(&c);
- fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c);
- }
- }
+ if (dad.children.empty()) {
+ DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty");
+ return;
+ }
+
+ // reserve enough storage
+ std::list< LWS::Element >::const_iterator it = dad.children.begin();;
+ fill.keys.reserve(strtoul10(it->tokens[1].c_str()));
+
+ for (++it; it != dad.children.end(); ++it) {
+ const char* c = (*it).tokens[1].c_str();
+
+ if ((*it).tokens[0] == "Key") {
+ fill.keys.push_back(LWO::Key());
+ LWO::Key& key = fill.keys.back();
+
+ float f;
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c,key.value);
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c,f);
+
+ key.time = f;
+
+ unsigned int span = strtoul10(c,&c), num = 0;
+ switch (span) {
+
+ case 0:
+ key.inter = LWO::IT_TCB;
+ num = 5;
+ break;
+ case 1:
+ case 2:
+ key.inter = LWO::IT_HERM;
+ num = 5;
+ break;
+ case 3:
+ key.inter = LWO::IT_LINE;
+ num = 0;
+ break;
+ case 4:
+ key.inter = LWO::IT_STEP;
+ num = 0;
+ break;
+ case 5:
+ key.inter = LWO::IT_BEZ2;
+ num = 4;
+ break;
+ default:
+ DefaultLogger::get()->error("LWS: Unknown span type");
+ }
+ for (unsigned int i = 0; i < num;++i) {
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c,key.params[i]);
+ }
+ }
+ else if ((*it).tokens[0] == "Behaviors") {
+ SkipSpaces(&c);
+ fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c);
+ SkipSpaces(&c);
+ fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Read animation channels in the old LightWave animation format
void LWSImporter::ReadEnvelope_Old(
- std::list< LWS::Element >::const_iterator& it,
- const std::list< LWS::Element >::const_iterator& end,
- LWS::NodeDesc& nodes,
- unsigned int /*version*/)
+ std::list< LWS::Element >::const_iterator& it,
+ const std::list< LWS::Element >::const_iterator& end,
+ LWS::NodeDesc& nodes,
+ unsigned int /*version*/)
{
- unsigned int num,sub_num;
- if (++it == end)goto unexpected_end;
-
- num = strtoul10((*it).tokens[0].c_str());
- for (unsigned int i = 0; i < num; ++i) {
-
- nodes.channels.push_back(LWO::Envelope());
- LWO::Envelope& envl = nodes.channels.back();
-
- envl.index = i;
- envl.type = (LWO::EnvelopeType)(i+1);
-
- if (++it == end)goto unexpected_end;
- sub_num = strtoul10((*it).tokens[0].c_str());
-
- for (unsigned int n = 0; n < sub_num;++n) {
-
- if (++it == end)goto unexpected_end;
-
- // parse value and time, skip the rest for the moment.
- LWO::Key key;
- const char* c = fast_atoreal_move<float>((*it).tokens[0].c_str(),key.value);
- SkipSpaces(&c);
- float f;
- fast_atoreal_move<float>((*it).tokens[0].c_str(),f);
- key.time = f;
-
- envl.keys.push_back(key);
- }
- }
- return;
+ unsigned int num,sub_num;
+ if (++it == end)goto unexpected_end;
+
+ num = strtoul10((*it).tokens[0].c_str());
+ for (unsigned int i = 0; i < num; ++i) {
+
+ nodes.channels.push_back(LWO::Envelope());
+ LWO::Envelope& envl = nodes.channels.back();
+
+ envl.index = i;
+ envl.type = (LWO::EnvelopeType)(i+1);
+
+ if (++it == end)goto unexpected_end;
+ sub_num = strtoul10((*it).tokens[0].c_str());
+
+ for (unsigned int n = 0; n < sub_num;++n) {
+
+ if (++it == end)goto unexpected_end;
+
+ // parse value and time, skip the rest for the moment.
+ LWO::Key key;
+ const char* c = fast_atoreal_move<float>((*it).tokens[0].c_str(),key.value);
+ SkipSpaces(&c);
+ float f;
+ fast_atoreal_move<float>((*it).tokens[0].c_str(),f);
+ key.time = f;
+
+ envl.keys.push_back(key);
+ }
+ }
+ return;
unexpected_end:
- DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion");
+ DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion");
}
// ------------------------------------------------------------------------------------------------
-// Setup a nice name for a node
+// Setup a nice name for a node
void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src)
{
- const unsigned int combined = src.number | ((unsigned int)src.type) << 28u;
+ const unsigned int combined = src.number | ((unsigned int)src.type) << 28u;
- // the name depends on the type. We break LWS's strange naming convention
- // and return human-readable, but still machine-parsable and unique, strings.
- if (src.type == LWS::NodeDesc::OBJECT) {
+ // the name depends on the type. We break LWS's strange naming convention
+ // and return human-readable, but still machine-parsable and unique, strings.
+ if (src.type == LWS::NodeDesc::OBJECT) {
- if (src.path.length()) {
- std::string::size_type s = src.path.find_last_of("\\/");
- if (s == std::string::npos)
- s = 0;
- else ++s;
+ if (src.path.length()) {
+ std::string::size_type s = src.path.find_last_of("\\/");
+ if (s == std::string::npos)
+ s = 0;
+ else ++s;
std::string::size_type t = src.path.substr(s).find_last_of(".");
-
- nd->mName.length = ::sprintf(nd->mName.data,"%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined);
- return;
- }
- }
- nd->mName.length = ::sprintf(nd->mName.data,"%s_(%08X)",src.name,combined);
+
+ nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined);
+ return;
+ }
+ }
+ nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.name,combined);
}
// ------------------------------------------------------------------------------------------------
// Recursively build the scenegraph
void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach,
- BatchLoader& batch,
- aiCamera**& camOut,
- aiLight**& lightOut,
- std::vector<aiNodeAnim*>& animOut)
+ BatchLoader& batch,
+ aiCamera**& camOut,
+ aiLight**& lightOut,
+ std::vector<aiNodeAnim*>& animOut)
{
- // Setup a very cryptic name for the node, we want the user to be happy
- SetupNodeName(nd,src);
+ // Setup a very cryptic name for the node, we want the user to be happy
+ SetupNodeName(nd,src);
aiNode* ndAnim = nd;
- // If the node is an object
- if (src.type == LWS::NodeDesc::OBJECT) {
+ // If the node is an object
+ if (src.type == LWS::NodeDesc::OBJECT) {
- // If the object is from an external file, get it
- aiScene* obj = NULL;
+ // If the object is from an external file, get it
+ aiScene* obj = NULL;
if (src.path.length() ) {
obj = batch.GetImport(src.id);
if (!obj) {
@@ -344,18 +354,18 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
}
else {
if (obj->mRootNode->mNumChildren == 1) {
-
+
//If the pivot is not set for this layer, get it from the external object
if (!src.isPivotSet) {
src.pivotPos.x = +obj->mRootNode->mTransformation.a4;
src.pivotPos.y = +obj->mRootNode->mTransformation.b4;
src.pivotPos.z = -obj->mRootNode->mTransformation.c4; //The sign is the RH to LH back conversion
}
-
+
//Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
aiNode* newRootNode = obj->mRootNode->mChildren[0];
- obj->mRootNode->mChildren[0] = NULL;
- delete obj->mRootNode;
+ obj->mRootNode->mChildren[0] = NULL;
+ delete obj->mRootNode;
obj->mRootNode = newRootNode;
obj->mRootNode->mTransformation.a4 = 0.0;
@@ -364,11 +374,11 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
}
}
}
-
- //Setup the pivot node (also the animation node), the one we received
+
+ //Setup the pivot node (also the animation node), the one we received
nd->mName = std::string("Pivot:") + nd->mName.data;
- ndAnim = nd;
-
+ ndAnim = nd;
+
//Add the attachment node to it
nd->mNumChildren = 1;
nd->mChildren = new aiNode*[1];
@@ -377,547 +387,547 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x;
nd->mChildren[0]->mTransformation.b4 = -src.pivotPos.y;
nd->mChildren[0]->mTransformation.c4 = -src.pivotPos.z;
- SetupNodeName(nd->mChildren[0], src);
-
- //Update the attachment node
- nd = nd->mChildren[0];
-
+ SetupNodeName(nd->mChildren[0], src);
+
+ //Update the attachment node
+ nd = nd->mChildren[0];
+
//Push attachment, if the object came from an external file
if (obj) {
attach.push_back(AttachmentInfo(obj,nd));
}
}
- // If object is a light source - setup a corresponding ai structure
- else if (src.type == LWS::NodeDesc::LIGHT) {
- aiLight* lit = *lightOut++ = new aiLight();
-
- // compute final light color
- lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;
-
- // name to attach light to node -> unique due to LWs indexing system
- lit->mName = nd->mName;
-
- // detemine light type and setup additional members
- if (src.lightType == 2) { /* spot light */
-
- lit->mType = aiLightSource_SPOT;
- lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
- lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );
-
- }
- else if (src.lightType == 1) { /* directional light source */
- lit->mType = aiLightSource_DIRECTIONAL;
- }
- else lit->mType = aiLightSource_POINT;
-
- // fixme: no proper handling of light falloffs yet
- if (src.lightFalloffType == 1)
- lit->mAttenuationConstant = 1.f;
- else if (src.lightFalloffType == 1)
- lit->mAttenuationLinear = 1.f;
- else
- lit->mAttenuationQuadratic = 1.f;
- }
-
- // If object is a camera - setup a corresponding ai structure
- else if (src.type == LWS::NodeDesc::CAMERA) {
- aiCamera* cam = *camOut++ = new aiCamera();
-
- // name to attach cam to node -> unique due to LWs indexing system
- cam->mName = nd->mName;
- }
-
- // Get the node transformation from the LWO key
- LWO::AnimResolver resolver(src.channels,fps);
- resolver.ExtractBindPose(ndAnim->mTransformation);
-
- // .. and construct animation channels
- aiNodeAnim* anim = NULL;
-
- if (first != last) {
- resolver.SetAnimationRange(first,last);
- resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
- if (anim) {
- anim->mNodeName = ndAnim->mName;
- animOut.push_back(anim);
- }
- }
-
- // Add children
- if (src.children.size()) {
- nd->mChildren = new aiNode*[src.children.size()];
- for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
- aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
- ndd->mParent = nd;
-
- BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
- }
- }
+ // If object is a light source - setup a corresponding ai structure
+ else if (src.type == LWS::NodeDesc::LIGHT) {
+ aiLight* lit = *lightOut++ = new aiLight();
+
+ // compute final light color
+ lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity;
+
+ // name to attach light to node -> unique due to LWs indexing system
+ lit->mName = nd->mName;
+
+ // detemine light type and setup additional members
+ if (src.lightType == 2) { /* spot light */
+
+ lit->mType = aiLightSource_SPOT;
+ lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle );
+ lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle );
+
+ }
+ else if (src.lightType == 1) { /* directional light source */
+ lit->mType = aiLightSource_DIRECTIONAL;
+ }
+ else lit->mType = aiLightSource_POINT;
+
+ // fixme: no proper handling of light falloffs yet
+ if (src.lightFalloffType == 1)
+ lit->mAttenuationConstant = 1.f;
+ else if (src.lightFalloffType == 1)
+ lit->mAttenuationLinear = 1.f;
+ else
+ lit->mAttenuationQuadratic = 1.f;
+ }
+
+ // If object is a camera - setup a corresponding ai structure
+ else if (src.type == LWS::NodeDesc::CAMERA) {
+ aiCamera* cam = *camOut++ = new aiCamera();
+
+ // name to attach cam to node -> unique due to LWs indexing system
+ cam->mName = nd->mName;
+ }
+
+ // Get the node transformation from the LWO key
+ LWO::AnimResolver resolver(src.channels,fps);
+ resolver.ExtractBindPose(ndAnim->mTransformation);
+
+ // .. and construct animation channels
+ aiNodeAnim* anim = NULL;
+
+ if (first != last) {
+ resolver.SetAnimationRange(first,last);
+ resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
+ if (anim) {
+ anim->mNodeName = ndAnim->mName;
+ animOut.push_back(anim);
+ }
+ }
+
+ // Add children
+ if (!src.children.empty()) {
+ nd->mChildren = new aiNode*[src.children.size()];
+ for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) {
+ aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode();
+ ndd->mParent = nd;
+
+ BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Determine the exact location of a LWO file
std::string LWSImporter::FindLWOFile(const std::string& in)
{
- // insert missing directory seperator if necessary
- std::string tmp;
- if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
- {
- tmp = in[0] + (":\\" + in.substr(2));
- }
- else tmp = in;
-
- if (io->Exists(tmp)) {
- return in;
- }
-
- // file is not accessible for us ... maybe it's packed by
- // LightWave's 'Package Scene' command?
-
- // Relevant for us are the following two directories:
- // <folder>\Objects\<hh>\<*>.lwo
- // <folder>\Scenes\<hh>\<*>.lws
- // where <hh> is optional.
-
- std::string test = ".." + (io->getOsSeparator() + tmp);
- if (io->Exists(test)) {
- return test;
- }
-
- test = ".." + (io->getOsSeparator() + test);
- if (io->Exists(test)) {
- return test;
- }
-
-
- // return original path, maybe the IOsystem knows better
- return tmp;
+ // insert missing directory seperator if necessary
+ std::string tmp;
+ if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
+ {
+ tmp = in[0] + (std::string(":\\") + in.substr(2));
+ }
+ else tmp = in;
+
+ if (io->Exists(tmp)) {
+ return in;
+ }
+
+ // file is not accessible for us ... maybe it's packed by
+ // LightWave's 'Package Scene' command?
+
+ // Relevant for us are the following two directories:
+ // <folder>\Objects\<hh>\<*>.lwo
+ // <folder>\Scenes\<hh>\<*>.lws
+ // where <hh> is optional.
+
+ std::string test = std::string("..") + (io->getOsSeparator() + tmp);
+ if (io->Exists(test)) {
+ return test;
+ }
+
+ test = std::string("..") + (io->getOsSeparator() + test);
+ if (io->Exists(test)) {
+ return test;
+ }
+
+
+ // return original path, maybe the IOsystem knows better
+ return tmp;
}
// ------------------------------------------------------------------------------------------------
// Read file into given scene data structure
-void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler)
+void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler)
{
- io = pIOHandler;
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open LWS file " + pFile + ".");
- }
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector< char > mBuffer;
- TextFileToBuffer(file.get(),mBuffer);
-
- // Parse the file structure
- LWS::Element root; const char* dummy = &mBuffer[0];
- root.Parse(dummy);
-
- // Construct a Batchimporter to read more files recursively
- BatchLoader batch(pIOHandler);
-// batch.SetBasePath(pFile);
-
- // Construct an array to receive the flat output graph
- std::list<LWS::NodeDesc> nodes;
-
- unsigned int cur_light = 0, cur_camera = 0, cur_object = 0;
- unsigned int num_light = 0, num_camera = 0, num_object = 0;
-
- // check magic identifier, 'LWSC'
- bool motion_file = false;
- std::list< LWS::Element >::const_iterator it = root.children.begin();
-
- if ((*it).tokens[0] == "LWMO")
- motion_file = true;
-
- if ((*it).tokens[0] != "LWSC" && !motion_file)
- throw DeadlyImportError("LWS: Not a LightWave scene, magic tag LWSC not found");
-
- // get file format version and print to log
- ++it;
- unsigned int version = strtoul10((*it).tokens[0].c_str());
- DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]);
- first = 0.;
- last = 60.;
- fps = 25.; /* seems to be a good default frame rate */
-
- // Now read all elements in a very straghtforward manner
- for (; it != root.children.end(); ++it) {
- const char* c = (*it).tokens[1].c_str();
-
- // 'FirstFrame': begin of animation slice
- if ((*it).tokens[0] == "FirstFrame") {
- if (150392. != first /* see SetupProperties() */)
- first = strtoul10(c,&c)-1.; /* we're zero-based */
- }
-
- // 'LastFrame': end of animation slice
- else if ((*it).tokens[0] == "LastFrame") {
- if (150392. != last /* see SetupProperties() */)
- last = strtoul10(c,&c)-1.; /* we're zero-based */
- }
-
- // 'FramesPerSecond': frames per second
- else if ((*it).tokens[0] == "FramesPerSecond") {
- fps = strtoul10(c,&c);
- }
-
- // 'LoadObjectLayer': load a layer of a specific LWO file
- else if ((*it).tokens[0] == "LoadObjectLayer") {
-
- // get layer index
- const int layer = strtoul10(c,&c);
-
- // setup the layer to be loaded
- BatchLoader::PropertyMap props;
- SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer);
-
- // add node to list
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::OBJECT;
- if (version >= 4) { // handle LWSC 4 explicit ID
- SkipSpaces(&c);
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- }
- else d.number = cur_object++;
-
- // and add the file to the import list
- SkipSpaces(&c);
- std::string path = FindLWOFile( c );
- d.path = path;
- d.id = batch.AddLoadRequest(path,0,&props);
-
- nodes.push_back(d);
- num_object++;
- }
- // 'LoadObject': load a LWO file into the scenegraph
- else if ((*it).tokens[0] == "LoadObject") {
-
- // add node to list
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::OBJECT;
-
- if (version >= 4) { // handle LWSC 4 explicit ID
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- SkipSpaces(&c);
- }
- else d.number = cur_object++;
- std::string path = FindLWOFile( c );
- d.id = batch.AddLoadRequest(path,0,NULL);
-
- d.path = path;
- nodes.push_back(d);
- num_object++;
- }
- // 'AddNullObject': add a dummy node to the hierarchy
- else if ((*it).tokens[0] == "AddNullObject") {
-
- // add node to list
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::OBJECT;
- if (version >= 4) { // handle LWSC 4 explicit ID
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- SkipSpaces(&c);
- }
- else d.number = cur_object++;
+ io = pIOHandler;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open LWS file " + pFile + ".");
+ }
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector< char > mBuffer;
+ TextFileToBuffer(file.get(),mBuffer);
+
+ // Parse the file structure
+ LWS::Element root; const char* dummy = &mBuffer[0];
+ root.Parse(dummy);
+
+ // Construct a Batchimporter to read more files recursively
+ BatchLoader batch(pIOHandler);
+// batch.SetBasePath(pFile);
+
+ // Construct an array to receive the flat output graph
+ std::list<LWS::NodeDesc> nodes;
+
+ unsigned int cur_light = 0, cur_camera = 0, cur_object = 0;
+ unsigned int num_light = 0, num_camera = 0, num_object = 0;
+
+ // check magic identifier, 'LWSC'
+ bool motion_file = false;
+ std::list< LWS::Element >::const_iterator it = root.children.begin();
+
+ if ((*it).tokens[0] == "LWMO")
+ motion_file = true;
+
+ if ((*it).tokens[0] != "LWSC" && !motion_file)
+ throw DeadlyImportError("LWS: Not a LightWave scene, magic tag LWSC not found");
+
+ // get file format version and print to log
+ ++it;
+ unsigned int version = strtoul10((*it).tokens[0].c_str());
+ DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]);
+ first = 0.;
+ last = 60.;
+ fps = 25.; /* seems to be a good default frame rate */
+
+ // Now read all elements in a very straghtforward manner
+ for (; it != root.children.end(); ++it) {
+ const char* c = (*it).tokens[1].c_str();
+
+ // 'FirstFrame': begin of animation slice
+ if ((*it).tokens[0] == "FirstFrame") {
+ if (150392. != first /* see SetupProperties() */)
+ first = strtoul10(c,&c)-1.; /* we're zero-based */
+ }
+
+ // 'LastFrame': end of animation slice
+ else if ((*it).tokens[0] == "LastFrame") {
+ if (150392. != last /* see SetupProperties() */)
+ last = strtoul10(c,&c)-1.; /* we're zero-based */
+ }
+
+ // 'FramesPerSecond': frames per second
+ else if ((*it).tokens[0] == "FramesPerSecond") {
+ fps = strtoul10(c,&c);
+ }
+
+ // 'LoadObjectLayer': load a layer of a specific LWO file
+ else if ((*it).tokens[0] == "LoadObjectLayer") {
+
+ // get layer index
+ const int layer = strtoul10(c,&c);
+
+ // setup the layer to be loaded
+ BatchLoader::PropertyMap props;
+ SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer);
+
+ // add node to list
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::OBJECT;
+ if (version >= 4) { // handle LWSC 4 explicit ID
+ SkipSpaces(&c);
+ d.number = strtoul16(c,&c) & AI_LWS_MASK;
+ }
+ else d.number = cur_object++;
+
+ // and add the file to the import list
+ SkipSpaces(&c);
+ std::string path = FindLWOFile( c );
+ d.path = path;
+ d.id = batch.AddLoadRequest(path,0,&props);
+
+ nodes.push_back(d);
+ num_object++;
+ }
+ // 'LoadObject': load a LWO file into the scenegraph
+ else if ((*it).tokens[0] == "LoadObject") {
+
+ // add node to list
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::OBJECT;
+
+ if (version >= 4) { // handle LWSC 4 explicit ID
+ d.number = strtoul16(c,&c) & AI_LWS_MASK;
+ SkipSpaces(&c);
+ }
+ else d.number = cur_object++;
+ std::string path = FindLWOFile( c );
+ d.id = batch.AddLoadRequest(path,0,NULL);
+
+ d.path = path;
+ nodes.push_back(d);
+ num_object++;
+ }
+ // 'AddNullObject': add a dummy node to the hierarchy
+ else if ((*it).tokens[0] == "AddNullObject") {
+
+ // add node to list
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::OBJECT;
+ if (version >= 4) { // handle LWSC 4 explicit ID
+ d.number = strtoul16(c,&c) & AI_LWS_MASK;
+ SkipSpaces(&c);
+ }
+ else d.number = cur_object++;
d.name = c;
- nodes.push_back(d);
-
- num_object++;
- }
- // 'NumChannels': Number of envelope channels assigned to last layer
- else if ((*it).tokens[0] == "NumChannels") {
- // ignore for now
- }
- // 'Channel': preceedes any envelope description
- else if ((*it).tokens[0] == "Channel") {
- if (nodes.empty()) {
- if (motion_file) {
-
- // LightWave motion file. Add dummy node
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::OBJECT;
- d.name = c;
- d.number = cur_object++;
- nodes.push_back(d);
- }
- else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'");
- }
-
- // important: index of channel
- nodes.back().channels.push_back(LWO::Envelope());
- LWO::Envelope& env = nodes.back().channels.back();
-
- env.index = strtoul10(c);
-
- // currently we can just interpret the standard channels 0...9
- // (hack) assume that index-i yields the binary channel type from LWO
- env.type = (LWO::EnvelopeType)(env.index+1);
-
- }
- // 'Envelope': a single animation channel
- else if ((*it).tokens[0] == "Envelope") {
- if (nodes.empty() || nodes.back().channels.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'");
- else {
- ReadEnvelope((*it),nodes.back().channels.back());
- }
- }
- // 'ObjectMotion': animation information for older lightwave formats
- else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
- (*it).tokens[0] == "CameraMotion" ||
- (*it).tokens[0] == "LightMotion")) {
-
- if (nodes.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
- else {
- ReadEnvelope_Old(it,root.children.end(),nodes.back(),version);
- }
- }
- // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2
- else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") {
- if (nodes.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'");
- else {
- for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
- // two ints per envelope
- LWO::Envelope& env = *it;
- env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
- env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
- }
- }
- }
- // 'ParentItem': specifies the parent of the current element
- else if ((*it).tokens[0] == "ParentItem") {
- if (nodes.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'");
-
- else nodes.back().parent = strtoul16(c,&c);
- }
- // 'ParentObject': deprecated one for older formats
- else if (version < 3 && (*it).tokens[0] == "ParentObject") {
- if (nodes.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'");
-
- else {
- nodes.back().parent = strtoul10(c,&c) | (1u << 28u);
- }
- }
- // 'AddCamera': add a camera to the scenegraph
- else if ((*it).tokens[0] == "AddCamera") {
-
- // add node to list
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::CAMERA;
-
- if (version >= 4) { // handle LWSC 4 explicit ID
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- }
- else d.number = cur_camera++;
- nodes.push_back(d);
-
- num_camera++;
- }
- // 'CameraName': set name of currently active camera
- else if ((*it).tokens[0] == "CameraName") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'");
-
- else nodes.back().name = c;
- }
- // 'AddLight': add a light to the scenegraph
- else if ((*it).tokens[0] == "AddLight") {
-
- // add node to list
- LWS::NodeDesc d;
- d.type = LWS::NodeDesc::LIGHT;
-
- if (version >= 4) { // handle LWSC 4 explicit ID
- d.number = strtoul16(c,&c) & AI_LWS_MASK;
- }
- else d.number = cur_light++;
- nodes.push_back(d);
-
- num_light++;
- }
- // 'LightName': set name of currently active light
- else if ((*it).tokens[0] == "LightName") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'");
-
- else nodes.back().name = c;
- }
- // 'LightIntensity': set intensity of currently active light
- else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'");
-
- else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
-
- }
- // 'LightType': set type of currently active light
- else if ((*it).tokens[0] == "LightType") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'");
-
- else nodes.back().lightType = strtoul10(c);
-
- }
- // 'LightFalloffType': set falloff type of currently active light
- else if ((*it).tokens[0] == "LightFalloffType") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'");
-
- else nodes.back().lightFalloffType = strtoul10(c);
-
- }
- // 'LightConeAngle': set cone angle of currently active light
- else if ((*it).tokens[0] == "LightConeAngle") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'");
-
- else nodes.back().lightConeAngle = fast_atof(c);
-
- }
- // 'LightEdgeAngle': set area where we're smoothing from min to max intensity
- else if ((*it).tokens[0] == "LightEdgeAngle") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'");
-
- else nodes.back().lightEdgeAngle = fast_atof(c);
-
- }
- // 'LightColor': set color of currently active light
- else if ((*it).tokens[0] == "LightColor") {
- if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'");
-
- else {
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r );
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.g );
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.b );
- }
- }
-
- // 'PivotPosition': position of local transformation origin
- else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") {
- if (nodes.empty())
- DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'");
- else {
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x );
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.y );
- SkipSpaces(&c);
- c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.z );
+ nodes.push_back(d);
+
+ num_object++;
+ }
+ // 'NumChannels': Number of envelope channels assigned to last layer
+ else if ((*it).tokens[0] == "NumChannels") {
+ // ignore for now
+ }
+ // 'Channel': preceedes any envelope description
+ else if ((*it).tokens[0] == "Channel") {
+ if (nodes.empty()) {
+ if (motion_file) {
+
+ // LightWave motion file. Add dummy node
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::OBJECT;
+ d.name = c;
+ d.number = cur_object++;
+ nodes.push_back(d);
+ }
+ else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'");
+ }
+
+ // important: index of channel
+ nodes.back().channels.push_back(LWO::Envelope());
+ LWO::Envelope& env = nodes.back().channels.back();
+
+ env.index = strtoul10(c);
+
+ // currently we can just interpret the standard channels 0...9
+ // (hack) assume that index-i yields the binary channel type from LWO
+ env.type = (LWO::EnvelopeType)(env.index+1);
+
+ }
+ // 'Envelope': a single animation channel
+ else if ((*it).tokens[0] == "Envelope") {
+ if (nodes.empty() || nodes.back().channels.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'");
+ else {
+ ReadEnvelope((*it),nodes.back().channels.back());
+ }
+ }
+ // 'ObjectMotion': animation information for older lightwave formats
+ else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" ||
+ (*it).tokens[0] == "CameraMotion" ||
+ (*it).tokens[0] == "LightMotion")) {
+
+ if (nodes.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
+ else {
+ ReadEnvelope_Old(it,root.children.end(),nodes.back(),version);
+ }
+ }
+ // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2
+ else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") {
+ if (nodes.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'");
+ else {
+ for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
+ // two ints per envelope
+ LWO::Envelope& env = *it;
+ env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
+ env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c);
+ }
+ }
+ }
+ // 'ParentItem': specifies the parent of the current element
+ else if ((*it).tokens[0] == "ParentItem") {
+ if (nodes.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'");
+
+ else nodes.back().parent = strtoul16(c,&c);
+ }
+ // 'ParentObject': deprecated one for older formats
+ else if (version < 3 && (*it).tokens[0] == "ParentObject") {
+ if (nodes.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'");
+
+ else {
+ nodes.back().parent = strtoul10(c,&c) | (1u << 28u);
+ }
+ }
+ // 'AddCamera': add a camera to the scenegraph
+ else if ((*it).tokens[0] == "AddCamera") {
+
+ // add node to list
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::CAMERA;
+
+ if (version >= 4) { // handle LWSC 4 explicit ID
+ d.number = strtoul16(c,&c) & AI_LWS_MASK;
+ }
+ else d.number = cur_camera++;
+ nodes.push_back(d);
+
+ num_camera++;
+ }
+ // 'CameraName': set name of currently active camera
+ else if ((*it).tokens[0] == "CameraName") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'");
+
+ else nodes.back().name = c;
+ }
+ // 'AddLight': add a light to the scenegraph
+ else if ((*it).tokens[0] == "AddLight") {
+
+ // add node to list
+ LWS::NodeDesc d;
+ d.type = LWS::NodeDesc::LIGHT;
+
+ if (version >= 4) { // handle LWSC 4 explicit ID
+ d.number = strtoul16(c,&c) & AI_LWS_MASK;
+ }
+ else d.number = cur_light++;
+ nodes.push_back(d);
+
+ num_light++;
+ }
+ // 'LightName': set name of currently active light
+ else if ((*it).tokens[0] == "LightName") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'");
+
+ else nodes.back().name = c;
+ }
+ // 'LightIntensity': set intensity of currently active light
+ else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'");
+
+ else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
+
+ }
+ // 'LightType': set type of currently active light
+ else if ((*it).tokens[0] == "LightType") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'");
+
+ else nodes.back().lightType = strtoul10(c);
+
+ }
+ // 'LightFalloffType': set falloff type of currently active light
+ else if ((*it).tokens[0] == "LightFalloffType") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'");
+
+ else nodes.back().lightFalloffType = strtoul10(c);
+
+ }
+ // 'LightConeAngle': set cone angle of currently active light
+ else if ((*it).tokens[0] == "LightConeAngle") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'");
+
+ else nodes.back().lightConeAngle = fast_atof(c);
+
+ }
+ // 'LightEdgeAngle': set area where we're smoothing from min to max intensity
+ else if ((*it).tokens[0] == "LightEdgeAngle") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'");
+
+ else nodes.back().lightEdgeAngle = fast_atof(c);
+
+ }
+ // 'LightColor': set color of currently active light
+ else if ((*it).tokens[0] == "LightColor") {
+ if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'");
+
+ else {
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r );
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.g );
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.b );
+ }
+ }
+
+ // 'PivotPosition': position of local transformation origin
+ else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") {
+ if (nodes.empty())
+ DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'");
+ else {
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x );
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.y );
+ SkipSpaces(&c);
+ c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.z );
// Mark pivotPos as set
nodes.back().isPivotSet = true;
- }
- }
- }
-
- // resolve parenting
- for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
-
- // check whether there is another node which calls us a parent
- for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) {
- if (dit != it && *it == (*dit).parent) {
- if ((*dit).parent_resolved) {
- // fixme: it's still possible to produce an overflow due to cross references ..
- DefaultLogger::get()->error("LWS: Found cross reference in scenegraph");
- continue;
- }
-
- (*it).children.push_back(&*dit);
- (*dit).parent_resolved = &*it;
- }
- }
- }
-
- // find out how many nodes have no parent yet
- unsigned int no_parent = 0;
- for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
- if (!(*it).parent_resolved)
- ++ no_parent;
- }
- if (!no_parent)
- throw DeadlyImportError("LWS: Unable to find scene root node");
-
-
- // Load all subsequent files
- batch.LoadAll();
-
- // and build the final output graph by attaching the loaded external
- // files to ourselves. first build a master graph
- aiScene* master = new aiScene();
- aiNode* nd = master->mRootNode = new aiNode();
-
- // allocate storage for cameras&lights
- if (num_camera) {
- master->mCameras = new aiCamera*[master->mNumCameras = num_camera];
- }
- aiCamera** cams = master->mCameras;
- if (num_light) {
- master->mLights = new aiLight*[master->mNumLights = num_light];
- }
- aiLight** lights = master->mLights;
-
- std::vector<AttachmentInfo> attach;
- std::vector<aiNodeAnim*> anims;
-
- nd->mName.Set("<LWSRoot>");
- nd->mChildren = new aiNode*[no_parent];
- for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
- if (!(*it).parent_resolved) {
- aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode();
- ro->mParent = nd;
-
- // ... and build the scene graph. If we encounter object nodes,
- // add then to our attachment table.
- BuildGraph(ro,*it, attach, batch, cams, lights, anims);
- }
- }
-
- // create a master animation channel for us
- if (anims.size()) {
- master->mAnimations = new aiAnimation*[master->mNumAnimations = 1];
- aiAnimation* anim = master->mAnimations[0] = new aiAnimation();
- anim->mName.Set("LWSMasterAnim");
-
- // LWS uses seconds as time units, but we convert to frames
- anim->mTicksPerSecond = fps;
- anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/
-
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels = anims.size()];
- std::copy(anims.begin(),anims.end(),anim->mChannels);
- }
-
- // convert the master scene to RH
- MakeLeftHandedProcess monster_cheat;
- monster_cheat.Execute(master);
-
- // .. ccw
- FlipWindingOrderProcess flipper;
- flipper.Execute(master);
-
- // OK ... finally build the output graph
- SceneCombiner::MergeScenes(&pScene,master,attach,
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
-
- // Check flags
- if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-
- if (pScene->mNumAnimations && !noSkeletonMesh) {
- // construct skeleton mesh
- SkeletonMeshBuilder builder(pScene);
- }
- }
+ }
+ }
+ }
+
+ // resolve parenting
+ for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
+
+ // check whether there is another node which calls us a parent
+ for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) {
+ if (dit != it && *it == (*dit).parent) {
+ if ((*dit).parent_resolved) {
+ // fixme: it's still possible to produce an overflow due to cross references ..
+ DefaultLogger::get()->error("LWS: Found cross reference in scenegraph");
+ continue;
+ }
+
+ (*it).children.push_back(&*dit);
+ (*dit).parent_resolved = &*it;
+ }
+ }
+ }
+
+ // find out how many nodes have no parent yet
+ unsigned int no_parent = 0;
+ for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
+ if (!(*it).parent_resolved)
+ ++ no_parent;
+ }
+ if (!no_parent)
+ throw DeadlyImportError("LWS: Unable to find scene root node");
+
+
+ // Load all subsequent files
+ batch.LoadAll();
+
+ // and build the final output graph by attaching the loaded external
+ // files to ourselves. first build a master graph
+ aiScene* master = new aiScene();
+ aiNode* nd = master->mRootNode = new aiNode();
+
+ // allocate storage for cameras&lights
+ if (num_camera) {
+ master->mCameras = new aiCamera*[master->mNumCameras = num_camera];
+ }
+ aiCamera** cams = master->mCameras;
+ if (num_light) {
+ master->mLights = new aiLight*[master->mNumLights = num_light];
+ }
+ aiLight** lights = master->mLights;
+
+ std::vector<AttachmentInfo> attach;
+ std::vector<aiNodeAnim*> anims;
+
+ nd->mName.Set("<LWSRoot>");
+ nd->mChildren = new aiNode*[no_parent];
+ for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
+ if (!(*it).parent_resolved) {
+ aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode();
+ ro->mParent = nd;
+
+ // ... and build the scene graph. If we encounter object nodes,
+ // add then to our attachment table.
+ BuildGraph(ro,*it, attach, batch, cams, lights, anims);
+ }
+ }
+
+ // create a master animation channel for us
+ if (anims.size()) {
+ master->mAnimations = new aiAnimation*[master->mNumAnimations = 1];
+ aiAnimation* anim = master->mAnimations[0] = new aiAnimation();
+ anim->mName.Set("LWSMasterAnim");
+
+ // LWS uses seconds as time units, but we convert to frames
+ anim->mTicksPerSecond = fps;
+ anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/
+
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels = anims.size()];
+ std::copy(anims.begin(),anims.end(),anim->mChannels);
+ }
+
+ // convert the master scene to RH
+ MakeLeftHandedProcess monster_cheat;
+ monster_cheat.Execute(master);
+
+ // .. ccw
+ FlipWindingOrderProcess flipper;
+ flipper.Execute(master);
+
+ // OK ... finally build the output graph
+ SceneCombiner::MergeScenes(&pScene,master,attach,
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? (
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0));
+
+ // Check flags
+ if (!pScene->mNumMeshes || !pScene->mNumMaterials) {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+
+ if (pScene->mNumAnimations && !noSkeletonMesh) {
+ // construct skeleton mesh
+ SkeletonMeshBuilder builder(pScene);
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/LWSLoader.h b/src/3rdparty/assimp/code/LWSLoader.h
index 06ca34c33..9547b67bb 100644
--- a/src/3rdparty/assimp/code/LWSLoader.h
+++ b/src/3rdparty/assimp/code/LWSLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,32 +23,39 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file LWSLoader.h
- * @brief Declaration of the LightWave scene importer class.
+ * @brief Declaration of the LightWave scene importer class.
*/
#ifndef AI_LWSLOADER_H_INCLUDED
#define AI_LWSLOADER_H_INCLUDED
#include "LWOFileData.h"
#include "SceneCombiner.h"
+#include "BaseImporter.h"
-namespace Assimp {
- namespace LWS {
+struct aiImporterDesc;
+
+namespace Assimp {
+ class BatchLoader;
+ class Importer;
+ class IOSystem;
+
+ namespace LWS {
// ---------------------------------------------------------------------------
/** Represents an element in a LWS file.
@@ -59,15 +66,15 @@ namespace Assimp {
class Element
{
public:
- Element()
- {}
+ Element()
+ {}
- // first: name, second: rest
- std::string tokens[2];
- std::list<Element> children;
+ // first: name, second: rest
+ std::string tokens[2];
+ std::list<Element> children;
- //! Recursive parsing function
- void Parse (const char*& buffer);
+ //! Recursive parsing function
+ void Parse (const char*& buffer);
};
#define AI_LWS_MASK (0xffffffff >> 4u)
@@ -77,84 +84,87 @@ public:
*/
struct NodeDesc
{
- NodeDesc()
- : number (0)
- , parent (0)
- , name ("")
- , isPivotSet (false)
- , lightColor (1.f,1.f,1.f)
- , lightIntensity (1.f)
- , lightType (0)
- , lightFalloffType (0)
- , lightConeAngle (45.f)
- , parent_resolved (NULL)
- {}
+ NodeDesc()
+ : type()
+ , id()
+ , number (0)
+ , parent (0)
+ , name ("")
+ , isPivotSet (false)
+ , lightColor (1.f,1.f,1.f)
+ , lightIntensity (1.f)
+ , lightType (0)
+ , lightFalloffType (0)
+ , lightConeAngle (45.f)
+ , lightEdgeAngle()
+ , parent_resolved (NULL)
+ {}
+
+ enum {
+
+ OBJECT = 1,
+ LIGHT = 2,
+ CAMERA = 3,
+ BONE = 4
+ } type; // type of node
- enum {
-
- OBJECT = 1,
- LIGHT = 2,
- CAMERA = 3,
- BONE = 4
- } type; // type of node
+ // if object: path
+ std::string path;
+ unsigned int id;
- // if object: path
- std::string path;
- unsigned int id;
+ // number of object
+ unsigned int number;
- // number of object
- unsigned int number;
+ // index of parent index
+ unsigned int parent;
- // index of parent index
- unsigned int parent;
+ // lights & cameras & dummies: name
+ const char* name;
- // lights & cameras & dummies: name
- const char* name;
+ // animation channels
+ std::list< LWO::Envelope > channels;
- // animation channels
- std::list< LWO::Envelope > channels;
+ // position of pivot point
+ aiVector3D pivotPos;
+ bool isPivotSet;
- // position of pivot point
- aiVector3D pivotPos;
- bool isPivotSet;
+ // color of light source
+ aiColor3D lightColor;
- // color of light source
- aiColor3D lightColor;
+ // intensity of light source
+ float lightIntensity;
- // intensity of light source
- float lightIntensity;
+ // type of light source
+ unsigned int lightType;
- // type of light source
- unsigned int lightType;
+ // falloff type of light source
+ unsigned int lightFalloffType;
- // falloff type of light source
- unsigned int lightFalloffType;
+ // cone angle of (spot) light source
+ float lightConeAngle;
- // cone angle of (spot) light source
- float lightConeAngle;
+ // soft cone angle of (spot) light source
+ float lightEdgeAngle;
- // soft cone angle of (spot) light source
- float lightEdgeAngle;
+ // list of resolved children
+ std::list< NodeDesc* > children;
- // list of resolved children
- std::list< NodeDesc* > children;
+ // resolved parent node
+ NodeDesc* parent_resolved;
- // resolved parent node
- NodeDesc* parent_resolved;
+ // for std::find()
+ bool operator == (unsigned int num) const {
+ if (!num)
+ return false;
+ unsigned int _type = num >> 28u;
- // for std::find()
- bool operator == (unsigned int num) const {
- if (!num)
- return false;
- unsigned int _type = num >> 28u;
-
- return _type == static_cast<unsigned int>(type) && (num & AI_LWS_MASK) == number;
- }
+ return _type == static_cast<unsigned int>(type) && (num & AI_LWS_MASK) == number;
+ }
};
} // end namespace LWS
@@ -164,77 +174,77 @@ struct NodeDesc
*
* This class does heavily depend on the LWO importer class. LWS files
* contain mainly descriptions how LWO objects are composed together
- * in a scene.
+ * in a scene.
*/
class LWSImporter : public BaseImporter
{
public:
- LWSImporter();
- ~LWSImporter();
+ LWSImporter();
+ ~LWSImporter();
public:
- // -------------------------------------------------------------------
- // Check whether we can read a specific file
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ // Check whether we can read a specific file
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- // Get list of supported extensions
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ // Get list of supported extensions
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- // Import file into given scene data structure
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ // Import file into given scene data structure
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- // Setup import properties
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ // Setup import properties
+ void SetupProperties(const Importer* pImp);
private:
- // -------------------------------------------------------------------
- // Read an envelope description
- void ReadEnvelope(const LWS::Element& dad, LWO::Envelope& out );
+ // -------------------------------------------------------------------
+ // Read an envelope description
+ void ReadEnvelope(const LWS::Element& dad, LWO::Envelope& out );
- // -------------------------------------------------------------------
- // Read an envelope description for the older LW file format
- void ReadEnvelope_Old(std::list< LWS::Element >::const_iterator& it,
- const std::list< LWS::Element >::const_iterator& end,
- LWS::NodeDesc& nodes,
- unsigned int version);
+ // -------------------------------------------------------------------
+ // Read an envelope description for the older LW file format
+ void ReadEnvelope_Old(std::list< LWS::Element >::const_iterator& it,
+ const std::list< LWS::Element >::const_iterator& end,
+ LWS::NodeDesc& nodes,
+ unsigned int version);
- // -------------------------------------------------------------------
- // Setup a nice name for a node
- void SetupNodeName(aiNode* nd, LWS::NodeDesc& src);
+ // -------------------------------------------------------------------
+ // Setup a nice name for a node
+ void SetupNodeName(aiNode* nd, LWS::NodeDesc& src);
- // -------------------------------------------------------------------
- // Recursively build the scenegraph
- void BuildGraph(aiNode* nd,
- LWS::NodeDesc& src,
- std::vector<AttachmentInfo>& attach,
- BatchLoader& batch,
- aiCamera**& camOut,
- aiLight**& lightOut,
- std::vector<aiNodeAnim*>& animOut);
+ // -------------------------------------------------------------------
+ // Recursively build the scenegraph
+ void BuildGraph(aiNode* nd,
+ LWS::NodeDesc& src,
+ std::vector<AttachmentInfo>& attach,
+ BatchLoader& batch,
+ aiCamera**& camOut,
+ aiLight**& lightOut,
+ std::vector<aiNodeAnim*>& animOut);
- // -------------------------------------------------------------------
- // Try several dirs until we find the right location of a LWS file.
- std::string FindLWOFile(const std::string& in);
+ // -------------------------------------------------------------------
+ // Try several dirs until we find the right location of a LWS file.
+ std::string FindLWOFile(const std::string& in);
private:
- bool configSpeedFlag;
- IOSystem* io;
+ bool configSpeedFlag;
+ IOSystem* io;
- double first,last,fps;
+ double first,last,fps;
- bool noSkeletonMesh;
+ bool noSkeletonMesh;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
index bfe60892d..e7fd9ab60 100644
--- a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
+++ b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,9 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** Implementation of the LimitBoneWeightsProcess post processing step */
-#include "AssimpPCH.h"
-#include "LimitBoneWeightsProcess.h"
+#include "LimitBoneWeightsProcess.h"
+#include "StringUtils.h"
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <stdio.h>
using namespace Assimp;
@@ -51,154 +55,147 @@ using namespace Assimp;
// Constructor to be privately used by Importer
LimitBoneWeightsProcess::LimitBoneWeightsProcess()
{
- mMaxWeights = AI_LMW_MAX_WEIGHTS;
+ mMaxWeights = AI_LMW_MAX_WEIGHTS;
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
LimitBoneWeightsProcess::~LimitBoneWeightsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_LimitBoneWeights) != 0;
+ return (pFlags & aiProcess_LimitBoneWeights) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("LimitBoneWeightsProcess begin");
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- ProcessMesh( pScene->mMeshes[a]);
+ DefaultLogger::get()->debug("LimitBoneWeightsProcess begin");
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ ProcessMesh( pScene->mMeshes[a]);
- DefaultLogger::get()->debug("LimitBoneWeightsProcess end");
+ DefaultLogger::get()->debug("LimitBoneWeightsProcess end");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
{
- // get the current value of the property
- this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
+ // get the current value of the property
+ this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
}
// ------------------------------------------------------------------------------------------------
// Unites identical vertices in the given mesh
void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
{
- if( !pMesh->HasBones())
- return;
-
- // collect all bone weights per vertex
- typedef std::vector< std::vector< Weight > > WeightsPerVertex;
- WeightsPerVertex vertexWeights( pMesh->mNumVertices);
-
- // collect all weights per vertex
- for( unsigned int a = 0; a < pMesh->mNumBones; a++)
- {
- const aiBone* bone = pMesh->mBones[a];
- for( unsigned int b = 0; b < bone->mNumWeights; b++)
- {
- const aiVertexWeight& w = bone->mWeights[b];
- vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
- }
- }
-
- unsigned int removed = 0, old_bones = pMesh->mNumBones;
-
- // now cut the weight count if it exceeds the maximum
- bool bChanged = false;
- for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
- {
- if( vit->size() <= mMaxWeights)
- continue;
-
- bChanged = true;
-
- // more than the defined maximum -> first sort by weight in descending order. That's
- // why we defined the < operator in such a weird way.
- std::sort( vit->begin(), vit->end());
-
- // now kill everything beyond the maximum count
- unsigned int m = vit->size();
- vit->erase( vit->begin() + mMaxWeights, vit->end());
- removed += m-vit->size();
-
- // and renormalize the weights
- float sum = 0.0f;
- for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it)
- sum += it->mWeight;
- for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it)
- it->mWeight /= sum;
- }
-
- if (bChanged) {
- // rebuild the vertex weight array for all bones
- typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
- WeightsPerBone boneWeights( pMesh->mNumBones);
- for( unsigned int a = 0; a < vertexWeights.size(); a++)
- {
- const std::vector<Weight>& vw = vertexWeights[a];
- for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
- boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
- }
-
- // and finally copy the vertex weight list over to the mesh's bones
- std::vector<bool> abNoNeed(pMesh->mNumBones,false);
- bChanged = false;
-
- for( unsigned int a = 0; a < pMesh->mNumBones; a++)
- {
- const std::vector<aiVertexWeight>& bw = boneWeights[a];
- aiBone* bone = pMesh->mBones[a];
-
- // ignore the bone if no vertex weights were removed there
-
- // FIX (Aramis, 07|22|08)
- // NO! we can't ignore it in this case ... it is possible that
- // the number of weights did not change, but the weight values did.
-
- // if( bw.size() == bone->mNumWeights)
- // continue;
-
- // FIX (Aramis, 07|21|08)
- // It is possible that all weights of a bone have been removed.
- // This would naturally cause an exception in &bw[0].
- if ( bw.empty() )
- {
- abNoNeed[a] = bChanged = true;
- continue;
- }
-
- // copy the weight list. should always be less weights than before, so we don't need a new allocation
- ai_assert( bw.size() <= bone->mNumWeights);
- bone->mNumWeights = (unsigned int) bw.size();
- ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
- }
-
- if (bChanged) {
- // the number of new bones is smaller than before, so we can reuse the old array
- aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
-
- for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
- if (*iter) {
- delete *ppcSrc;
- --pMesh->mNumBones;
- }
- else *ppcCur++ = *ppcSrc;
- ++ppcSrc;
- }
- }
-
- if (!DefaultLogger::isNullLogger()) {
- char buffer[1024];
- ::sprintf(buffer,"Removed %i weights. Input bones: %i. Output bones: %i",removed,old_bones,pMesh->mNumBones);
- DefaultLogger::get()->info(buffer);
- }
- }
+ if( !pMesh->HasBones())
+ return;
+
+ // collect all bone weights per vertex
+ typedef std::vector< std::vector< Weight > > WeightsPerVertex;
+ WeightsPerVertex vertexWeights( pMesh->mNumVertices);
+
+ // collect all weights per vertex
+ for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+ {
+ const aiBone* bone = pMesh->mBones[a];
+ for( unsigned int b = 0; b < bone->mNumWeights; b++)
+ {
+ const aiVertexWeight& w = bone->mWeights[b];
+ vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
+ }
+ }
+
+ unsigned int removed = 0, old_bones = pMesh->mNumBones;
+
+ // now cut the weight count if it exceeds the maximum
+ bool bChanged = false;
+ for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
+ {
+ if( vit->size() <= mMaxWeights)
+ continue;
+
+ bChanged = true;
+
+ // more than the defined maximum -> first sort by weight in descending order. That's
+ // why we defined the < operator in such a weird way.
+ std::sort( vit->begin(), vit->end());
+
+ // now kill everything beyond the maximum count
+ unsigned int m = vit->size();
+ vit->erase( vit->begin() + mMaxWeights, vit->end());
+ removed += m-vit->size();
+
+ // and renormalize the weights
+ float sum = 0.0f;
+ for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
+ sum += it->mWeight;
+ }
+ if( 0.0f != sum ) {
+ const float invSum = 1.0f / sum;
+ for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
+ it->mWeight *= invSum;
+ }
+ }
+ }
+
+ if (bChanged) {
+ // rebuild the vertex weight array for all bones
+ typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
+ WeightsPerBone boneWeights( pMesh->mNumBones);
+ for( unsigned int a = 0; a < vertexWeights.size(); a++)
+ {
+ const std::vector<Weight>& vw = vertexWeights[a];
+ for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
+ boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
+ }
+
+ // and finally copy the vertex weight list over to the mesh's bones
+ std::vector<bool> abNoNeed(pMesh->mNumBones,false);
+ bChanged = false;
+
+ for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+ {
+ const std::vector<aiVertexWeight>& bw = boneWeights[a];
+ aiBone* bone = pMesh->mBones[a];
+
+ if ( bw.empty() )
+ {
+ abNoNeed[a] = bChanged = true;
+ continue;
+ }
+
+ // copy the weight list. should always be less weights than before, so we don't need a new allocation
+ ai_assert( bw.size() <= bone->mNumWeights);
+ bone->mNumWeights = static_cast<unsigned int>( bw.size() );
+ ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
+ }
+
+ if (bChanged) {
+ // the number of new bones is smaller than before, so we can reuse the old array
+ aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
+
+ for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) {
+ if (*iter) {
+ delete *ppcSrc;
+ --pMesh->mNumBones;
+ }
+ else *ppcCur++ = *ppcSrc;
+ ++ppcSrc;
+ }
+ }
+
+ if (!DefaultLogger::isNullLogger()) {
+ char buffer[1024];
+ ai_snprintf(buffer,1024,"Removed %u weights. Input bones: %u. Output bones: %u",removed,old_bones,pMesh->mNumBones);
+ DefaultLogger::get()->info(buffer);
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
index 942c2ceb5..f6907cf26 100644
--- a/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
+++ b/src/3rdparty/assimp/code/LimitBoneWeightsProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -55,12 +55,12 @@ namespace Assimp
// corresponding values in all Assimp ports
// **********************************************************
-// Java: ConfigProperty.java,
+// Java: ConfigProperty.java,
// ConfigProperty.DEFAULT_BONE_WEIGHT_LIMIT
// **********************************************************
#if (!defined AI_LMW_MAX_WEIGHTS)
-# define AI_LMW_MAX_WEIGHTS 0x4
+# define AI_LMW_MAX_WEIGHTS 0x4
#endif // !! AI_LMW_MAX_WEIGHTS
// ---------------------------------------------------------------------------
@@ -74,67 +74,67 @@ class ASSIMP_API LimitBoneWeightsProcess : public BaseProcess
{
public:
- LimitBoneWeightsProcess();
- ~LimitBoneWeightsProcess();
+ LimitBoneWeightsProcess();
+ ~LimitBoneWeightsProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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);
public:
- // -------------------------------------------------------------------
- /** Limits the bone weight count for all vertices in the given mesh.
- * @param pMesh The mesh to process.
- */
- void ProcessMesh( aiMesh* pMesh);
+ // -------------------------------------------------------------------
+ /** Limits the bone weight count for all vertices in the given mesh.
+ * @param pMesh The mesh to process.
+ */
+ void ProcessMesh( aiMesh* pMesh);
- // -------------------------------------------------------------------
- /** 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);
+ // -------------------------------------------------------------------
+ /** 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);
public:
- // -------------------------------------------------------------------
- /** Describes a bone weight on a vertex */
- struct Weight
- {
- unsigned int mBone; ///< Index of the bone
- float mWeight; ///< Weight of that bone on this vertex
- Weight() { }
- Weight( unsigned int pBone, float pWeight)
- {
- mBone = pBone;
- mWeight = pWeight;
- }
-
- /** Comparision operator to sort bone weights by descending weight */
- bool operator < (const Weight& pWeight) const
- {
- return mWeight > pWeight.mWeight;
- }
- };
+ // -------------------------------------------------------------------
+ /** Describes a bone weight on a vertex */
+ struct Weight
+ {
+ unsigned int mBone; ///< Index of the bone
+ float mWeight; ///< Weight of that bone on this vertex
+ Weight() { }
+ Weight( unsigned int pBone, float pWeight)
+ {
+ mBone = pBone;
+ mWeight = pWeight;
+ }
+
+ /** Comparison operator to sort bone weights by descending weight */
+ bool operator < (const Weight& pWeight) const
+ {
+ return mWeight > pWeight.mWeight;
+ }
+ };
public:
- /** Maximum number of bones influencing any single vertex. */
- unsigned int mMaxWeights;
+ /** Maximum number of bones influencing any single vertex. */
+ unsigned int mMaxWeights;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/LineSplitter.h b/src/3rdparty/assimp/code/LineSplitter.h
index 03e54cfbe..0fa47380e 100644
--- a/src/3rdparty/assimp/code/LineSplitter.h
+++ b/src/3rdparty/assimp/code/LineSplitter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -57,16 +57,16 @@ namespace Assimp {
@code
for(LineSplitter splitter(stream);splitter;++splitter) {
- if (*splitter == "hi!") {
- ...
- }
+ if (*splitter == "hi!") {
+ ...
+ }
else if (splitter->substr(0,5) == "hello") {
- ...
- // access the third token in the line (tokens are space-separated)
- if (strtol(splitter[2]) > 5) { .. }
- }
+ ...
+ // access the third token in the line (tokens are space-separated)
+ if (strtol(splitter[2]) > 5) { .. }
+ }
- std::cout << "Current line is: " << splitter.get_index() << std::endl;
+ std::cout << "Current line is: " << splitter.get_index() << std::endl;
}
@endcode */
// ------------------------------------------------------------------------------------------------
@@ -74,164 +74,172 @@ class LineSplitter
{
public:
- typedef size_t line_idx;
+ typedef size_t line_idx;
public:
- // -----------------------------------------
- /** construct from existing stream reader
- note: trim is *always* assumed true if skyp_empty_lines==true
- */
- LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
- : stream(stream)
- , swallow()
- , skip_empty_lines(skip_empty_lines)
- , trim(trim)
- {
- cur.reserve(1024);
- operator++();
-
- idx = 0;
- }
+ // -----------------------------------------
+ /** construct from existing stream reader
+ note: trim is *always* assumed true if skyp_empty_lines==true
+ */
+ LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
+ : idx( 0 )
+ , stream(stream)
+ , swallow()
+ , skip_empty_lines(skip_empty_lines)
+ , trim(trim)
+ {
+ cur.reserve(1024);
+ operator++();
+
+ idx = 0;
+ }
+
+ ~LineSplitter() {
+ // empty
+ }
public:
- // -----------------------------------------
- /** pseudo-iterator increment */
- LineSplitter& operator++() {
- if(swallow) {
- swallow = false;
- return *this;
- }
- if (!*this) {
- throw std::logic_error("End of file, no more lines to be retrieved.");
- }
- char s;
- cur.clear();
- while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) {
- if (s == '\n' || s == '\r') {
- if (skip_empty_lines) {
- while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n'));
- if (stream.GetRemainingSize()) {
- stream.IncPtr(-1);
- }
- }
- else {
- // skip both potential line terminators but don't read past this line.
- if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) {
- stream.IncPtr(-1);
- }
- if (trim) {
- while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t'));
- if (stream.GetRemainingSize()) {
- stream.IncPtr(-1);
- }
- }
- }
- break;
- }
- cur += s;
- }
- ++idx;
- return *this;
- }
-
- // -----------------------------------------
- LineSplitter& operator++(int) {
- return ++(*this);
- }
-
- // -----------------------------------------
- /** get a pointer to the beginning of a particular token */
- const char* operator[] (size_t idx) const {
- const char* s = operator->()->c_str();
-
- SkipSpaces(&s);
- for(size_t i = 0; i < idx; ++i) {
-
- for(;!IsSpace(*s); ++s) {
- if(IsLineEnd(*s)) {
- throw std::range_error("Token index out of range, EOL reached");
- }
- }
- SkipSpaces(&s);
- }
- return s;
- }
-
- // -----------------------------------------
- /** extract the start positions of N tokens from the current line*/
- template <size_t N>
- void get_tokens(const char* (&tokens)[N]) const {
- const char* s = operator->()->c_str();
-
- SkipSpaces(&s);
- for(size_t i = 0; i < N; ++i) {
- if(IsLineEnd(*s)) {
-
- throw std::range_error("Token count out of range, EOL reached");
-
- }
- tokens[i] = s;
-
- for(;*s && !IsSpace(*s); ++s);
- SkipSpaces(&s);
- }
- }
-
- // -----------------------------------------
- /** member access */
- const std::string* operator -> () const {
- return &cur;
- }
-
- std::string operator* () const {
- return cur;
- }
-
- // -----------------------------------------
- /** boolean context */
- operator bool() const {
- return stream.GetRemainingSize()>0;
- }
-
- // -----------------------------------------
- /** line indices are zero-based, empty lines are included */
- operator line_idx() const {
- return idx;
- }
-
- line_idx get_index() const {
- return idx;
- }
-
- // -----------------------------------------
- /** access the underlying stream object */
- StreamReaderLE& get_stream() {
- return stream;
- }
-
- // -----------------------------------------
- /** !strcmp((*this)->substr(0,strlen(check)),check) */
- bool match_start(const char* check) {
- const size_t len = strlen(check);
-
- return len <= cur.length() && std::equal(check,check+len,cur.begin());
- }
-
-
- // -----------------------------------------
- /** swallow the next call to ++, return the previous value. */
- void swallow_next_increment() {
- swallow = true;
- }
+ // -----------------------------------------
+ /** pseudo-iterator increment */
+ LineSplitter& operator++() {
+ if(swallow) {
+ swallow = false;
+ return *this;
+ }
+ if (!*this) {
+ throw std::logic_error("End of file, no more lines to be retrieved.");
+ }
+ char s;
+ cur.clear();
+ while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) {
+ if (s == '\n' || s == '\r') {
+ if (skip_empty_lines) {
+ while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n'));
+ if (stream.GetRemainingSize()) {
+ stream.IncPtr(-1);
+ }
+ }
+ else {
+ // skip both potential line terminators but don't read past this line.
+ if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) {
+ stream.IncPtr(-1);
+ }
+ if (trim) {
+ while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\t'));
+ if (stream.GetRemainingSize()) {
+ stream.IncPtr(-1);
+ }
+ }
+ }
+ break;
+ }
+ cur += s;
+ }
+ ++idx;
+ return *this;
+ }
+
+ // -----------------------------------------
+ LineSplitter& operator++(int) {
+ return ++(*this);
+ }
+
+ // -----------------------------------------
+ /** get a pointer to the beginning of a particular token */
+ const char* operator[] (size_t idx) const {
+ const char* s = operator->()->c_str();
+
+ SkipSpaces(&s);
+ for(size_t i = 0; i < idx; ++i) {
+
+ for(;!IsSpace(*s); ++s) {
+ if(IsLineEnd(*s)) {
+ throw std::range_error("Token index out of range, EOL reached");
+ }
+ }
+ SkipSpaces(&s);
+ }
+ return s;
+ }
+
+ // -----------------------------------------
+ /** extract the start positions of N tokens from the current line*/
+ template <size_t N>
+ void get_tokens(const char* (&tokens)[N]) const {
+ const char* s = operator->()->c_str();
+
+ SkipSpaces(&s);
+ for(size_t i = 0; i < N; ++i) {
+ if(IsLineEnd(*s)) {
+
+ throw std::range_error("Token count out of range, EOL reached");
+
+ }
+ tokens[i] = s;
+
+ for(;*s && !IsSpace(*s); ++s);
+ SkipSpaces(&s);
+ }
+ }
+
+ // -----------------------------------------
+ /** member access */
+ const std::string* operator -> () const {
+ return &cur;
+ }
+
+ std::string operator* () const {
+ return cur;
+ }
+
+ // -----------------------------------------
+ /** boolean context */
+ operator bool() const {
+ return stream.GetRemainingSize()>0;
+ }
+
+ // -----------------------------------------
+ /** line indices are zero-based, empty lines are included */
+ operator line_idx() const {
+ return idx;
+ }
+
+ line_idx get_index() const {
+ return idx;
+ }
+
+ // -----------------------------------------
+ /** access the underlying stream object */
+ StreamReaderLE& get_stream() {
+ return stream;
+ }
+
+ // -----------------------------------------
+ /** !strcmp((*this)->substr(0,strlen(check)),check) */
+ bool match_start(const char* check) {
+ const size_t len = strlen(check);
+
+ return len <= cur.length() && std::equal(check,check+len,cur.begin());
+ }
+
+
+ // -----------------------------------------
+ /** swallow the next call to ++, return the previous value. */
+ void swallow_next_increment() {
+ swallow = true;
+ }
private:
+ LineSplitter( const LineSplitter & );
+ LineSplitter &operator = ( const LineSplitter & );
- line_idx idx;
- std::string cur;
- StreamReaderLE& stream;
- bool swallow, skip_empty_lines, trim;
+private:
+ line_idx idx;
+ std::string cur;
+ StreamReaderLE& stream;
+ bool swallow, skip_empty_lines, trim;
};
}
diff --git a/src/3rdparty/assimp/code/LogAux.h b/src/3rdparty/assimp/code/LogAux.h
index 4c7de04e6..f754903c6 100644
--- a/src/3rdparty/assimp/code/LogAux.h
+++ b/src/3rdparty/assimp/code/LogAux.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,85 +45,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_LOGAUX_H
#include "TinyFormatter.h"
+#include "Exceptional.h"
+#include <assimp/DefaultLogger.hpp>
namespace Assimp {
template <class TDeriving>
-class LogFunctions
+class LogFunctions
{
public:
- // ------------------------------------------------------------------------------------------------
- static void ThrowException(const std::string& msg)
- {
- throw DeadlyImportError(log_prefix+msg);
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogWarn(const Formatter::format& message) {
- if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->warn(log_prefix+(std::string)message);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogError(const Formatter::format& message) {
- if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->error(log_prefix+(std::string)message);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogInfo(const Formatter::format& message) {
- if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->info(log_prefix+(std::string)message);
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogDebug(const Formatter::format& message) {
- if (!DefaultLogger::isNullLogger()) {
- DefaultLogger::get()->debug(log_prefix+(std::string)message);
- }
- }
-
- // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
+ // ------------------------------------------------------------------------------------------------
+ static void ThrowException(const std::string& msg)
+ {
+ throw DeadlyImportError(log_prefix+msg);
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogWarn(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ DefaultLogger::get()->warn(log_prefix+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogError(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ DefaultLogger::get()->error(log_prefix+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogInfo(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ DefaultLogger::get()->info(log_prefix+(std::string)message);
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogDebug(const Formatter::format& message) {
+ if (!DefaultLogger::isNullLogger()) {
+ DefaultLogger::get()->debug(log_prefix+(std::string)message);
+ }
+ }
+
+ // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
- // ------------------------------------------------------------------------------------------------
- static void LogWarn (const char* message) {
- if (!DefaultLogger::isNullLogger()) {
- LogWarn(Formatter::format(message));
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogError (const char* message) {
- if (!DefaultLogger::isNullLogger()) {
- LogError(Formatter::format(message));
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogInfo (const char* message) {
- if (!DefaultLogger::isNullLogger()) {
- LogInfo(Formatter::format(message));
- }
- }
-
- // ------------------------------------------------------------------------------------------------
- static void LogDebug (const char* message) {
- if (!DefaultLogger::isNullLogger()) {
- LogDebug(Formatter::format(message));
- }
- }
+ // ------------------------------------------------------------------------------------------------
+ static void LogWarn (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogWarn(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogError (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogError(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogInfo (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogInfo(Formatter::format(message));
+ }
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ static void LogDebug (const char* message) {
+ if (!DefaultLogger::isNullLogger()) {
+ LogDebug(Formatter::format(message));
+ }
+ }
#endif
private:
- static const std::string log_prefix;
+ static const std::string log_prefix;
};
diff --git a/src/3rdparty/assimp/code/MD2FileData.h b/src/3rdparty/assimp/code/MD2FileData.h
index 058a5d500..f7a494335 100644
--- a/src/3rdparty/assimp/code/MD2FileData.h
+++ b/src/3rdparty/assimp/code/MD2FileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,76 +23,77 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file MD2FileData.h
- * @brief Defines helper data structures for importing MD2 files
+ * @brief Defines helper data structures for importing MD2 files
* http://linux.ucla.edu/~phaethon/q3/formats/md2-schoenblum.html
*/
#ifndef AI_MD2FILEHELPER_H_INC
#define AI_MD2FILEHELPER_H_INC
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/anim.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
+#include <stdint.h>
-#include "./../include/assimp/Compiler/pushpack1.h"
+#include <assimp/Compiler/pushpack1.h>
-namespace Assimp {
-namespace MD2 {
+namespace Assimp {
+namespace MD2 {
// to make it easier for us, we test the magic word against both "endianesses"
-#define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2")
-#define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI")
+#define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2")
+#define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI")
// common limitations
-#define AI_MD2_VERSION 15
-#define AI_MD2_MAXQPATH 64
-#define AI_MD2_MAX_FRAMES 512
-#define AI_MD2_MAX_SKINS 32
-#define AI_MD2_MAX_VERTS 2048
-#define AI_MD2_MAX_TRIANGLES 4096
+#define AI_MD2_VERSION 15
+#define AI_MD2_MAXQPATH 64
+#define AI_MD2_MAX_FRAMES 512
+#define AI_MD2_MAX_SKINS 32
+#define AI_MD2_MAX_VERTS 2048
+#define AI_MD2_MAX_TRIANGLES 4096
// ---------------------------------------------------------------------------
-/** \brief Data structure for the MD2 main header
+/** \brief Data structure for the MD2 main header
*/
struct Header
{
- uint32_t magic;
- uint32_t version;
- uint32_t skinWidth;
- uint32_t skinHeight;
- uint32_t frameSize;
- uint32_t numSkins;
- uint32_t numVertices;
- uint32_t numTexCoords;
- uint32_t numTriangles;
- uint32_t numGlCommands;
- uint32_t numFrames;
- uint32_t offsetSkins;
- uint32_t offsetTexCoords;
- uint32_t offsetTriangles;
- uint32_t offsetFrames;
- uint32_t offsetGlCommands;
- uint32_t offsetEnd;
+ uint32_t magic;
+ uint32_t version;
+ uint32_t skinWidth;
+ uint32_t skinHeight;
+ uint32_t frameSize;
+ uint32_t numSkins;
+ uint32_t numVertices;
+ uint32_t numTexCoords;
+ uint32_t numTriangles;
+ uint32_t numGlCommands;
+ uint32_t numFrames;
+ uint32_t offsetSkins;
+ uint32_t offsetTexCoords;
+ uint32_t offsetTriangles;
+ uint32_t offsetFrames;
+ uint32_t offsetGlCommands;
+ uint32_t offsetEnd;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 OpenGl draw command
+/** \brief Data structure for a MD2 OpenGl draw command
*/
struct GLCommand
{
@@ -101,52 +102,52 @@ struct GLCommand
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 triangle
+/** \brief Data structure for a MD2 triangle
*/
struct Triangle
{
- uint16_t vertexIndices[3];
- uint16_t textureIndices[3];
+ uint16_t vertexIndices[3];
+ uint16_t textureIndices[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 vertex
+/** \brief Data structure for a MD2 vertex
*/
struct Vertex
{
- uint8_t vertex[3];
- uint8_t lightNormalIndex;
+ uint8_t vertex[3];
+ uint8_t lightNormalIndex;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 frame
+/** \brief Data structure for a MD2 frame
*/
struct Frame
{
- float scale[3];
- float translate[3];
- char name[16];
- Vertex vertices[1];
+ float scale[3];
+ float translate[3];
+ char name[16];
+ Vertex vertices[1];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 texture coordinate
+/** \brief Data structure for a MD2 texture coordinate
*/
struct TexCoord
{
- uint16_t s;
- uint16_t t;
+ uint16_t s;
+ uint16_t t;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
-/** \brief Data structure for a MD2 skin
+/** \brief Data structure for a MD2 skin
*/
struct Skin
{
- char name[AI_MD2_MAXQPATH]; /* texture file name */
+ char name[AI_MD2_MAXQPATH]; /* texture file name */
} PACK_STRUCT;
-#include "./../include/assimp/Compiler/poppack1.h"
+#include <assimp/Compiler/poppack1.h>
// ---------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/MD2Loader.cpp b/src/3rdparty/assimp/code/MD2Loader.cpp
index 050555bad..b4c124774 100644
--- a/src/3rdparty/assimp/code/MD2Loader.cpp
+++ b/src/3rdparty/assimp/code/MD2Loader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,402 +25,433 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
/** @file Implementation of the MD2 importer class */
#include "MD2Loader.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
#include "MD2NormalTable.h" // shouldn't be included by other units
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <memory>
using namespace Assimp;
using namespace Assimp::MD2;
-
// helper macro to determine the size of an array
#if (!defined ARRAYSIZE)
-# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
-#endif
+# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
+#endif
static const aiImporterDesc desc = {
- "Quake II Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "md2"
+ "Quake II Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "md2"
};
// ------------------------------------------------------------------------------------------------
// Helper function to lookup a normal in Quake 2's precalculated table
void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
{
- // make sure the normal index has a valid value
- if (iNormalIndex >= ARRAYSIZE(g_avNormals)) {
- DefaultLogger::get()->warn("Index overflow in Quake II normal vector list");
- iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
- }
- vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
+ // make sure the normal index has a valid value
+ if (iNormalIndex >= ARRAYSIZE(g_avNormals)) {
+ DefaultLogger::get()->warn("Index overflow in Quake II normal vector list");
+ iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
+ }
+ vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MD2Importer::MD2Importer()
+ : configFrameID(),
+ m_pcHeader(),
+ mBuffer(),
+ fileSize()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MD2Importer::~MD2Importer()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "md2")
- return true;
-
- // if check for extension is not enough, check for the magic tokens
- if (!extension.length() || checkSig) {
- uint32_t tokens[1];
- tokens[0] = AI_MD2_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "md2")
+ return true;
+
+ // if check for extension is not enough, check for the magic tokens
+ if (!extension.length() || checkSig) {
+ uint32_t tokens[1];
+ tokens[0] = AI_MD2_MAGIC_NUMBER_LE;
+ return CheckMagicToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get a list of all extensions supported by this loader
const aiImporterDesc* MD2Importer::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MD2Importer::SetupProperties(const Importer* pImp)
{
- // The
- // AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,-1);
- if(static_cast<unsigned int>(-1) == configFrameID){
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The
+ // AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,-1);
+ if(static_cast<unsigned int>(-1) == configFrameID){
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
}
// ------------------------------------------------------------------------------------------------
// Validate the file header
void MD2Importer::ValidateHeader( )
{
- // check magic number
- if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
- m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
- {
- char szBuffer[5];
- szBuffer[0] = ((char*)&m_pcHeader->magic)[0];
- szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
- szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
- szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
- szBuffer[4] = '\0';
-
- throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
- "magic word found is " + std::string(szBuffer));
- }
-
- // check file format version
- if (m_pcHeader->version != 8)
- DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
-
- // check some values whether they are valid
- if (0 == m_pcHeader->numFrames)
- throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0");
-
- if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
- throw DeadlyImportError( "Invalid md2 file: File is too small");
-
- if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize ||
- m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize ||
- m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize ||
- m_pcHeader->offsetFrames + m_pcHeader->numFrames * sizeof (MD2::Frame) >= fileSize ||
- m_pcHeader->offsetEnd > fileSize)
- {
- throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file");
- }
-
- if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
- DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
- if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
- DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
- if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
- DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
-
- if (m_pcHeader->numFrames <= configFrameID )
- throw DeadlyImportError("The requested frame is not existing the file");
+ // check magic number
+ if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
+ m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
+ {
+ char szBuffer[5];
+ szBuffer[0] = ((char*)&m_pcHeader->magic)[0];
+ szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
+ szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
+ szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
+ szBuffer[4] = '\0';
+
+ throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
+ "magic word found is " + std::string(szBuffer));
+ }
+
+ // check file format version
+ if (m_pcHeader->version != 8)
+ DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
+
+ // check some values whether they are valid
+ if (0 == m_pcHeader->numFrames)
+ throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0");
+
+ if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
+ throw DeadlyImportError( "Invalid md2 file: File is too small");
+
+ if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) {
+ throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow");
+ }
+
+ if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) {
+ throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow");
+ }
+
+ if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) {
+ throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow");
+ }
+
+ if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) {
+ throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow");
+ }
+
+ if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) {
+ throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow");
+ }
+
+ // -1 because Frame already contains one
+ unsigned int frameSize = sizeof (MD2::Frame) + (m_pcHeader->numVertices - 1) * sizeof(MD2::Vertex);
+
+ if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize ||
+ m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize ||
+ m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize ||
+ m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize ||
+ m_pcHeader->offsetEnd > fileSize)
+ {
+ throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file");
+ }
+
+ if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
+ DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
+ if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
+ DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
+ if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
+ DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
+
+ if (m_pcHeader->numFrames <= configFrameID )
+ throw DeadlyImportError("The requested frame is not existing the file");
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MD2Importer::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void MD2Importer::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open MD2 file " + pFile + "");
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open MD2 file " + pFile + "");
- // check whether the md3 file is large enough to contain
- // at least the file header
- fileSize = (unsigned int)file->FileSize();
- if( fileSize < sizeof(MD2::Header))
- throw DeadlyImportError( "MD2 File is too small");
+ // check whether the md3 file is large enough to contain
+ // at least the file header
+ fileSize = (unsigned int)file->FileSize();
+ if( fileSize < sizeof(MD2::Header))
+ throw DeadlyImportError( "MD2 File is too small");
- std::vector<uint8_t> mBuffer2(fileSize);
- file->Read(&mBuffer2[0], 1, fileSize);
- mBuffer = &mBuffer2[0];
+ std::vector<uint8_t> mBuffer2(fileSize);
+ file->Read(&mBuffer2[0], 1, fileSize);
+ mBuffer = &mBuffer2[0];
- m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
+ m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN
- ByteSwap::Swap4(&m_pcHeader->frameSize);
- ByteSwap::Swap4(&m_pcHeader->magic);
- ByteSwap::Swap4(&m_pcHeader->numFrames);
- ByteSwap::Swap4(&m_pcHeader->numGlCommands);
- ByteSwap::Swap4(&m_pcHeader->numSkins);
- ByteSwap::Swap4(&m_pcHeader->numTexCoords);
- ByteSwap::Swap4(&m_pcHeader->numTriangles);
- ByteSwap::Swap4(&m_pcHeader->numVertices);
- ByteSwap::Swap4(&m_pcHeader->offsetEnd);
- ByteSwap::Swap4(&m_pcHeader->offsetFrames);
- ByteSwap::Swap4(&m_pcHeader->offsetGlCommands);
- ByteSwap::Swap4(&m_pcHeader->offsetSkins);
- ByteSwap::Swap4(&m_pcHeader->offsetTexCoords);
- ByteSwap::Swap4(&m_pcHeader->offsetTriangles);
- ByteSwap::Swap4(&m_pcHeader->skinHeight);
- ByteSwap::Swap4(&m_pcHeader->skinWidth);
- ByteSwap::Swap4(&m_pcHeader->version);
+ ByteSwap::Swap4(&m_pcHeader->frameSize);
+ ByteSwap::Swap4(&m_pcHeader->magic);
+ ByteSwap::Swap4(&m_pcHeader->numFrames);
+ ByteSwap::Swap4(&m_pcHeader->numGlCommands);
+ ByteSwap::Swap4(&m_pcHeader->numSkins);
+ ByteSwap::Swap4(&m_pcHeader->numTexCoords);
+ ByteSwap::Swap4(&m_pcHeader->numTriangles);
+ ByteSwap::Swap4(&m_pcHeader->numVertices);
+ ByteSwap::Swap4(&m_pcHeader->offsetEnd);
+ ByteSwap::Swap4(&m_pcHeader->offsetFrames);
+ ByteSwap::Swap4(&m_pcHeader->offsetGlCommands);
+ ByteSwap::Swap4(&m_pcHeader->offsetSkins);
+ ByteSwap::Swap4(&m_pcHeader->offsetTexCoords);
+ ByteSwap::Swap4(&m_pcHeader->offsetTriangles);
+ ByteSwap::Swap4(&m_pcHeader->skinHeight);
+ ByteSwap::Swap4(&m_pcHeader->skinWidth);
+ ByteSwap::Swap4(&m_pcHeader->version);
#endif
- ValidateHeader();
+ ValidateHeader();
- // there won't be more than one mesh inside the file
- pScene->mNumMaterials = 1;
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = new aiMaterial();
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
+ // there won't be more than one mesh inside the file
+ pScene->mNumMaterials = 1;
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = new aiMaterial();
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
- aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- // navigate to the begin of the frame data
- BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
- m_pcHeader + m_pcHeader->offsetFrames);
+ // navigate to the begin of the frame data
+ BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
+ m_pcHeader + m_pcHeader->offsetFrames);
- pcFrame += configFrameID;
+ pcFrame += configFrameID;
- // navigate to the begin of the triangle data
- MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
- m_pcHeader + m_pcHeader->offsetTriangles);
+ // navigate to the begin of the triangle data
+ MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
+ m_pcHeader + m_pcHeader->offsetTriangles);
- // navigate to the begin of the tex coords data
- BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*)
- m_pcHeader + m_pcHeader->offsetTexCoords);
+ // navigate to the begin of the tex coords data
+ BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*)
+ m_pcHeader + m_pcHeader->offsetTexCoords);
- // navigate to the begin of the vertex data
- BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices);
+ // navigate to the begin of the vertex data
+ BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices);
#ifdef AI_BUILD_BIG_ENDIAN
- for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i)
- {
- for (unsigned int p = 0; p < 3;++p)
- {
- ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]);
- ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]);
- }
- }
- for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i)
- {
- ByteSwap::Swap2(& pcTexCoords[i].s);
- ByteSwap::Swap2(& pcTexCoords[i].t);
- }
- ByteSwap::Swap4( & pcFrame->scale[0] );
- ByteSwap::Swap4( & pcFrame->scale[1] );
- ByteSwap::Swap4( & pcFrame->scale[2] );
- ByteSwap::Swap4( & pcFrame->translate[0] );
- ByteSwap::Swap4( & pcFrame->translate[1] );
- ByteSwap::Swap4( & pcFrame->translate[2] );
+ for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i)
+ {
+ for (unsigned int p = 0; p < 3;++p)
+ {
+ ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]);
+ ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]);
+ }
+ }
+ for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i)
+ {
+ ByteSwap::Swap2(& pcTexCoords[i].s);
+ ByteSwap::Swap2(& pcTexCoords[i].t);
+ }
+ ByteSwap::Swap4( & pcFrame->scale[0] );
+ ByteSwap::Swap4( & pcFrame->scale[1] );
+ ByteSwap::Swap4( & pcFrame->scale[2] );
+ ByteSwap::Swap4( & pcFrame->translate[0] );
+ ByteSwap::Swap4( & pcFrame->translate[1] );
+ ByteSwap::Swap4( & pcFrame->translate[2] );
#endif
- pcMesh->mNumFaces = m_pcHeader->numTriangles;
- pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles];
-
- // allocate output storage
- pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
-
- // Not sure whether there are MD2 files without texture coordinates
- // NOTE: texture coordinates can be there without a texture,
- // but a texture can't be there without a valid UV channel
- aiMaterial* pcHelper = (aiMaterial*)pScene->mMaterials[0];
- const int iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- if (m_pcHeader->numTexCoords && m_pcHeader->numSkins)
- {
- // navigate to the first texture associated with the mesh
- const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader +
- m_pcHeader->offsetSkins);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 1.0f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- if (pcSkins->name[0])
- {
- aiString szString;
- const size_t iLen = ::strlen(pcSkins->name);
- ::memcpy(szString.data,pcSkins->name,iLen);
- szString.data[iLen] = '\0';
- szString.length = iLen;
-
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- else{
- DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
- }
- }
- else {
- // apply a default material
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- aiString szName;
- szName.Set(AI_DEFAULT_MATERIAL_NAME);
- pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
-
- aiString sz;
-
- // TODO: Try to guess the name of the texture file from the model file name
-
- sz.Set("$texture_dummy.bmp");
- pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
-
-
- // now read all triangles of the first frame, apply scaling and translation
- unsigned int iCurrent = 0;
-
- float fDivisorU = 1.0f,fDivisorV = 1.0f;
- if (m_pcHeader->numTexCoords) {
- // allocate storage for texture coordinates, too
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
-
- // check whether the skin width or height are zero (this would
- // cause a division through zero)
- if (!m_pcHeader->skinWidth) {
- DefaultLogger::get()->error("MD2: No valid skin width given");
- }
- else fDivisorU = (float)m_pcHeader->skinWidth;
- if (!m_pcHeader->skinHeight){
- DefaultLogger::get()->error("MD2: No valid skin height given");
- }
- else fDivisorV = (float)m_pcHeader->skinHeight;
- }
-
- for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) {
- // Allocate the face
- pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3];
- pScene->mMeshes[0]->mFaces[i].mNumIndices = 3;
-
- // copy texture coordinates
- // check whether they are different from the previous value at this index.
- // In this case, create a full separate set of vertices/normals/texcoords
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
-
- // validate vertex indices
- unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
- if (iIndex >= m_pcHeader->numVertices) {
- DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
- iIndex = m_pcHeader->numVertices-1;
- }
-
- // read x,y, and z component of the vertex
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
-
- vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
- vec.x += pcFrame->translate[0];
-
- vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1];
- vec.y += pcFrame->translate[1];
-
- vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2];
- vec.z += pcFrame->translate[2];
-
- // read the normal vector from the precalculated normal table
- aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
- LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
-
- // flip z and y to become right-handed
- std::swap((float&)vNormal.z,(float&)vNormal.y);
- std::swap((float&)vec.z,(float&)vec.y);
-
- if (m_pcHeader->numTexCoords) {
- // validate texture coordinates
- iIndex = pcTriangles[i].textureIndices[c];
- if (iIndex >= m_pcHeader->numTexCoords) {
- DefaultLogger::get()->error("MD2: UV index is outside the allowed range");
- iIndex = m_pcHeader->numTexCoords-1;
- }
-
- aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
-
- // the texture coordinates are absolute values but we
- // need relative values between 0 and 1
- pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
- pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV;
- }
- pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
- }
- }
+ pcMesh->mNumFaces = m_pcHeader->numTriangles;
+ pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles];
+
+ // allocate output storage
+ pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ // Not sure whether there are MD2 files without texture coordinates
+ // NOTE: texture coordinates can be there without a texture,
+ // but a texture can't be there without a valid UV channel
+ aiMaterial* pcHelper = (aiMaterial*)pScene->mMaterials[0];
+ const int iMode = (int)aiShadingMode_Gouraud;
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ if (m_pcHeader->numTexCoords && m_pcHeader->numSkins)
+ {
+ // navigate to the first texture associated with the mesh
+ const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader +
+ m_pcHeader->offsetSkins);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 1.0f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ if (pcSkins->name[0])
+ {
+ aiString szString;
+ const size_t iLen = ::strlen(pcSkins->name);
+ ::memcpy(szString.data,pcSkins->name,iLen);
+ szString.data[iLen] = '\0';
+ szString.length = iLen;
+
+ pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ else{
+ DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
+ }
+ }
+ else {
+ // apply a default material
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.6f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString szName;
+ szName.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+
+ aiString sz;
+
+ // TODO: Try to guess the name of the texture file from the model file name
+
+ sz.Set("$texture_dummy.bmp");
+ pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+
+
+ // now read all triangles of the first frame, apply scaling and translation
+ unsigned int iCurrent = 0;
+
+ float fDivisorU = 1.0f,fDivisorV = 1.0f;
+ if (m_pcHeader->numTexCoords) {
+ // allocate storage for texture coordinates, too
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+
+ // check whether the skin width or height are zero (this would
+ // cause a division through zero)
+ if (!m_pcHeader->skinWidth) {
+ DefaultLogger::get()->error("MD2: No valid skin width given");
+ }
+ else fDivisorU = (float)m_pcHeader->skinWidth;
+ if (!m_pcHeader->skinHeight){
+ DefaultLogger::get()->error("MD2: No valid skin height given");
+ }
+ else fDivisorV = (float)m_pcHeader->skinHeight;
+ }
+
+ for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) {
+ // Allocate the face
+ pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3];
+ pScene->mMeshes[0]->mFaces[i].mNumIndices = 3;
+
+ // copy texture coordinates
+ // check whether they are different from the previous value at this index.
+ // In this case, create a full separate set of vertices/normals/texcoords
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+
+ // validate vertex indices
+ unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
+ if (iIndex >= m_pcHeader->numVertices) {
+ DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
+ iIndex = m_pcHeader->numVertices-1;
+ }
+
+ // read x,y, and z component of the vertex
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+
+ vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0];
+ vec.x += pcFrame->translate[0];
+
+ vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1];
+ vec.y += pcFrame->translate[1];
+
+ vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2];
+ vec.z += pcFrame->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
+ LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
+
+ // flip z and y to become right-handed
+ std::swap((float&)vNormal.z,(float&)vNormal.y);
+ std::swap((float&)vec.z,(float&)vec.y);
+
+ if (m_pcHeader->numTexCoords) {
+ // validate texture coordinates
+ iIndex = pcTriangles[i].textureIndices[c];
+ if (iIndex >= m_pcHeader->numTexCoords) {
+ DefaultLogger::get()->error("MD2: UV index is outside the allowed range");
+ iIndex = m_pcHeader->numTexCoords-1;
+ }
+
+ aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent];
+
+ // the texture coordinates are absolute values but we
+ // need relative values between 0 and 1
+ pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
+ pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV;
+ }
+ pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER
diff --git a/src/3rdparty/assimp/code/MD2Loader.h b/src/3rdparty/assimp/code/MD2Loader.h
index b164bae34..126c16359 100644
--- a/src/3rdparty/assimp/code/MD2Loader.h
+++ b/src/3rdparty/assimp/code/MD2Loader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,13 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MD2LOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
-
-struct aiNode;
+#include <assimp/types.h>
+#include "ByteSwapper.h"
#include "MD2FileData.h"
-namespace Assimp {
+struct aiNode;
+namespace Assimp {
using namespace MD2;
@@ -61,60 +61,60 @@ using namespace MD2;
class MD2Importer : public BaseImporter
{
public:
- MD2Importer();
- ~MD2Importer();
+ MD2Importer();
+ ~MD2Importer();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- /** Validate the header of the file
- */
- void ValidateHeader();
+ // -------------------------------------------------------------------
+ /** Validate the header of the file
+ */
+ void ValidateHeader();
protected:
- /** Configuration option: frame to be loaded */
- unsigned int configFrameID;
+ /** Configuration option: frame to be loaded */
+ unsigned int configFrameID;
- /** Header of the MD2 file */
- BE_NCONST MD2::Header* m_pcHeader;
+ /** Header of the MD2 file */
+ BE_NCONST MD2::Header* m_pcHeader;
- /** Buffer to hold the loaded file */
- BE_NCONST uint8_t* mBuffer;
+ /** Buffer to hold the loaded file */
+ BE_NCONST uint8_t* mBuffer;
- /** Size of the file, in bytes */
- unsigned int fileSize;
+ /** Size of the file, in bytes */
+ unsigned int fileSize;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/MD2NormalTable.h b/src/3rdparty/assimp/code/MD2NormalTable.h
index d1054b1e0..5b1344bd6 100644
--- a/src/3rdparty/assimp/code/MD2NormalTable.h
+++ b/src/3rdparty/assimp/code/MD2NormalTable.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,26 +23,26 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/*
- * @file Slightly modified version of the anorms.h header file
+ * @file Slightly modified version of the anorms.h header file
* released by ID software with the Quake 2 source code.
*
- * Table of normals used by MD2 models
+ * Table of normals used by MD2 models
*/
#ifndef AI_MDL_NORMALTABLE_H_INC
@@ -50,167 +50,167 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
float g_avNormals[162][3] = {
-{ -0.525731f, 0.000000f, 0.850651f },
-{ -0.442863f, 0.238856f, 0.864188f },
-{ -0.295242f, 0.000000f, 0.955423f },
-{ -0.309017f, 0.500000f, 0.809017f },
-{ -0.162460f, 0.262866f, 0.951056f },
-{ 0.000000f, 0.000000f, 1.000000f },
-{ 0.000000f, 0.850651f, 0.525731f },
-{ -0.147621f, 0.716567f, 0.681718f },
-{ 0.147621f, 0.716567f, 0.681718f },
-{ 0.000000f, 0.525731f, 0.850651f },
-{ 0.309017f, 0.500000f, 0.809017f },
-{ 0.525731f, 0.000000f, 0.850651f },
-{ 0.295242f, 0.000000f, 0.955423f },
-{ 0.442863f, 0.238856f, 0.864188f },
-{ 0.162460f, 0.262866f, 0.951056f },
-{ -0.681718f, 0.147621f, 0.716567f },
-{ -0.809017f, 0.309017f, 0.500000f },
-{ -0.587785f, 0.425325f, 0.688191f },
-{ -0.850651f, 0.525731f, 0.000000f },
-{ -0.864188f, 0.442863f, 0.238856f },
-{ -0.716567f, 0.681718f, 0.147621f },
-{ -0.688191f, 0.587785f, 0.425325f },
-{ -0.500000f, 0.809017f, 0.309017f },
-{ -0.238856f, 0.864188f, 0.442863f },
-{ -0.425325f, 0.688191f, 0.587785f },
-{ -0.716567f, 0.681718f, -0.147621f },
-{ -0.500000f, 0.809017f, -0.309017f },
-{ -0.525731f, 0.850651f, 0.000000f },
-{ 0.000000f, 0.850651f, -0.525731f },
-{ -0.238856f, 0.864188f, -0.442863f },
-{ 0.000000f, 0.955423f, -0.295242f },
-{ -0.262866f, 0.951056f, -0.162460f },
-{ 0.000000f, 1.000000f, 0.000000f },
-{ 0.000000f, 0.955423f, 0.295242f },
-{ -0.262866f, 0.951056f, 0.162460f },
-{ 0.238856f, 0.864188f, 0.442863f },
-{ 0.262866f, 0.951056f, 0.162460f },
-{ 0.500000f, 0.809017f, 0.309017f },
-{ 0.238856f, 0.864188f, -0.442863f },
-{ 0.262866f, 0.951056f, -0.162460f },
-{ 0.500000f, 0.809017f, -0.309017f },
-{ 0.850651f, 0.525731f, 0.000000f },
-{ 0.716567f, 0.681718f, 0.147621f },
-{ 0.716567f, 0.681718f, -0.147621f },
-{ 0.525731f, 0.850651f, 0.000000f },
-{ 0.425325f, 0.688191f, 0.587785f },
-{ 0.864188f, 0.442863f, 0.238856f },
-{ 0.688191f, 0.587785f, 0.425325f },
-{ 0.809017f, 0.309017f, 0.500000f },
-{ 0.681718f, 0.147621f, 0.716567f },
-{ 0.587785f, 0.425325f, 0.688191f },
-{ 0.955423f, 0.295242f, 0.000000f },
-{ 1.000000f, 0.000000f, 0.000000f },
-{ 0.951056f, 0.162460f, 0.262866f },
-{ 0.850651f, -0.525731f, 0.000000f },
-{ 0.955423f, -0.295242f, 0.000000f },
-{ 0.864188f, -0.442863f, 0.238856f },
-{ 0.951056f, -0.162460f, 0.262866f },
-{ 0.809017f, -0.309017f, 0.500000f },
-{ 0.681718f, -0.147621f, 0.716567f },
-{ 0.850651f, 0.000000f, 0.525731f },
-{ 0.864188f, 0.442863f, -0.238856f },
-{ 0.809017f, 0.309017f, -0.500000f },
-{ 0.951056f, 0.162460f, -0.262866f },
-{ 0.525731f, 0.000000f, -0.850651f },
-{ 0.681718f, 0.147621f, -0.716567f },
-{ 0.681718f, -0.147621f, -0.716567f },
-{ 0.850651f, 0.000000f, -0.525731f },
-{ 0.809017f, -0.309017f, -0.500000f },
-{ 0.864188f, -0.442863f, -0.238856f },
-{ 0.951056f, -0.162460f, -0.262866f },
-{ 0.147621f, 0.716567f, -0.681718f },
-{ 0.309017f, 0.500000f, -0.809017f },
-{ 0.425325f, 0.688191f, -0.587785f },
-{ 0.442863f, 0.238856f, -0.864188f },
-{ 0.587785f, 0.425325f, -0.688191f },
-{ 0.688191f, 0.587785f, -0.425325f },
-{ -0.147621f, 0.716567f, -0.681718f },
-{ -0.309017f, 0.500000f, -0.809017f },
-{ 0.000000f, 0.525731f, -0.850651f },
-{ -0.525731f, 0.000000f, -0.850651f },
-{ -0.442863f, 0.238856f, -0.864188f },
-{ -0.295242f, 0.000000f, -0.955423f },
-{ -0.162460f, 0.262866f, -0.951056f },
-{ 0.000000f, 0.000000f, -1.000000f },
-{ 0.295242f, 0.000000f, -0.955423f },
-{ 0.162460f, 0.262866f, -0.951056f },
-{ -0.442863f, -0.238856f, -0.864188f },
-{ -0.309017f, -0.500000f, -0.809017f },
-{ -0.162460f, -0.262866f, -0.951056f },
-{ 0.000000f, -0.850651f, -0.525731f },
-{ -0.147621f, -0.716567f, -0.681718f },
-{ 0.147621f, -0.716567f, -0.681718f },
-{ 0.000000f, -0.525731f, -0.850651f },
-{ 0.309017f, -0.500000f, -0.809017f },
-{ 0.442863f, -0.238856f, -0.864188f },
-{ 0.162460f, -0.262866f, -0.951056f },
-{ 0.238856f, -0.864188f, -0.442863f },
-{ 0.500000f, -0.809017f, -0.309017f },
-{ 0.425325f, -0.688191f, -0.587785f },
-{ 0.716567f, -0.681718f, -0.147621f },
-{ 0.688191f, -0.587785f, -0.425325f },
-{ 0.587785f, -0.425325f, -0.688191f },
-{ 0.000000f, -0.955423f, -0.295242f },
-{ 0.000000f, -1.000000f, 0.000000f },
-{ 0.262866f, -0.951056f, -0.162460f },
-{ 0.000000f, -0.850651f, 0.525731f },
-{ 0.000000f, -0.955423f, 0.295242f },
-{ 0.238856f, -0.864188f, 0.442863f },
-{ 0.262866f, -0.951056f, 0.162460f },
-{ 0.500000f, -0.809017f, 0.309017f },
-{ 0.716567f, -0.681718f, 0.147621f },
-{ 0.525731f, -0.850651f, 0.000000f },
-{ -0.238856f, -0.864188f, -0.442863f },
-{ -0.500000f, -0.809017f, -0.309017f },
-{ -0.262866f, -0.951056f, -0.162460f },
-{ -0.850651f, -0.525731f, 0.000000f },
-{ -0.716567f, -0.681718f, -0.147621f },
-{ -0.716567f, -0.681718f, 0.147621f },
-{ -0.525731f, -0.850651f, 0.000000f },
-{ -0.500000f, -0.809017f, 0.309017f },
-{ -0.238856f, -0.864188f, 0.442863f },
-{ -0.262866f, -0.951056f, 0.162460f },
-{ -0.864188f, -0.442863f, 0.238856f },
-{ -0.809017f, -0.309017f, 0.500000f },
-{ -0.688191f, -0.587785f, 0.425325f },
-{ -0.681718f, -0.147621f, 0.716567f },
-{ -0.442863f, -0.238856f, 0.864188f },
-{ -0.587785f, -0.425325f, 0.688191f },
-{ -0.309017f, -0.500000f, 0.809017f },
-{ -0.147621f, -0.716567f, 0.681718f },
-{ -0.425325f, -0.688191f, 0.587785f },
-{ -0.162460f, -0.262866f, 0.951056f },
-{ 0.442863f, -0.238856f, 0.864188f },
-{ 0.162460f, -0.262866f, 0.951056f },
-{ 0.309017f, -0.500000f, 0.809017f },
-{ 0.147621f, -0.716567f, 0.681718f },
-{ 0.000000f, -0.525731f, 0.850651f },
-{ 0.425325f, -0.688191f, 0.587785f },
-{ 0.587785f, -0.425325f, 0.688191f },
-{ 0.688191f, -0.587785f, 0.425325f },
-{ -0.955423f, 0.295242f, 0.000000f },
-{ -0.951056f, 0.162460f, 0.262866f },
-{ -1.000000f, 0.000000f, 0.000000f },
-{ -0.850651f, 0.000000f, 0.525731f },
-{ -0.955423f, -0.295242f, 0.000000f },
-{ -0.951056f, -0.162460f, 0.262866f },
-{ -0.864188f, 0.442863f, -0.238856f },
-{ -0.951056f, 0.162460f, -0.262866f },
-{ -0.809017f, 0.309017f, -0.500000f },
-{ -0.864188f, -0.442863f, -0.238856f },
-{ -0.951056f, -0.162460f, -0.262866f },
-{ -0.809017f, -0.309017f, -0.500000f },
-{ -0.681718f, 0.147621f, -0.716567f },
-{ -0.681718f, -0.147621f, -0.716567f },
-{ -0.850651f, 0.000000f, -0.525731f },
-{ -0.688191f, 0.587785f, -0.425325f },
-{ -0.587785f, 0.425325f, -0.688191f },
-{ -0.425325f, 0.688191f, -0.587785f },
-{ -0.425325f, -0.688191f, -0.587785f },
-{ -0.587785f, -0.425325f, -0.688191f },
+{ -0.525731f, 0.000000f, 0.850651f },
+{ -0.442863f, 0.238856f, 0.864188f },
+{ -0.295242f, 0.000000f, 0.955423f },
+{ -0.309017f, 0.500000f, 0.809017f },
+{ -0.162460f, 0.262866f, 0.951056f },
+{ 0.000000f, 0.000000f, 1.000000f },
+{ 0.000000f, 0.850651f, 0.525731f },
+{ -0.147621f, 0.716567f, 0.681718f },
+{ 0.147621f, 0.716567f, 0.681718f },
+{ 0.000000f, 0.525731f, 0.850651f },
+{ 0.309017f, 0.500000f, 0.809017f },
+{ 0.525731f, 0.000000f, 0.850651f },
+{ 0.295242f, 0.000000f, 0.955423f },
+{ 0.442863f, 0.238856f, 0.864188f },
+{ 0.162460f, 0.262866f, 0.951056f },
+{ -0.681718f, 0.147621f, 0.716567f },
+{ -0.809017f, 0.309017f, 0.500000f },
+{ -0.587785f, 0.425325f, 0.688191f },
+{ -0.850651f, 0.525731f, 0.000000f },
+{ -0.864188f, 0.442863f, 0.238856f },
+{ -0.716567f, 0.681718f, 0.147621f },
+{ -0.688191f, 0.587785f, 0.425325f },
+{ -0.500000f, 0.809017f, 0.309017f },
+{ -0.238856f, 0.864188f, 0.442863f },
+{ -0.425325f, 0.688191f, 0.587785f },
+{ -0.716567f, 0.681718f, -0.147621f },
+{ -0.500000f, 0.809017f, -0.309017f },
+{ -0.525731f, 0.850651f, 0.000000f },
+{ 0.000000f, 0.850651f, -0.525731f },
+{ -0.238856f, 0.864188f, -0.442863f },
+{ 0.000000f, 0.955423f, -0.295242f },
+{ -0.262866f, 0.951056f, -0.162460f },
+{ 0.000000f, 1.000000f, 0.000000f },
+{ 0.000000f, 0.955423f, 0.295242f },
+{ -0.262866f, 0.951056f, 0.162460f },
+{ 0.238856f, 0.864188f, 0.442863f },
+{ 0.262866f, 0.951056f, 0.162460f },
+{ 0.500000f, 0.809017f, 0.309017f },
+{ 0.238856f, 0.864188f, -0.442863f },
+{ 0.262866f, 0.951056f, -0.162460f },
+{ 0.500000f, 0.809017f, -0.309017f },
+{ 0.850651f, 0.525731f, 0.000000f },
+{ 0.716567f, 0.681718f, 0.147621f },
+{ 0.716567f, 0.681718f, -0.147621f },
+{ 0.525731f, 0.850651f, 0.000000f },
+{ 0.425325f, 0.688191f, 0.587785f },
+{ 0.864188f, 0.442863f, 0.238856f },
+{ 0.688191f, 0.587785f, 0.425325f },
+{ 0.809017f, 0.309017f, 0.500000f },
+{ 0.681718f, 0.147621f, 0.716567f },
+{ 0.587785f, 0.425325f, 0.688191f },
+{ 0.955423f, 0.295242f, 0.000000f },
+{ 1.000000f, 0.000000f, 0.000000f },
+{ 0.951056f, 0.162460f, 0.262866f },
+{ 0.850651f, -0.525731f, 0.000000f },
+{ 0.955423f, -0.295242f, 0.000000f },
+{ 0.864188f, -0.442863f, 0.238856f },
+{ 0.951056f, -0.162460f, 0.262866f },
+{ 0.809017f, -0.309017f, 0.500000f },
+{ 0.681718f, -0.147621f, 0.716567f },
+{ 0.850651f, 0.000000f, 0.525731f },
+{ 0.864188f, 0.442863f, -0.238856f },
+{ 0.809017f, 0.309017f, -0.500000f },
+{ 0.951056f, 0.162460f, -0.262866f },
+{ 0.525731f, 0.000000f, -0.850651f },
+{ 0.681718f, 0.147621f, -0.716567f },
+{ 0.681718f, -0.147621f, -0.716567f },
+{ 0.850651f, 0.000000f, -0.525731f },
+{ 0.809017f, -0.309017f, -0.500000f },
+{ 0.864188f, -0.442863f, -0.238856f },
+{ 0.951056f, -0.162460f, -0.262866f },
+{ 0.147621f, 0.716567f, -0.681718f },
+{ 0.309017f, 0.500000f, -0.809017f },
+{ 0.425325f, 0.688191f, -0.587785f },
+{ 0.442863f, 0.238856f, -0.864188f },
+{ 0.587785f, 0.425325f, -0.688191f },
+{ 0.688191f, 0.587785f, -0.425325f },
+{ -0.147621f, 0.716567f, -0.681718f },
+{ -0.309017f, 0.500000f, -0.809017f },
+{ 0.000000f, 0.525731f, -0.850651f },
+{ -0.525731f, 0.000000f, -0.850651f },
+{ -0.442863f, 0.238856f, -0.864188f },
+{ -0.295242f, 0.000000f, -0.955423f },
+{ -0.162460f, 0.262866f, -0.951056f },
+{ 0.000000f, 0.000000f, -1.000000f },
+{ 0.295242f, 0.000000f, -0.955423f },
+{ 0.162460f, 0.262866f, -0.951056f },
+{ -0.442863f, -0.238856f, -0.864188f },
+{ -0.309017f, -0.500000f, -0.809017f },
+{ -0.162460f, -0.262866f, -0.951056f },
+{ 0.000000f, -0.850651f, -0.525731f },
+{ -0.147621f, -0.716567f, -0.681718f },
+{ 0.147621f, -0.716567f, -0.681718f },
+{ 0.000000f, -0.525731f, -0.850651f },
+{ 0.309017f, -0.500000f, -0.809017f },
+{ 0.442863f, -0.238856f, -0.864188f },
+{ 0.162460f, -0.262866f, -0.951056f },
+{ 0.238856f, -0.864188f, -0.442863f },
+{ 0.500000f, -0.809017f, -0.309017f },
+{ 0.425325f, -0.688191f, -0.587785f },
+{ 0.716567f, -0.681718f, -0.147621f },
+{ 0.688191f, -0.587785f, -0.425325f },
+{ 0.587785f, -0.425325f, -0.688191f },
+{ 0.000000f, -0.955423f, -0.295242f },
+{ 0.000000f, -1.000000f, 0.000000f },
+{ 0.262866f, -0.951056f, -0.162460f },
+{ 0.000000f, -0.850651f, 0.525731f },
+{ 0.000000f, -0.955423f, 0.295242f },
+{ 0.238856f, -0.864188f, 0.442863f },
+{ 0.262866f, -0.951056f, 0.162460f },
+{ 0.500000f, -0.809017f, 0.309017f },
+{ 0.716567f, -0.681718f, 0.147621f },
+{ 0.525731f, -0.850651f, 0.000000f },
+{ -0.238856f, -0.864188f, -0.442863f },
+{ -0.500000f, -0.809017f, -0.309017f },
+{ -0.262866f, -0.951056f, -0.162460f },
+{ -0.850651f, -0.525731f, 0.000000f },
+{ -0.716567f, -0.681718f, -0.147621f },
+{ -0.716567f, -0.681718f, 0.147621f },
+{ -0.525731f, -0.850651f, 0.000000f },
+{ -0.500000f, -0.809017f, 0.309017f },
+{ -0.238856f, -0.864188f, 0.442863f },
+{ -0.262866f, -0.951056f, 0.162460f },
+{ -0.864188f, -0.442863f, 0.238856f },
+{ -0.809017f, -0.309017f, 0.500000f },
+{ -0.688191f, -0.587785f, 0.425325f },
+{ -0.681718f, -0.147621f, 0.716567f },
+{ -0.442863f, -0.238856f, 0.864188f },
+{ -0.587785f, -0.425325f, 0.688191f },
+{ -0.309017f, -0.500000f, 0.809017f },
+{ -0.147621f, -0.716567f, 0.681718f },
+{ -0.425325f, -0.688191f, 0.587785f },
+{ -0.162460f, -0.262866f, 0.951056f },
+{ 0.442863f, -0.238856f, 0.864188f },
+{ 0.162460f, -0.262866f, 0.951056f },
+{ 0.309017f, -0.500000f, 0.809017f },
+{ 0.147621f, -0.716567f, 0.681718f },
+{ 0.000000f, -0.525731f, 0.850651f },
+{ 0.425325f, -0.688191f, 0.587785f },
+{ 0.587785f, -0.425325f, 0.688191f },
+{ 0.688191f, -0.587785f, 0.425325f },
+{ -0.955423f, 0.295242f, 0.000000f },
+{ -0.951056f, 0.162460f, 0.262866f },
+{ -1.000000f, 0.000000f, 0.000000f },
+{ -0.850651f, 0.000000f, 0.525731f },
+{ -0.955423f, -0.295242f, 0.000000f },
+{ -0.951056f, -0.162460f, 0.262866f },
+{ -0.864188f, 0.442863f, -0.238856f },
+{ -0.951056f, 0.162460f, -0.262866f },
+{ -0.809017f, 0.309017f, -0.500000f },
+{ -0.864188f, -0.442863f, -0.238856f },
+{ -0.951056f, -0.162460f, -0.262866f },
+{ -0.809017f, -0.309017f, -0.500000f },
+{ -0.681718f, 0.147621f, -0.716567f },
+{ -0.681718f, -0.147621f, -0.716567f },
+{ -0.850651f, 0.000000f, -0.525731f },
+{ -0.688191f, 0.587785f, -0.425325f },
+{ -0.587785f, 0.425325f, -0.688191f },
+{ -0.425325f, 0.688191f, -0.587785f },
+{ -0.425325f, -0.688191f, -0.587785f },
+{ -0.587785f, -0.425325f, -0.688191f },
{ -0.688191f, -0.587785f, -0.425325f }
};
diff --git a/src/3rdparty/assimp/code/MD3FileData.h b/src/3rdparty/assimp/code/MD3FileData.h
index d24fa66d3..88a40f230 100644
--- a/src/3rdparty/assimp/code/MD3FileData.h
+++ b/src/3rdparty/assimp/code/MD3FileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,74 +49,75 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
#include <sstream>
+#include <stdint.h>
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/anim.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
-#include "./../include/assimp/Compiler/pushpack1.h"
+#include <assimp/Compiler/pushpack1.h>
-namespace Assimp {
-namespace MD3 {
+namespace Assimp {
+namespace MD3 {
// to make it easier for us, we test the magic word against both "endianesses"
-#define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3")
-#define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI")
+#define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3")
+#define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI")
// common limitations
-#define AI_MD3_VERSION 15
-#define AI_MD3_MAXQPATH 64
-#define AI_MD3_MAXFRAME 16
-#define AI_MD3_MAX_FRAMES 1024
-#define AI_MD3_MAX_TAGS 16
-#define AI_MD3_MAX_SURFACES 32
-#define AI_MD3_MAX_SHADERS 256
-#define AI_MD3_MAX_VERTS 4096
-#define AI_MD3_MAX_TRIANGLES 8192
+#define AI_MD3_VERSION 15
+#define AI_MD3_MAXQPATH 64
+#define AI_MD3_MAXFRAME 16
+#define AI_MD3_MAX_FRAMES 1024
+#define AI_MD3_MAX_TAGS 16
+#define AI_MD3_MAX_SURFACES 32
+#define AI_MD3_MAX_SHADERS 256
+#define AI_MD3_MAX_VERTS 4096
+#define AI_MD3_MAX_TRIANGLES 8192
// master scale factor for all vertices in a MD3 model
-#define AI_MD3_XYZ_SCALE (1.0f/64.0f)
+#define AI_MD3_XYZ_SCALE (1.0f/64.0f)
// -------------------------------------------------------------------------------
/** @brief Data structure for the MD3 main header
*/
struct Header
{
- //! magic number
- uint32_t IDENT;
+ //! magic number
+ uint32_t IDENT;
- //! file format version
- uint32_t VERSION;
+ //! file format version
+ uint32_t VERSION;
- //! original name in .pak archive
- char NAME[ AI_MD3_MAXQPATH ];
+ //! original name in .pak archive
+ char NAME[ AI_MD3_MAXQPATH ];
- //! unknown
- int32_t FLAGS;
+ //! unknown
+ int32_t FLAGS;
- //! number of frames in the file
- uint32_t NUM_FRAMES;
+ //! number of frames in the file
+ uint32_t NUM_FRAMES;
- //! number of tags in the file
- uint32_t NUM_TAGS;
+ //! number of tags in the file
+ uint32_t NUM_TAGS;
- //! number of surfaces in the file
- uint32_t NUM_SURFACES;
+ //! number of surfaces in the file
+ uint32_t NUM_SURFACES;
- //! number of skins in the file
- uint32_t NUM_SKINS;
+ //! number of skins in the file
+ uint32_t NUM_SKINS;
- //! offset of the first frame
- uint32_t OFS_FRAMES;
+ //! offset of the first frame
+ uint32_t OFS_FRAMES;
- //! offset of the first tag
- uint32_t OFS_TAGS;
+ //! offset of the first tag
+ uint32_t OFS_TAGS;
- //! offset of the first surface
- uint32_t OFS_SURFACES;
+ //! offset of the first surface
+ uint32_t OFS_SURFACES;
- //! end of file
- uint32_t OFS_EOF;
+ //! end of file
+ uint32_t OFS_EOF;
} PACK_STRUCT;
@@ -125,20 +126,20 @@ struct Header
*/
struct Frame
{
- //! minimum bounds
- aiVector3D min;
+ //! minimum bounds
+ aiVector3D min;
- //! maximum bounds
- aiVector3D max;
+ //! maximum bounds
+ aiVector3D max;
- //! local origin for this frame
- aiVector3D origin;
+ //! local origin for this frame
+ aiVector3D origin;
- //! radius of bounding sphere
- float radius;
+ //! radius of bounding sphere
+ float radius;
- //! name of frame
- char name[ AI_MD3_MAXFRAME ];
+ //! name of frame
+ char name[ AI_MD3_MAXFRAME ];
} PACK_STRUCT;
@@ -148,12 +149,12 @@ struct Frame
*/
struct Tag
{
- //! name of the tag
- char NAME[ AI_MD3_MAXQPATH ];
+ //! name of the tag
+ char NAME[ AI_MD3_MAXQPATH ];
- //! Local tag origin and orientation
- aiVector3D origin;
- float orientation[3][3];
+ //! Local tag origin and orientation
+ aiVector3D origin;
+ float orientation[3][3];
} PACK_STRUCT;
@@ -163,42 +164,42 @@ struct Tag
*/
struct Surface
{
- //! magic number
- int32_t IDENT;
+ //! magic number
+ int32_t IDENT;
- //! original name of the surface
- char NAME[ AI_MD3_MAXQPATH ];
+ //! original name of the surface
+ char NAME[ AI_MD3_MAXQPATH ];
- //! unknown
- int32_t FLAGS;
+ //! unknown
+ int32_t FLAGS;
- //! number of frames in the surface
- uint32_t NUM_FRAMES;
+ //! number of frames in the surface
+ uint32_t NUM_FRAMES;
- //! number of shaders in the surface
- uint32_t NUM_SHADER;
+ //! number of shaders in the surface
+ uint32_t NUM_SHADER;
- //! number of vertices in the surface
- uint32_t NUM_VERTICES;
+ //! number of vertices in the surface
+ uint32_t NUM_VERTICES;
- //! number of triangles in the surface
- uint32_t NUM_TRIANGLES;
+ //! number of triangles in the surface
+ uint32_t NUM_TRIANGLES;
- //! offset to the triangle data
- uint32_t OFS_TRIANGLES;
+ //! offset to the triangle data
+ uint32_t OFS_TRIANGLES;
- //! offset to the shader data
- uint32_t OFS_SHADERS;
+ //! offset to the shader data
+ uint32_t OFS_SHADERS;
- //! offset to the texture coordinate data
- uint32_t OFS_ST;
+ //! offset to the texture coordinate data
+ uint32_t OFS_ST;
- //! offset to the vertex/normal data
- uint32_t OFS_XYZNORMAL;
+ //! offset to the vertex/normal data
+ uint32_t OFS_XYZNORMAL;
- //! offset to the end of the Surface object
- int32_t OFS_END;
+ //! offset to the end of the Surface object
+ int32_t OFS_END;
} PACK_STRUCT;
// -------------------------------------------------------------------------------
@@ -206,11 +207,11 @@ struct Surface
*/
struct Shader
{
- //! filename of the shader
- char NAME[ AI_MD3_MAXQPATH ];
+ //! filename of the shader
+ char NAME[ AI_MD3_MAXQPATH ];
- //! index of the shader
- uint32_t SHADER_INDEX;
+ //! index of the shader
+ uint32_t SHADER_INDEX;
} PACK_STRUCT;
@@ -219,8 +220,8 @@ struct Shader
*/
struct Triangle
{
- //! triangle indices
- uint32_t INDEXES[3];
+ //! triangle indices
+ uint32_t INDEXES[3];
} PACK_STRUCT;
@@ -229,8 +230,8 @@ struct Triangle
*/
struct TexCoord
{
- //! UV coordinates
- float U,V;
+ //! UV coordinates
+ float U,V;
} PACK_STRUCT;
@@ -239,73 +240,73 @@ struct TexCoord
*/
struct Vertex
{
- //! X/Y/Z coordinates
- int16_t X,Y,Z;
+ //! X/Y/Z coordinates
+ int16_t X,Y,Z;
- //! encoded normal vector
- uint16_t NORMAL;
+ //! encoded normal vector
+ uint16_t NORMAL;
} PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h"
// -------------------------------------------------------------------------------
-/** @brief Unpack a Q3 16 bit vector to its full float3 representation
+/** @brief Unpack a Q3 16 bit vector to its full float3 representation
*
- * @param p_iNormal Input normal vector in latitude/longitude form
- * @param p_afOut Pointer to an array of three floats to receive the result
+ * @param p_iNormal Input normal vector in latitude/longitude form
+ * @param p_afOut Pointer to an array of three floats to receive the result
*
- * @note This has been taken from q3 source (misc_model.c)
+ * @note This has been taken from q3 source (misc_model.c)
*/
inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
{
- float lat = (float)(( p_iNormal >> 8u ) & 0xff);
- float lng = (float)(( p_iNormal & 0xff ));
- lat *= 3.141926f/128.0f;
- lng *= 3.141926f/128.0f;
-
- p_afOut[0] = cosf(lat) * sinf(lng);
- p_afOut[1] = sinf(lat) * sinf(lng);
- p_afOut[2] = cosf(lng);
- return;
+ float lat = (float)(( p_iNormal >> 8u ) & 0xff);
+ float lng = (float)(( p_iNormal & 0xff ));
+ lat *= 3.141926f/128.0f;
+ lng *= 3.141926f/128.0f;
+
+ p_afOut[0] = std::cos(lat) * std::sin(lng);
+ p_afOut[1] = std::sin(lat) * std::sin(lng);
+ p_afOut[2] = std::cos(lng);
+ return;
}
// -------------------------------------------------------------------------------
-/** @brief Pack a Q3 normal into 16bit latitute/longitude representation
- * @param p_vIn Input vector
- * @param p_iOut Output normal
+/** @brief Pack a Q3 normal into 16bit latitute/longitude representation
+ * @param p_vIn Input vector
+ * @param p_iOut Output normal
*
- * @note This has been taken from q3 source (mathlib.c)
+ * @note This has been taken from q3 source (mathlib.c)
*/
-inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut )
+inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut )
{
- // check for singularities
- if ( 0.0f == p_vIn[0] && 0.0f == p_vIn[1] )
- {
- if ( p_vIn[2] > 0.0f )
- {
- ((unsigned char*)&p_iOut)[0] = 0;
- ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 0
- }
- else
- {
- ((unsigned char*)&p_iOut)[0] = 128;
- ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 128
- }
- }
- else
- {
- int a, b;
-
- a = int(57.2957795f * ( atan2f( p_vIn[1], p_vIn[0] ) ) * (255.0f / 360.0f ));
- a &= 0xff;
-
- b = int(57.2957795f * ( acosf( p_vIn[2] ) ) * ( 255.0f / 360.0f ));
- b &= 0xff;
-
- ((unsigned char*)&p_iOut)[0] = b; // longitude
- ((unsigned char*)&p_iOut)[1] = a; // lattitude
- }
+ // check for singularities
+ if ( 0.0f == p_vIn[0] && 0.0f == p_vIn[1] )
+ {
+ if ( p_vIn[2] > 0.0f )
+ {
+ ((unsigned char*)&p_iOut)[0] = 0;
+ ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 0
+ }
+ else
+ {
+ ((unsigned char*)&p_iOut)[0] = 128;
+ ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 128
+ }
+ }
+ else
+ {
+ int a, b;
+
+ a = int(57.2957795f * ( atan2f( p_vIn[1], p_vIn[0] ) ) * (255.0f / 360.0f ));
+ a &= 0xff;
+
+ b = int(57.2957795f * ( acosf( p_vIn[2] ) ) * ( 255.0f / 360.0f ));
+ b &= 0xff;
+
+ ((unsigned char*)&p_iOut)[0] = b; // longitude
+ ((unsigned char*)&p_iOut)[1] = a; // latitude
+ }
}
}
diff --git a/src/3rdparty/assimp/code/MD3Loader.cpp b/src/3rdparty/assimp/code/MD3Loader.cpp
index 74c585aac..8294da489 100644
--- a/src/3rdparty/assimp/code/MD3Loader.cpp
+++ b/src/3rdparty/assimp/code/MD3Loader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,1033 +25,1070 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file MD3Loader.cpp
- * @brief Implementation of the MD3 importer class
- *
- * Sources:
+ * @brief Implementation of the MD3 importer class
+ *
+ * Sources:
* http://www.gamers.org/dEngine/quake3/UQ3S
* http://linux.ucla.edu/~phaethon/q3/formats/md3format.html
* http://www.heppler.com/shader/shader/
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER
#include "MD3Loader.h"
-#include "ByteSwap.h"
#include "SceneCombiner.h"
#include "GenericProperty.h"
#include "RemoveComments.h"
#include "ParsingUtils.h"
#include "Importer.h"
+#include <assimp/DefaultLogger.hpp>
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <cctype>
+
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Quake III Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "md3"
+ "Quake III Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "md3"
};
// ------------------------------------------------------------------------------------------------
// Convert a Q3 shader blend function to the appropriate enum value
Q3Shader::BlendFunc StringToBlendFunc(const std::string& m)
{
- if (m == "GL_ONE") {
- return Q3Shader::BLEND_GL_ONE;
- }
- if (m == "GL_ZERO") {
- return Q3Shader::BLEND_GL_ZERO;
- }
- if (m == "GL_SRC_ALPHA") {
- return Q3Shader::BLEND_GL_SRC_ALPHA;
- }
- if (m == "GL_ONE_MINUS_SRC_ALPHA") {
- return Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
- }
- if (m == "GL_ONE_MINUS_DST_COLOR") {
- return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
- }
- DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m);
- return Q3Shader::BLEND_NONE;
+ if (m == "GL_ONE") {
+ return Q3Shader::BLEND_GL_ONE;
+ }
+ if (m == "GL_ZERO") {
+ return Q3Shader::BLEND_GL_ZERO;
+ }
+ if (m == "GL_SRC_ALPHA") {
+ return Q3Shader::BLEND_GL_SRC_ALPHA;
+ }
+ if (m == "GL_ONE_MINUS_SRC_ALPHA") {
+ return Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ }
+ if (m == "GL_ONE_MINUS_DST_COLOR") {
+ return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
+ }
+ DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m);
+ return Q3Shader::BLEND_NONE;
}
// ------------------------------------------------------------------------------------------------
// Load a Quake 3 shader
bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io)
{
- boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt"));
- if (!file.get())
- return false; // if we can't access the file, don't worry and return
-
- DefaultLogger::get()->info("Loading Quake3 shader file " + pFile);
-
- // read file in memory
- const size_t s = file->FileSize();
- std::vector<char> _buff(s+1);
- file->Read(&_buff[0],s,1);
- _buff[s] = 0;
-
- // remove comments from it (C++ style)
- CommentRemover::RemoveLineComments("//",&_buff[0]);
- const char* buff = &_buff[0];
-
- Q3Shader::ShaderDataBlock* curData = NULL;
- Q3Shader::ShaderMapBlock* curMap = NULL;
-
- // read line per line
- for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
-
- if (*buff == '{') {
- ++buff;
-
- // append to last section, if any
- if (!curData) {
- DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'");
- return true; // still no failure, the file is there
- }
-
- // read this data section
- for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
- if (*buff == '{') {
- ++buff;
- // add new map section
- curData->maps.push_back(Q3Shader::ShaderMapBlock());
- curMap = &curData->maps.back();
-
- for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
- // 'map' - Specifies texture file name
- if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) {
- curMap->name = GetNextToken(buff);
- }
- // 'blendfunc' - Alpha blending mode
- else if (TokenMatchI(buff,"blendfunc",9)) {
- const std::string blend_src = GetNextToken(buff);
- if (blend_src == "add") {
- curMap->blend_src = Q3Shader::BLEND_GL_ONE;
- curMap->blend_dest = Q3Shader::BLEND_GL_ONE;
- }
- else if (blend_src == "filter") {
- curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR;
- curMap->blend_dest = Q3Shader::BLEND_GL_ZERO;
- }
- else if (blend_src == "blend") {
- curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA;
- curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
- }
- else {
- curMap->blend_src = StringToBlendFunc(blend_src);
- curMap->blend_dest = StringToBlendFunc(GetNextToken(buff));
- }
- }
- // 'alphafunc' - Alpha testing mode
- else if (TokenMatchI(buff,"alphafunc",9)) {
- const std::string at = GetNextToken(buff);
- if (at == "GT0") {
- curMap->alpha_test = Q3Shader::AT_GT0;
- }
- else if (at == "LT128") {
- curMap->alpha_test = Q3Shader::AT_LT128;
- }
- else if (at == "GE128") {
- curMap->alpha_test = Q3Shader::AT_GE128;
- }
- }
- else if (*buff == '}') {
- ++buff;
- // close this map section
- curMap = NULL;
- break;
- }
- }
-
- }
- else if (*buff == '}') {
- ++buff;
- curData = NULL;
- break;
- }
-
- // 'cull' specifies culling behaviour for the model
- else if (TokenMatchI(buff,"cull",4)) {
- SkipSpaces(&buff);
- if (!ASSIMP_strincmp(buff,"back",4)) {
- curData->cull = Q3Shader::CULL_CCW;
- }
- else if (!ASSIMP_strincmp(buff,"front",5)) {
- curData->cull = Q3Shader::CULL_CW;
- }
- else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) {
- curData->cull = Q3Shader::CULL_NONE;
- }
- else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode");
- }
- }
- }
-
- else {
- // add new section
- fill.blocks.push_back(Q3Shader::ShaderDataBlock());
- curData = &fill.blocks.back();
-
- // get the name of this section
- curData->name = GetNextToken(buff);
- }
- }
- return true;
+ std::unique_ptr<IOStream> file( io->Open( pFile, "rt"));
+ if (!file.get())
+ return false; // if we can't access the file, don't worry and return
+
+ DefaultLogger::get()->info("Loading Quake3 shader file " + pFile);
+
+ // read file in memory
+ const size_t s = file->FileSize();
+ std::vector<char> _buff(s+1);
+ file->Read(&_buff[0],s,1);
+ _buff[s] = 0;
+
+ // remove comments from it (C++ style)
+ CommentRemover::RemoveLineComments("//",&_buff[0]);
+ const char* buff = &_buff[0];
+
+ Q3Shader::ShaderDataBlock* curData = NULL;
+ Q3Shader::ShaderMapBlock* curMap = NULL;
+
+ // read line per line
+ for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
+
+ if (*buff == '{') {
+ ++buff;
+
+ // append to last section, if any
+ if (!curData) {
+ DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'");
+ return true; // still no failure, the file is there
+ }
+
+ // read this data section
+ for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
+ if (*buff == '{') {
+ ++buff;
+ // add new map section
+ curData->maps.push_back(Q3Shader::ShaderMapBlock());
+ curMap = &curData->maps.back();
+
+ for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
+ // 'map' - Specifies texture file name
+ if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) {
+ curMap->name = GetNextToken(buff);
+ }
+ // 'blendfunc' - Alpha blending mode
+ else if (TokenMatchI(buff,"blendfunc",9)) {
+ const std::string blend_src = GetNextToken(buff);
+ if (blend_src == "add") {
+ curMap->blend_src = Q3Shader::BLEND_GL_ONE;
+ curMap->blend_dest = Q3Shader::BLEND_GL_ONE;
+ }
+ else if (blend_src == "filter") {
+ curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR;
+ curMap->blend_dest = Q3Shader::BLEND_GL_ZERO;
+ }
+ else if (blend_src == "blend") {
+ curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA;
+ curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ }
+ else {
+ curMap->blend_src = StringToBlendFunc(blend_src);
+ curMap->blend_dest = StringToBlendFunc(GetNextToken(buff));
+ }
+ }
+ // 'alphafunc' - Alpha testing mode
+ else if (TokenMatchI(buff,"alphafunc",9)) {
+ const std::string at = GetNextToken(buff);
+ if (at == "GT0") {
+ curMap->alpha_test = Q3Shader::AT_GT0;
+ }
+ else if (at == "LT128") {
+ curMap->alpha_test = Q3Shader::AT_LT128;
+ }
+ else if (at == "GE128") {
+ curMap->alpha_test = Q3Shader::AT_GE128;
+ }
+ }
+ else if (*buff == '}') {
+ ++buff;
+ // close this map section
+ curMap = NULL;
+ break;
+ }
+ }
+
+ }
+ else if (*buff == '}') {
+ ++buff;
+ curData = NULL;
+ break;
+ }
+
+ // 'cull' specifies culling behaviour for the model
+ else if (TokenMatchI(buff,"cull",4)) {
+ SkipSpaces(&buff);
+ if (!ASSIMP_strincmp(buff,"back",4)) {
+ curData->cull = Q3Shader::CULL_CCW;
+ }
+ else if (!ASSIMP_strincmp(buff,"front",5)) {
+ curData->cull = Q3Shader::CULL_CW;
+ }
+ else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) {
+ curData->cull = Q3Shader::CULL_NONE;
+ }
+ else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode");
+ }
+ }
+ }
+
+ else {
+ // add new section
+ fill.blocks.push_back(Q3Shader::ShaderDataBlock());
+ curData = &fill.blocks.back();
+
+ // get the name of this section
+ curData->name = GetNextToken(buff);
+ }
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Load a Quake 3 skin
bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
{
- boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt"));
- if (!file.get())
- return false; // if we can't access the file, don't worry and return
+ std::unique_ptr<IOStream> file( io->Open( pFile, "rt"));
+ if (!file.get())
+ return false; // if we can't access the file, don't worry and return
- DefaultLogger::get()->info("Loading Quake3 skin file " + pFile);
+ DefaultLogger::get()->info("Loading Quake3 skin file " + pFile);
- // read file in memory
- const size_t s = file->FileSize();
- std::vector<char> _buff(s+1);const char* buff = &_buff[0];
- file->Read(&_buff[0],s,1);
- _buff[s] = 0;
+ // read file in memory
+ const size_t s = file->FileSize();
+ std::vector<char> _buff(s+1);const char* buff = &_buff[0];
+ file->Read(&_buff[0],s,1);
+ _buff[s] = 0;
- // remove commas
- std::replace(_buff.begin(),_buff.end(),',',' ');
+ // remove commas
+ std::replace(_buff.begin(),_buff.end(),',',' ');
- // read token by token and fill output table
- for (;*buff;) {
- SkipSpacesAndLineEnd(&buff);
+ // read token by token and fill output table
+ for (;*buff;) {
+ SkipSpacesAndLineEnd(&buff);
- // get first identifier
- std::string ss = GetNextToken(buff);
-
- // ignore tokens starting with tag_
- if (!::strncmp(&ss[0],"tag_",std::min((size_t)4, ss.length())))
- continue;
+ // get first identifier
+ std::string ss = GetNextToken(buff);
- fill.textures.push_back(SkinData::TextureEntry());
- SkinData::TextureEntry& s = fill.textures.back();
+ // ignore tokens starting with tag_
+ if (!::strncmp(&ss[0],"tag_",std::min((size_t)4, ss.length())))
+ continue;
- s.first = ss;
- s.second = GetNextToken(buff);
- }
- return true;
+ fill.textures.push_back(SkinData::TextureEntry());
+ SkinData::TextureEntry& s = fill.textures.back();
+
+ s.first = ss;
+ s.second = GetNextToken(buff);
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Convert Q3Shader to material
void Q3Shader::ConvertShaderToMaterial(aiMaterial* out, const ShaderDataBlock& shader)
{
- ai_assert(NULL != out);
-
- /* IMPORTANT: This is not a real conversion. Actually we're just guessing and
- * hacking around to build an aiMaterial that looks nearly equal to the
- * original Quake 3 shader. We're missing some important features like
- * animatable material properties in our material system, but at least
- * multiple textures should be handled correctly.
- */
-
- // Two-sided material?
- if (shader.cull == Q3Shader::CULL_NONE) {
- const int twosided = 1;
- out->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
- }
-
- unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm =0;
-
- // Iterate through all textures
- for (std::list< Q3Shader::ShaderMapBlock >::const_iterator it = shader.maps.begin(); it != shader.maps.end();++it) {
-
- // CONVERSION BEHAVIOUR:
- //
- //
- // If the texture is additive
- // - if it is the first texture, assume additive blending for the whole material
- // - otherwise register it as emissive texture.
- //
- // If the texture is using standard blend (or if the blend mode is unknown)
- // - if first texture: assume default blending for material
- // - in any case: set it as diffuse texture
- //
- // If the texture is using 'filter' blending
- // - take as lightmap
- //
- // Textures with alpha funcs
- // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set)
- aiString s((*it).name);
- aiTextureType type; unsigned int index;
-
- if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) {
- if (it == shader.maps.begin()) {
- const int additive = aiBlendMode_Additive;
- out->AddProperty(&additive,1,AI_MATKEY_BLEND_FUNC);
-
- index = cur_diffuse++;
- type = aiTextureType_DIFFUSE;
- }
- else {
- index = cur_emissive++;
- type = aiTextureType_EMISSIVE;
- }
- }
- else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) {
- index = cur_lm++;
- type = aiTextureType_LIGHTMAP;
- }
- else {
- const int blend = aiBlendMode_Default;
- out->AddProperty(&blend,1,AI_MATKEY_BLEND_FUNC);
-
- index = cur_diffuse++;
- type = aiTextureType_DIFFUSE;
- }
-
- // setup texture
- out->AddProperty(&s,AI_MATKEY_TEXTURE(type,index));
-
- // setup texture flags
- const int use_alpha = ((*it).alpha_test != Q3Shader::AT_NONE ? aiTextureFlags_UseAlpha : aiTextureFlags_IgnoreAlpha);
- out->AddProperty(&use_alpha,1,AI_MATKEY_TEXFLAGS(type,index));
- }
- // If at least one emissive texture was set, set the emissive base color to 1 to ensure
- // the texture is actually displayed.
- if (0 != cur_emissive) {
- aiColor3D one(1.f,1.f,1.f);
- out->AddProperty(&one,1,AI_MATKEY_COLOR_EMISSIVE);
- }
+ ai_assert(NULL != out);
+
+ /* IMPORTANT: This is not a real conversion. Actually we're just guessing and
+ * hacking around to build an aiMaterial that looks nearly equal to the
+ * original Quake 3 shader. We're missing some important features like
+ * animatable material properties in our material system, but at least
+ * multiple textures should be handled correctly.
+ */
+
+ // Two-sided material?
+ if (shader.cull == Q3Shader::CULL_NONE) {
+ const int twosided = 1;
+ out->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
+ }
+
+ unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm =0;
+
+ // Iterate through all textures
+ for (std::list< Q3Shader::ShaderMapBlock >::const_iterator it = shader.maps.begin(); it != shader.maps.end();++it) {
+
+ // CONVERSION BEHAVIOUR:
+ //
+ //
+ // If the texture is additive
+ // - if it is the first texture, assume additive blending for the whole material
+ // - otherwise register it as emissive texture.
+ //
+ // If the texture is using standard blend (or if the blend mode is unknown)
+ // - if first texture: assume default blending for material
+ // - in any case: set it as diffuse texture
+ //
+ // If the texture is using 'filter' blending
+ // - take as lightmap
+ //
+ // Textures with alpha funcs
+ // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set)
+ aiString s((*it).name);
+ aiTextureType type; unsigned int index;
+
+ if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) {
+ if (it == shader.maps.begin()) {
+ const int additive = aiBlendMode_Additive;
+ out->AddProperty(&additive,1,AI_MATKEY_BLEND_FUNC);
+
+ index = cur_diffuse++;
+ type = aiTextureType_DIFFUSE;
+ }
+ else {
+ index = cur_emissive++;
+ type = aiTextureType_EMISSIVE;
+ }
+ }
+ else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) {
+ index = cur_lm++;
+ type = aiTextureType_LIGHTMAP;
+ }
+ else {
+ const int blend = aiBlendMode_Default;
+ out->AddProperty(&blend,1,AI_MATKEY_BLEND_FUNC);
+
+ index = cur_diffuse++;
+ type = aiTextureType_DIFFUSE;
+ }
+
+ // setup texture
+ out->AddProperty(&s,AI_MATKEY_TEXTURE(type,index));
+
+ // setup texture flags
+ const int use_alpha = ((*it).alpha_test != Q3Shader::AT_NONE ? aiTextureFlags_UseAlpha : aiTextureFlags_IgnoreAlpha);
+ out->AddProperty(&use_alpha,1,AI_MATKEY_TEXFLAGS(type,index));
+ }
+ // If at least one emissive texture was set, set the emissive base color to 1 to ensure
+ // the texture is actually displayed.
+ if (0 != cur_emissive) {
+ aiColor3D one(1.f,1.f,1.f);
+ out->AddProperty(&one,1,AI_MATKEY_COLOR_EMISSIVE);
+ }
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MD3Importer::MD3Importer()
-: configFrameID (0)
-, configHandleMP (true)
+ : configFrameID (0)
+ , configHandleMP (true)
+ , configSpeedFlag()
+ , pcHeader()
+ , mBuffer()
+ , fileSize()
+ , mScene()
+ , mIOHandler()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MD3Importer::~MD3Importer()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "md3")
- return true;
-
- // if check for extension is not enough, check for the magic tokens
- if (!extension.length() || checkSig) {
- uint32_t tokens[1];
- tokens[0] = AI_MD3_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "md3")
+ return true;
+
+ // if check for extension is not enough, check for the magic tokens
+ if (!extension.length() || checkSig) {
+ uint32_t tokens[1];
+ tokens[0] = AI_MD3_MAGIC_NUMBER_LE;
+ return CheckMagicToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateHeaderOffsets()
{
- // Check magic number
- if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
- pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
- throw DeadlyImportError( "Invalid MD3 file: Magic bytes not found");
-
- // Check file format version
- if (pcHeader->VERSION > 15)
- DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
-
- // Check some offset values whether they are valid
- if (!pcHeader->NUM_SURFACES)
- throw DeadlyImportError( "Invalid md3 file: NUM_SURFACES is 0");
-
- if (pcHeader->OFS_FRAMES >= fileSize || pcHeader->OFS_SURFACES >= fileSize ||
- pcHeader->OFS_EOF > fileSize) {
- throw DeadlyImportError("Invalid MD3 header: some offsets are outside the file");
+ // Check magic number
+ if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE &&
+ pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE)
+ throw DeadlyImportError( "Invalid MD3 file: Magic bytes not found");
+
+ // Check file format version
+ if (pcHeader->VERSION > 15)
+ DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
+
+ // Check some offset values whether they are valid
+ if (!pcHeader->NUM_SURFACES)
+ throw DeadlyImportError( "Invalid md3 file: NUM_SURFACES is 0");
+
+ if (pcHeader->OFS_FRAMES >= fileSize || pcHeader->OFS_SURFACES >= fileSize ||
+ pcHeader->OFS_EOF > fileSize) {
+ throw DeadlyImportError("Invalid MD3 header: some offsets are outside the file");
+ }
+
+ if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(MD3::Surface)) {
+ throw DeadlyImportError("Invalid MD3 header: too many surfaces, would overflow");
}
- if (pcHeader->NUM_FRAMES <= configFrameID )
- throw DeadlyImportError("The requested frame is not existing the file");
+ if (pcHeader->OFS_SURFACES + pcHeader->NUM_SURFACES * sizeof(MD3::Surface) >= fileSize) {
+ throw DeadlyImportError("Invalid MD3 header: some surfaces are outside the file");
+ }
+
+ if (pcHeader->NUM_FRAMES <= configFrameID )
+ throw DeadlyImportError("The requested frame is not existing the file");
}
// ------------------------------------------------------------------------------------------------
void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
{
- // Calculate the relative offset of the surface
- const int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer);
-
- // Check whether all data chunks are inside the valid range
- if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize ||
- pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize ||
- pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize ||
- pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize) {
-
- throw DeadlyImportError("Invalid MD3 surface header: some offsets are outside the file");
- }
-
- // Check whether all requirements for Q3 files are met. We don't
- // care, but probably someone does.
- if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES) {
- DefaultLogger::get()->warn("MD3: Quake III triangle limit exceeded");
- }
-
- if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS) {
- DefaultLogger::get()->warn("MD3: Quake III shader limit exceeded");
- }
-
- if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS) {
- DefaultLogger::get()->warn("MD3: Quake III vertex limit exceeded");
- }
-
- if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES) {
- DefaultLogger::get()->warn("MD3: Quake III frame limit exceeded");
- }
+ // Calculate the relative offset of the surface
+ const int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer);
+
+ // Check whether all data chunks are inside the valid range
+ if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize ||
+ pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize ||
+ pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize ||
+ pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize) {
+
+ throw DeadlyImportError("Invalid MD3 surface header: some offsets are outside the file");
+ }
+
+ // Check whether all requirements for Q3 files are met. We don't
+ // care, but probably someone does.
+ if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES) {
+ DefaultLogger::get()->warn("MD3: Quake III triangle limit exceeded");
+ }
+
+ if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS) {
+ DefaultLogger::get()->warn("MD3: Quake III shader limit exceeded");
+ }
+
+ if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS) {
+ DefaultLogger::get()->warn("MD3: Quake III vertex limit exceeded");
+ }
+
+ if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES) {
+ DefaultLogger::get()->warn("MD3: Quake III frame limit exceeded");
+ }
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* MD3Importer::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MD3Importer::SetupProperties(const Importer* pImp)
{
- // The
- // AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_KEYFRAME,-1);
- if(static_cast<unsigned int>(-1) == configFrameID) {
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The
+ // AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_KEYFRAME,-1);
+ if(static_cast<unsigned int>(-1) == configFrameID) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
- // AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART
- configHandleMP = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART,1));
+ // AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART
+ configHandleMP = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART,1));
- // AI_CONFIG_IMPORT_MD3_SKIN_NAME
- configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME,"default"));
+ // AI_CONFIG_IMPORT_MD3_SKIN_NAME
+ configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME,"default"));
- // AI_CONFIG_IMPORT_MD3_SHADER_SRC
- configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC,""));
+ // AI_CONFIG_IMPORT_MD3_SHADER_SRC
+ configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC,""));
- // AI_CONFIG_FAVOUR_SPEED
- configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
+ // AI_CONFIG_FAVOUR_SPEED
+ configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0));
}
// ------------------------------------------------------------------------------------------------
// Try to read the skin for a MD3 file
void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const
{
- // skip any postfixes (e.g. lower_1.md3)
- std::string::size_type s = filename.find_last_of('_');
- if (s == std::string::npos) {
- s = filename.find_last_of('.');
- }
- ai_assert(s != std::string::npos);
-
- const std::string skin_file = path + filename.substr(0,s) + "_" + configSkinFile + ".skin";
- Q3Shader::LoadSkin(fill,skin_file,mIOHandler);
+ // skip any postfixes (e.g. lower_1.md3)
+ std::string::size_type s = filename.find_last_of('_');
+ if (s == std::string::npos) {
+ s = filename.find_last_of('.');
+ if (s == std::string::npos) {
+ s = filename.size();
+ }
+ }
+ ai_assert(s != std::string::npos);
+
+ const std::string skin_file = path + filename.substr(0,s) + "_" + configSkinFile + ".skin";
+ Q3Shader::LoadSkin(fill,skin_file,mIOHandler);
}
// ------------------------------------------------------------------------------------------------
// Try to read the shader for a MD3 file
void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const
{
- // Determine Q3 model name from given path
- const std::string::size_type s = path.find_last_of("\\/",path.length()-2);
- const std::string model_file = path.substr(s+1,path.length()-(s+2));
-
- // If no specific dir or file is given, use our default search behaviour
- if (!configShaderFile.length()) {
- if(!Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + model_file + ".shader",mIOHandler)) {
- Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + filename + ".shader",mIOHandler);
- }
- }
- else {
- // If the given string specifies a file, load this file.
- // Otherwise it's a directory.
- const std::string::size_type st = configShaderFile.find_last_of('.');
- if (st == std::string::npos) {
-
- if(!Q3Shader::LoadShader(fill,configShaderFile + model_file + ".shader",mIOHandler)) {
- Q3Shader::LoadShader(fill,configShaderFile + filename + ".shader",mIOHandler);
- }
- }
- else {
- Q3Shader::LoadShader(fill,configShaderFile,mIOHandler);
- }
- }
+ // Determine Q3 model name from given path
+ const std::string::size_type s = path.find_last_of("\\/",path.length()-2);
+ const std::string model_file = path.substr(s+1,path.length()-(s+2));
+
+ // If no specific dir or file is given, use our default search behaviour
+ if (!configShaderFile.length()) {
+ if(!Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + model_file + ".shader",mIOHandler)) {
+ Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + filename + ".shader",mIOHandler);
+ }
+ }
+ else {
+ // If the given string specifies a file, load this file.
+ // Otherwise it's a directory.
+ const std::string::size_type st = configShaderFile.find_last_of('.');
+ if (st == std::string::npos) {
+
+ if(!Q3Shader::LoadShader(fill,configShaderFile + model_file + ".shader",mIOHandler)) {
+ Q3Shader::LoadShader(fill,configShaderFile + filename + ".shader",mIOHandler);
+ }
+ }
+ else {
+ Q3Shader::LoadShader(fill,configShaderFile,mIOHandler);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Tiny helper to remove a single node from its parent' list
void RemoveSingleNodeFromList(aiNode* nd)
{
- if (!nd || nd->mNumChildren || !nd->mParent)return;
- aiNode* par = nd->mParent;
- for (unsigned int i = 0; i < par->mNumChildren;++i) {
- if (par->mChildren[i] == nd) {
- --par->mNumChildren;
- for (;i < par->mNumChildren;++i) {
- par->mChildren[i] = par->mChildren[i+1];
- }
- delete nd;
- break;
- }
- }
+ if (!nd || nd->mNumChildren || !nd->mParent)return;
+ aiNode* par = nd->mParent;
+ for (unsigned int i = 0; i < par->mNumChildren;++i) {
+ if (par->mChildren[i] == nd) {
+ --par->mNumChildren;
+ for (;i < par->mNumChildren;++i) {
+ par->mChildren[i] = par->mChildren[i+1];
+ }
+ delete nd;
+ break;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a multi-part Q3 player model
bool MD3Importer::ReadMultipartFile()
{
- // check whether the file name contains a common postfix, e.g lower_2.md3
- std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.');
- ai_assert(t != std::string::npos);
- if (s == std::string::npos)
- s = t;
-
- const std::string mod_filename = filename.substr(0,s);
- const std::string suffix = filename.substr(s,t-s);
-
- if (mod_filename == "lower" || mod_filename == "upper" || mod_filename == "head"){
- const std::string lower = path + "lower" + suffix + ".md3";
- const std::string upper = path + "upper" + suffix + ".md3";
- const std::string head = path + "head" + suffix + ".md3";
-
- aiScene* scene_upper = NULL;
- aiScene* scene_lower = NULL;
- aiScene* scene_head = NULL;
- std::string failure;
-
- aiNode* tag_torso, *tag_head;
- std::vector<AttachmentInfo> attach;
-
- DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined");
-
- // ensure we won't try to load ourselves recursively
- BatchLoader::PropertyMap props;
- SetGenericProperty( props.ints, AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 0, NULL);
-
- // now read these three files
- BatchLoader batch(mIOHandler);
- const unsigned int _lower = batch.AddLoadRequest(lower,0,&props);
- const unsigned int _upper = batch.AddLoadRequest(upper,0,&props);
- const unsigned int _head = batch.AddLoadRequest(head,0,&props);
- batch.LoadAll();
-
- // now construct a dummy scene to place these three parts in
- aiScene* master = new aiScene();
- aiNode* nd = master->mRootNode = new aiNode();
- nd->mName.Set("<MD3_Player>");
-
- // ... and get them. We need all of them.
- scene_lower = batch.GetImport(_lower);
- if (!scene_lower) {
- DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load");
- failure = "lower";
- goto error_cleanup;
- }
-
- scene_upper = batch.GetImport(_upper);
- if (!scene_upper) {
- DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load");
- failure = "upper";
- goto error_cleanup;
- }
-
- scene_head = batch.GetImport(_head);
- if (!scene_head) {
- DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load");
- failure = "head";
- goto error_cleanup;
- }
-
- // build attachment infos. search for typical Q3 tags
-
- // original root
- scene_lower->mRootNode->mName.Set("lower");
- attach.push_back(AttachmentInfo(scene_lower, nd));
-
- // tag_torso
- tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
- if (!tag_torso) {
- DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected");
- goto error_cleanup;
- }
- scene_upper->mRootNode->mName.Set("upper");
- attach.push_back(AttachmentInfo(scene_upper,tag_torso));
-
- // tag_head
- tag_head = scene_upper->mRootNode->FindNode("tag_head");
- if (!tag_head) {
- DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected");
- goto error_cleanup;
- }
- scene_head->mRootNode->mName.Set("head");
- attach.push_back(AttachmentInfo(scene_head,tag_head));
-
- // Remove tag_head and tag_torso from all other model parts ...
- // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY)
- // that tag_torso/tag_head is also the name of the (unique) output node
- RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso"));
- RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" ));
-
- // Undo the rotations which we applied to the coordinate systems. We're
- // working in global Quake space here
- scene_head->mRootNode->mTransformation = aiMatrix4x4();
- scene_lower->mRootNode->mTransformation = aiMatrix4x4();
- scene_upper->mRootNode->mTransformation = aiMatrix4x4();
-
- // and merge the scenes
- SceneCombiner::MergeScenes(&mScene,master, attach,
- AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES |
- AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES |
- AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS |
- (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0));
-
- // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
- mScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
-
- return true;
+ // check whether the file name contains a common postfix, e.g lower_2.md3
+ std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.');
+
+ if (t == std::string::npos)
+ t = filename.size();
+ if (s == std::string::npos)
+ s = t;
+
+ const std::string mod_filename = filename.substr(0,s);
+ const std::string suffix = filename.substr(s,t-s);
+
+ if (mod_filename == "lower" || mod_filename == "upper" || mod_filename == "head"){
+ const std::string lower = path + "lower" + suffix + ".md3";
+ const std::string upper = path + "upper" + suffix + ".md3";
+ const std::string head = path + "head" + suffix + ".md3";
+
+ aiScene* scene_upper = NULL;
+ aiScene* scene_lower = NULL;
+ aiScene* scene_head = NULL;
+ std::string failure;
+
+ aiNode* tag_torso, *tag_head;
+ std::vector<AttachmentInfo> attach;
+
+ DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined");
+
+ // ensure we won't try to load ourselves recursively
+ BatchLoader::PropertyMap props;
+ SetGenericProperty( props.ints, AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 0);
+
+ // now read these three files
+ BatchLoader batch(mIOHandler);
+ const unsigned int _lower = batch.AddLoadRequest(lower,0,&props);
+ const unsigned int _upper = batch.AddLoadRequest(upper,0,&props);
+ const unsigned int _head = batch.AddLoadRequest(head,0,&props);
+ batch.LoadAll();
+
+ // now construct a dummy scene to place these three parts in
+ aiScene* master = new aiScene();
+ aiNode* nd = master->mRootNode = new aiNode();
+ nd->mName.Set("<MD3_Player>");
+
+ // ... and get them. We need all of them.
+ scene_lower = batch.GetImport(_lower);
+ if (!scene_lower) {
+ DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load");
+ failure = "lower";
+ goto error_cleanup;
+ }
+
+ scene_upper = batch.GetImport(_upper);
+ if (!scene_upper) {
+ DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load");
+ failure = "upper";
+ goto error_cleanup;
+ }
+
+ scene_head = batch.GetImport(_head);
+ if (!scene_head) {
+ DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load");
+ failure = "head";
+ goto error_cleanup;
+ }
+
+ // build attachment infos. search for typical Q3 tags
+
+ // original root
+ scene_lower->mRootNode->mName.Set("lower");
+ attach.push_back(AttachmentInfo(scene_lower, nd));
+
+ // tag_torso
+ tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
+ if (!tag_torso) {
+ DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected");
+ goto error_cleanup;
+ }
+ scene_upper->mRootNode->mName.Set("upper");
+ attach.push_back(AttachmentInfo(scene_upper,tag_torso));
+
+ // tag_head
+ tag_head = scene_upper->mRootNode->FindNode("tag_head");
+ if (!tag_head) {
+ DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected");
+ goto error_cleanup;
+ }
+ scene_head->mRootNode->mName.Set("head");
+ attach.push_back(AttachmentInfo(scene_head,tag_head));
+
+ // Remove tag_head and tag_torso from all other model parts ...
+ // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY)
+ // that tag_torso/tag_head is also the name of the (unique) output node
+ RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso"));
+ RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" ));
+
+ // Undo the rotations which we applied to the coordinate systems. We're
+ // working in global Quake space here
+ scene_head->mRootNode->mTransformation = aiMatrix4x4();
+ scene_lower->mRootNode->mTransformation = aiMatrix4x4();
+ scene_upper->mRootNode->mTransformation = aiMatrix4x4();
+
+ // and merge the scenes
+ SceneCombiner::MergeScenes(&mScene,master, attach,
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES |
+ AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES |
+ AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS |
+ (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0));
+
+ // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+ mScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+
+ return true;
error_cleanup:
- delete scene_upper;
- delete scene_lower;
- delete scene_head;
- delete master;
-
- if (failure == mod_filename) {
- throw DeadlyImportError("MD3: failure to read multipart host file");
- }
- }
- return false;
+ delete scene_upper;
+ delete scene_lower;
+ delete scene_head;
+ delete master;
+
+ if (failure == mod_filename) {
+ throw DeadlyImportError("MD3: failure to read multipart host file");
+ }
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Convert a MD3 path to a proper value
void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, std::string& out) const
{
- // If the MD3's internal path itself and the given path are using
- // the same directory, remove it completely to get right output paths.
- const char* end1 = ::strrchr(header_name,'\\');
- if (!end1)end1 = ::strrchr(header_name,'/');
-
- const char* end2 = ::strrchr(texture_name,'\\');
- if (!end2)end2 = ::strrchr(texture_name,'/');
-
- // HACK: If the paths starts with "models", ignore the
- // next two hierarchy levels, it specifies just the model name.
- // Ignored by Q3, it might be not equal to the real model location.
- if (end2) {
-
- size_t len2;
- const size_t len1 = (size_t)(end1 - header_name);
- if (!ASSIMP_strincmp(texture_name,"models",6) && (texture_name[6] == '/' || texture_name[6] == '\\')) {
- len2 = 6; // ignore the seventh - could be slash or backslash
-
- if (!header_name[0]) {
- // Use the file name only
- out = end2+1;
- return;
- }
- }
- else len2 = std::min (len1, (size_t)(end2 - texture_name ));
- if (!ASSIMP_strincmp(texture_name,header_name,len2)) {
- // Use the file name only
- out = end2+1;
- return;
- }
- }
- // Use the full path
- out = texture_name;
+ // If the MD3's internal path itself and the given path are using
+ // the same directory, remove it completely to get right output paths.
+ const char* end1 = ::strrchr(header_name,'\\');
+ if (!end1)end1 = ::strrchr(header_name,'/');
+
+ const char* end2 = ::strrchr(texture_name,'\\');
+ if (!end2)end2 = ::strrchr(texture_name,'/');
+
+ // HACK: If the paths starts with "models", ignore the
+ // next two hierarchy levels, it specifies just the model name.
+ // Ignored by Q3, it might be not equal to the real model location.
+ if (end2) {
+
+ size_t len2;
+ const size_t len1 = (size_t)(end1 - header_name);
+ if (!ASSIMP_strincmp(texture_name,"models",6) && (texture_name[6] == '/' || texture_name[6] == '\\')) {
+ len2 = 6; // ignore the seventh - could be slash or backslash
+
+ if (!header_name[0]) {
+ // Use the file name only
+ out = end2+1;
+ return;
+ }
+ }
+ else len2 = std::min (len1, (size_t)(end2 - texture_name ));
+ if (!ASSIMP_strincmp(texture_name,header_name,len2)) {
+ // Use the file name only
+ out = end2+1;
+ return;
+ }
+ }
+ // Use the full path
+ out = texture_name;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MD3Importer::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void MD3Importer::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- mFile = pFile;
- mScene = pScene;
- mIOHandler = pIOHandler;
-
- // get base path and file name
- // todo ... move to PathConverter
- std::string::size_type s = mFile.find_last_of("/\\");
- if (s == std::string::npos) {
- s = 0;
- }
- else ++s;
- filename = mFile.substr(s), path = mFile.substr(0,s);
- for( std::string::iterator it = filename .begin(); it != filename.end(); ++it)
- *it = tolower( *it);
-
- // Load multi-part model file, if necessary
- if (configHandleMP) {
- if (ReadMultipartFile())
- return;
- }
-
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open MD3 file " + pFile + ".");
-
- // Check whether the md3 file is large enough to contain the header
- fileSize = (unsigned int)file->FileSize();
- if( fileSize < sizeof(MD3::Header))
- throw DeadlyImportError( "MD3 File is too small.");
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector<unsigned char> mBuffer2 (fileSize);
- file->Read( &mBuffer2[0], 1, fileSize);
- mBuffer = &mBuffer2[0];
-
- pcHeader = (BE_NCONST MD3::Header*)mBuffer;
-
- // Ensure correct endianess
+ mFile = pFile;
+ mScene = pScene;
+ mIOHandler = pIOHandler;
+
+ // get base path and file name
+ // todo ... move to PathConverter
+ std::string::size_type s = mFile.find_last_of("/\\");
+ if (s == std::string::npos) {
+ s = 0;
+ }
+ else ++s;
+ filename = mFile.substr(s), path = mFile.substr(0,s);
+ for( std::string::iterator it = filename .begin(); it != filename.end(); ++it)
+ *it = tolower( *it);
+
+ // Load multi-part model file, if necessary
+ if (configHandleMP) {
+ if (ReadMultipartFile())
+ return;
+ }
+
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open MD3 file " + pFile + ".");
+
+ // Check whether the md3 file is large enough to contain the header
+ fileSize = (unsigned int)file->FileSize();
+ if( fileSize < sizeof(MD3::Header))
+ throw DeadlyImportError( "MD3 File is too small.");
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector<unsigned char> mBuffer2 (fileSize);
+ file->Read( &mBuffer2[0], 1, fileSize);
+ mBuffer = &mBuffer2[0];
+
+ pcHeader = (BE_NCONST MD3::Header*)mBuffer;
+
+ // Ensure correct endianness
#ifdef AI_BUILD_BIG_ENDIAN
- AI_SWAP4(pcHeader->VERSION);
- AI_SWAP4(pcHeader->FLAGS);
- AI_SWAP4(pcHeader->IDENT);
- AI_SWAP4(pcHeader->NUM_FRAMES);
- AI_SWAP4(pcHeader->NUM_SKINS);
- AI_SWAP4(pcHeader->NUM_SURFACES);
- AI_SWAP4(pcHeader->NUM_TAGS);
- AI_SWAP4(pcHeader->OFS_EOF);
- AI_SWAP4(pcHeader->OFS_FRAMES);
- AI_SWAP4(pcHeader->OFS_SURFACES);
- AI_SWAP4(pcHeader->OFS_TAGS);
+ AI_SWAP4(pcHeader->VERSION);
+ AI_SWAP4(pcHeader->FLAGS);
+ AI_SWAP4(pcHeader->IDENT);
+ AI_SWAP4(pcHeader->NUM_FRAMES);
+ AI_SWAP4(pcHeader->NUM_SKINS);
+ AI_SWAP4(pcHeader->NUM_SURFACES);
+ AI_SWAP4(pcHeader->NUM_TAGS);
+ AI_SWAP4(pcHeader->OFS_EOF);
+ AI_SWAP4(pcHeader->OFS_FRAMES);
+ AI_SWAP4(pcHeader->OFS_SURFACES);
+ AI_SWAP4(pcHeader->OFS_TAGS);
#endif
- // Validate the file header
- ValidateHeaderOffsets();
-
- // Navigate to the list of surfaces
- BE_NCONST MD3::Surface* pcSurfaces = (BE_NCONST MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES);
-
- // Navigate to the list of tags
- BE_NCONST MD3::Tag* pcTags = (BE_NCONST MD3::Tag*)(mBuffer + pcHeader->OFS_TAGS);
-
- // Allocate output storage
- pScene->mNumMeshes = pcHeader->NUM_SURFACES;
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-
- pScene->mNumMaterials = pcHeader->NUM_SURFACES;
- pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
-
- // Set arrays to zero to ensue proper destruction if an exception is raised
- ::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
- ::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
-
- // Now read possible skins from .skin file
- Q3Shader::SkinData skins;
- ReadSkin(skins);
-
- // And check whether we can locate a shader file for this model
- Q3Shader::ShaderData shaders;
- ReadShader(shaders);
-
- // Adjust all texture paths in the shader
- const char* header_name = pcHeader->NAME;
- if (shaders.blocks.size()) {
- for (std::list< Q3Shader::ShaderDataBlock >::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) {
- ConvertPath((*dit).name.c_str(),header_name,(*dit).name);
-
- for (std::list< Q3Shader::ShaderMapBlock >::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) {
- ConvertPath((*mit).name.c_str(),header_name,(*mit).name);
- }
- }
- }
-
- // Read all surfaces from the file
- unsigned int iNum = pcHeader->NUM_SURFACES;
- unsigned int iNumMaterials = 0;
- while (iNum-- > 0) {
-
- // Ensure correct endianess
+ // Validate the file header
+ ValidateHeaderOffsets();
+
+ // Navigate to the list of surfaces
+ BE_NCONST MD3::Surface* pcSurfaces = (BE_NCONST MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES);
+
+ // Navigate to the list of tags
+ BE_NCONST MD3::Tag* pcTags = (BE_NCONST MD3::Tag*)(mBuffer + pcHeader->OFS_TAGS);
+
+ // Allocate output storage
+ pScene->mNumMeshes = pcHeader->NUM_SURFACES;
+ if (pcHeader->NUM_SURFACES == 0) {
+ throw DeadlyImportError("MD3: No surfaces");
+ } else if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(aiMesh)) {
+ // We allocate pointers but check against the size of aiMesh
+ // since those pointers will eventually have to point to real objects
+ throw DeadlyImportError("MD3: Too many surfaces, would run out of memory");
+ }
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+
+ pScene->mNumMaterials = pcHeader->NUM_SURFACES;
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
+
+ // Set arrays to zero to ensue proper destruction if an exception is raised
+ ::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*));
+ ::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*));
+
+ // Now read possible skins from .skin file
+ Q3Shader::SkinData skins;
+ ReadSkin(skins);
+
+ // And check whether we can locate a shader file for this model
+ Q3Shader::ShaderData shaders;
+ ReadShader(shaders);
+
+ // Adjust all texture paths in the shader
+ const char* header_name = pcHeader->NAME;
+ if (!shaders.blocks.empty()) {
+ for (std::list< Q3Shader::ShaderDataBlock >::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) {
+ ConvertPath((*dit).name.c_str(),header_name,(*dit).name);
+
+ for (std::list< Q3Shader::ShaderMapBlock >::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) {
+ ConvertPath((*mit).name.c_str(),header_name,(*mit).name);
+ }
+ }
+ }
+
+ // Read all surfaces from the file
+ unsigned int iNum = pcHeader->NUM_SURFACES;
+ unsigned int iNumMaterials = 0;
+ while (iNum-- > 0) {
+
+ // Ensure correct endianness
#ifdef AI_BUILD_BIG_ENDIAN
- AI_SWAP4(pcSurfaces->FLAGS);
- AI_SWAP4(pcSurfaces->IDENT);
- AI_SWAP4(pcSurfaces->NUM_FRAMES);
- AI_SWAP4(pcSurfaces->NUM_SHADER);
- AI_SWAP4(pcSurfaces->NUM_TRIANGLES);
- AI_SWAP4(pcSurfaces->NUM_VERTICES);
- AI_SWAP4(pcSurfaces->OFS_END);
- AI_SWAP4(pcSurfaces->OFS_SHADERS);
- AI_SWAP4(pcSurfaces->OFS_ST);
- AI_SWAP4(pcSurfaces->OFS_TRIANGLES);
- AI_SWAP4(pcSurfaces->OFS_XYZNORMAL);
+ AI_SWAP4(pcSurfaces->FLAGS);
+ AI_SWAP4(pcSurfaces->IDENT);
+ AI_SWAP4(pcSurfaces->NUM_FRAMES);
+ AI_SWAP4(pcSurfaces->NUM_SHADER);
+ AI_SWAP4(pcSurfaces->NUM_TRIANGLES);
+ AI_SWAP4(pcSurfaces->NUM_VERTICES);
+ AI_SWAP4(pcSurfaces->OFS_END);
+ AI_SWAP4(pcSurfaces->OFS_SHADERS);
+ AI_SWAP4(pcSurfaces->OFS_ST);
+ AI_SWAP4(pcSurfaces->OFS_TRIANGLES);
+ AI_SWAP4(pcSurfaces->OFS_XYZNORMAL);
#endif
- // Validate the surface header
- ValidateSurfaceHeaderOffsets(pcSurfaces);
-
- // Navigate to the vertex list of the surface
- BE_NCONST MD3::Vertex* pcVertices = (BE_NCONST MD3::Vertex*)
- (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
-
- // Navigate to the triangle list of the surface
- BE_NCONST MD3::Triangle* pcTriangles = (BE_NCONST MD3::Triangle*)
- (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
-
- // Navigate to the texture coordinate list of the surface
- BE_NCONST MD3::TexCoord* pcUVs = (BE_NCONST MD3::TexCoord*)
- (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
-
- // Navigate to the shader list of the surface
- BE_NCONST MD3::Shader* pcShaders = (BE_NCONST MD3::Shader*)
- (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
-
- // If the submesh is empty ignore it
- if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
- {
- pcSurfaces = (BE_NCONST MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
- pScene->mNumMeshes--;
- continue;
- }
-
- // Allocate output mesh
- pScene->mMeshes[iNum] = new aiMesh();
- aiMesh* pcMesh = pScene->mMeshes[iNum];
-
- std::string _texture_name;
- const char* texture_name = NULL;
-
- // Check whether we have a texture record for this surface in the .skin file
- std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find(
- skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME );
-
- if (it != skins.textures.end()) {
- texture_name = &*( _texture_name = (*it).second).begin();
- DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME);
- (*it).resolved = true; // mark entry as resolved
- }
-
- // Get the first shader (= texture?) assigned to the surface
- if (!texture_name && pcSurfaces->NUM_SHADER) {
- texture_name = pcShaders->NAME;
- }
-
- std::string convertedPath;
- if (texture_name) {
- ConvertPath(texture_name,header_name,convertedPath);
- }
-
- const Q3Shader::ShaderDataBlock* shader = NULL;
-
- // Now search the current shader for a record with this name (
- // excluding texture file extension)
- if (shaders.blocks.size()) {
-
- std::string::size_type s = convertedPath.find_last_of('.');
- if (s == std::string::npos)
- s = convertedPath.length();
-
- const std::string without_ext = convertedPath.substr(0,s);
- std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext);
- if (dit != shaders.blocks.end()) {
- // Hurra, wir haben einen. Tolle Sache.
- shader = &*dit;
- DefaultLogger::get()->info("Found shader record for " +without_ext );
- }
- else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext );
- }
-
- aiMaterial* pcHelper = new aiMaterial();
-
- const int iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- // Add a small ambient color value - Quake 3 seems to have one
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- clr.b = clr.g = clr.r = 1.0f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- // use surface name + skin_name as material name
- aiString name;
- name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]");
- pcHelper->AddProperty(&name,AI_MATKEY_NAME);
-
- if (!shader) {
- // Setup dummy texture file name to ensure UV coordinates are kept during postprocessing
- aiString szString;
- if (convertedPath.length()) {
- szString.Set(convertedPath);
- }
- else {
- DefaultLogger::get()->warn("Texture file name has zero length. Using default name");
- szString.Set("dummy_texture.bmp");
- }
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
- // prevent transparency by default
- int no_alpha = aiTextureFlags_IgnoreAlpha;
- pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0));
- }
- else {
- Q3Shader::ConvertShaderToMaterial(pcHelper,*shader);
- }
-
- pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
- pcMesh->mMaterialIndex = iNumMaterials++;
-
- // Ensure correct endianess
+ // Validate the surface header
+ ValidateSurfaceHeaderOffsets(pcSurfaces);
+
+ // Navigate to the vertex list of the surface
+ BE_NCONST MD3::Vertex* pcVertices = (BE_NCONST MD3::Vertex*)
+ (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL);
+
+ // Navigate to the triangle list of the surface
+ BE_NCONST MD3::Triangle* pcTriangles = (BE_NCONST MD3::Triangle*)
+ (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES);
+
+ // Navigate to the texture coordinate list of the surface
+ BE_NCONST MD3::TexCoord* pcUVs = (BE_NCONST MD3::TexCoord*)
+ (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST);
+
+ // Navigate to the shader list of the surface
+ BE_NCONST MD3::Shader* pcShaders = (BE_NCONST MD3::Shader*)
+ (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS);
+
+ // If the submesh is empty ignore it
+ if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES)
+ {
+ pcSurfaces = (BE_NCONST MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END);
+ pScene->mNumMeshes--;
+ continue;
+ }
+
+ // Allocate output mesh
+ pScene->mMeshes[iNum] = new aiMesh();
+ aiMesh* pcMesh = pScene->mMeshes[iNum];
+
+ std::string _texture_name;
+ const char* texture_name = NULL;
+
+ // Check whether we have a texture record for this surface in the .skin file
+ std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find(
+ skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME );
+
+ if (it != skins.textures.end()) {
+ texture_name = &*( _texture_name = (*it).second).begin();
+ DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME);
+ (*it).resolved = true; // mark entry as resolved
+ }
+
+ // Get the first shader (= texture?) assigned to the surface
+ if (!texture_name && pcSurfaces->NUM_SHADER) {
+ texture_name = pcShaders->NAME;
+ }
+
+ std::string convertedPath;
+ if (texture_name) {
+ ConvertPath(texture_name,header_name,convertedPath);
+ }
+
+ const Q3Shader::ShaderDataBlock* shader = NULL;
+
+ // Now search the current shader for a record with this name (
+ // excluding texture file extension)
+ if (!shaders.blocks.empty()) {
+
+ std::string::size_type s = convertedPath.find_last_of('.');
+ if (s == std::string::npos)
+ s = convertedPath.length();
+
+ const std::string without_ext = convertedPath.substr(0,s);
+ std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext);
+ if (dit != shaders.blocks.end()) {
+ // Hurra, wir haben einen. Tolle Sache.
+ shader = &*dit;
+ DefaultLogger::get()->info("Found shader record for " +without_ext );
+ }
+ else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext );
+ }
+
+ aiMaterial* pcHelper = new aiMaterial();
+
+ const int iMode = (int)aiShadingMode_Gouraud;
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ // Add a small ambient color value - Quake 3 seems to have one
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ clr.b = clr.g = clr.r = 1.0f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ // use surface name + skin_name as material name
+ aiString name;
+ name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]");
+ pcHelper->AddProperty(&name,AI_MATKEY_NAME);
+
+ if (!shader) {
+ // Setup dummy texture file name to ensure UV coordinates are kept during postprocessing
+ aiString szString;
+ if (convertedPath.length()) {
+ szString.Set(convertedPath);
+ }
+ else {
+ DefaultLogger::get()->warn("Texture file name has zero length. Using default name");
+ szString.Set("dummy_texture.bmp");
+ }
+ pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+ // prevent transparency by default
+ int no_alpha = aiTextureFlags_IgnoreAlpha;
+ pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0));
+ }
+ else {
+ Q3Shader::ConvertShaderToMaterial(pcHelper,*shader);
+ }
+
+ pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
+ pcMesh->mMaterialIndex = iNumMaterials++;
+
+ // Ensure correct endianness
#ifdef AI_BUILD_BIG_ENDIAN
- for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) {
- AI_SWAP2( pcVertices[i].NORMAL );
- AI_SWAP2( pcVertices[i].X );
- AI_SWAP2( pcVertices[i].Y );
- AI_SWAP2( pcVertices[i].Z );
-
- AI_SWAP4( pcUVs[i].U );
- AI_SWAP4( pcUVs[i].U );
- }
- for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) {
- AI_SWAP4(pcTriangles[i].INDEXES[0]);
- AI_SWAP4(pcTriangles[i].INDEXES[1]);
- AI_SWAP4(pcTriangles[i].INDEXES[2]);
- }
+ for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) {
+ AI_SWAP2( pcVertices[i].NORMAL );
+ AI_SWAP2( pcVertices[i].X );
+ AI_SWAP2( pcVertices[i].Y );
+ AI_SWAP2( pcVertices[i].Z );
+
+ AI_SWAP4( pcUVs[i].U );
+ AI_SWAP4( pcUVs[i].U );
+ }
+ for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) {
+ AI_SWAP4(pcTriangles[i].INDEXES[0]);
+ AI_SWAP4(pcTriangles[i].INDEXES[1]);
+ AI_SWAP4(pcTriangles[i].INDEXES[2]);
+ }
#endif
- // Fill mesh information
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
- pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
- pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
-
- // Fill in all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- //unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
- pcMesh->mFaces[i].mIndices[c] = iCurrent;
-
- // Read vertices
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE;
- vec.y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE;
- vec.z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE;
-
- // Convert the normal vector to uncompressed float3 format
- aiVector3D& nor = pcMesh->mNormals[iCurrent];
- LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(float*)&nor);
-
- // Read texture coordinates
- pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
- pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V;
- }
- // Flip face order if necessary
- if (!shader || shader->cull == Q3Shader::CULL_CW) {
- std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]);
- }
- pcTriangles++;
- }
-
- // Go to the next surface
- pcSurfaces = (BE_NCONST MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
- }
-
- // For debugging purposes: check whether we found matches for all entries in the skins file
- if (!DefaultLogger::isNullLogger()) {
- for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) {
- if (!(*it).resolved) {
- DefaultLogger::get()->error("MD3: Failed to match skin " + (*it).first + " to surface " + (*it).second);
- }
- }
- }
-
- if (!pScene->mNumMeshes)
- throw DeadlyImportError( "MD3: File contains no valid mesh");
- pScene->mNumMaterials = iNumMaterials;
-
- // Now we need to generate an empty node graph
- pScene->mRootNode = new aiNode("<MD3Root>");
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
-
- // Attach tiny children for all tags
- if (pcHeader->NUM_TAGS) {
- pScene->mRootNode->mNumChildren = pcHeader->NUM_TAGS;
- pScene->mRootNode->mChildren = new aiNode*[pcHeader->NUM_TAGS];
-
- for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) {
-
- aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
- nd->mName.Set((const char*)pcTags->NAME);
- nd->mParent = pScene->mRootNode;
-
- AI_SWAP4(pcTags->origin.x);
- AI_SWAP4(pcTags->origin.y);
- AI_SWAP4(pcTags->origin.z);
-
- // Copy local origin, again flip z,y
- nd->mTransformation.a4 = pcTags->origin.x;
- nd->mTransformation.b4 = pcTags->origin.y;
- nd->mTransformation.c4 = pcTags->origin.z;
-
- // Copy rest of transformation (need to transpose to match row-order matrix)
- for (unsigned int a = 0; a < 3;++a) {
- for (unsigned int m = 0; m < 3;++m) {
- nd->mTransformation[m][a] = pcTags->orientation[a][m];
- AI_SWAP4(nd->mTransformation[m][a]);
- }
- }
- }
- }
-
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mRootNode->mMeshes[i] = i;
-
- // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+ // Fill mesh information
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
+ pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES;
+ pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+
+ // Fill in all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ //unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+ pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+ // Read vertices
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ uint32_t index = pcTriangles->INDEXES[c];
+ if (index >= pcSurfaces->NUM_VERTICES) {
+ throw DeadlyImportError( "MD3: Invalid vertex index");
+ }
+ vec.x = pcVertices[index].X*AI_MD3_XYZ_SCALE;
+ vec.y = pcVertices[index].Y*AI_MD3_XYZ_SCALE;
+ vec.z = pcVertices[index].Z*AI_MD3_XYZ_SCALE;
+
+ // Convert the normal vector to uncompressed float3 format
+ aiVector3D& nor = pcMesh->mNormals[iCurrent];
+ LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(float*)&nor);
+
+ // Read texture coordinates
+ pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
+ pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V;
+ }
+ // Flip face order if necessary
+ if (!shader || shader->cull == Q3Shader::CULL_CW) {
+ std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]);
+ }
+ pcTriangles++;
+ }
+
+ // Go to the next surface
+ pcSurfaces = (BE_NCONST MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
+ }
+
+ // For debugging purposes: check whether we found matches for all entries in the skins file
+ if (!DefaultLogger::isNullLogger()) {
+ for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) {
+ if (!(*it).resolved) {
+ DefaultLogger::get()->error("MD3: Failed to match skin " + (*it).first + " to surface " + (*it).second);
+ }
+ }
+ }
+
+ if (!pScene->mNumMeshes)
+ throw DeadlyImportError( "MD3: File contains no valid mesh");
+ pScene->mNumMaterials = iNumMaterials;
+
+ // Now we need to generate an empty node graph
+ pScene->mRootNode = new aiNode("<MD3Root>");
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+
+ // Attach tiny children for all tags
+ if (pcHeader->NUM_TAGS) {
+ pScene->mRootNode->mNumChildren = pcHeader->NUM_TAGS;
+ pScene->mRootNode->mChildren = new aiNode*[pcHeader->NUM_TAGS];
+
+ for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) {
+
+ aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
+ nd->mName.Set((const char*)pcTags->NAME);
+ nd->mParent = pScene->mRootNode;
+
+ AI_SWAP4(pcTags->origin.x);
+ AI_SWAP4(pcTags->origin.y);
+ AI_SWAP4(pcTags->origin.z);
+
+ // Copy local origin, again flip z,y
+ nd->mTransformation.a4 = pcTags->origin.x;
+ nd->mTransformation.b4 = pcTags->origin.y;
+ nd->mTransformation.c4 = pcTags->origin.z;
+
+ // Copy rest of transformation (need to transpose to match row-order matrix)
+ for (unsigned int a = 0; a < 3;++a) {
+ for (unsigned int m = 0; m < 3;++m) {
+ nd->mTransformation[m][a] = pcTags->orientation[a][m];
+ AI_SWAP4(nd->mTransformation[m][a]);
+ }
+ }
+ }
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mRootNode->mMeshes[i] = i;
+
+ // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+ pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
}
#endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER
diff --git a/src/3rdparty/assimp/code/MD3Loader.h b/src/3rdparty/assimp/code/MD3Loader.h
index 7f941ae47..6b8143a97 100644
--- a/src/3rdparty/assimp/code/MD3Loader.h
+++ b/src/3rdparty/assimp/code/MD3Loader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,12 +45,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MD3LOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
+#include "MD3FileData.h"
+#include "StringComparison.h"
+#include <assimp/types.h>
-#include "../include/assimp/types.h"
+#include <list>
-#include "MD3FileData.h"
-namespace Assimp {
+struct aiMaterial;
+
+namespace Assimp {
using namespace MD3;
@@ -61,22 +65,22 @@ namespace Q3Shader {
*/
struct SkinData
{
- //! A single entryin texture list
- struct TextureEntry : public std::pair<std::string,std::string>
- {
- // did we resolve this texture entry?
- bool resolved;
-
- // for std::find()
- bool operator == (const std::string& f) const {
- return f == first;
- }
- };
-
- //! List of textures
- std::list<TextureEntry> textures;
-
- // rest is ignored for the moment
+ //! A single entryin texture list
+ struct TextureEntry : public std::pair<std::string,std::string>
+ {
+ // did we resolve this texture entry?
+ bool resolved;
+
+ // for std::find()
+ bool operator == (const std::string& f) const {
+ return f == first;
+ }
+ };
+
+ //! List of textures
+ std::list<TextureEntry> textures;
+
+ // rest is ignored for the moment
};
// ---------------------------------------------------------------------------
@@ -84,9 +88,9 @@ struct SkinData
*/
enum ShaderCullMode
{
- CULL_NONE,
- CULL_CW,
- CULL_CCW
+ CULL_NONE,
+ CULL_CW,
+ CULL_CCW
};
// ---------------------------------------------------------------------------
@@ -94,13 +98,13 @@ enum ShaderCullMode
*/
enum BlendFunc
{
- BLEND_NONE,
- BLEND_GL_ONE,
- BLEND_GL_ZERO,
- BLEND_GL_DST_COLOR,
- BLEND_GL_ONE_MINUS_DST_COLOR,
- BLEND_GL_SRC_ALPHA,
- BLEND_GL_ONE_MINUS_SRC_ALPHA
+ BLEND_NONE,
+ BLEND_GL_ONE,
+ BLEND_GL_ZERO,
+ BLEND_GL_DST_COLOR,
+ BLEND_GL_ONE_MINUS_DST_COLOR,
+ BLEND_GL_SRC_ALPHA,
+ BLEND_GL_ONE_MINUS_SRC_ALPHA
};
// ---------------------------------------------------------------------------
@@ -108,10 +112,10 @@ enum BlendFunc
*/
enum AlphaTestFunc
{
- AT_NONE,
- AT_GT0,
- AT_LT128,
- AT_GE128
+ AT_NONE,
+ AT_GT0,
+ AT_LT128,
+ AT_GE128
};
// ---------------------------------------------------------------------------
@@ -119,24 +123,24 @@ enum AlphaTestFunc
*/
struct ShaderMapBlock
{
- ShaderMapBlock()
- : blend_src (BLEND_NONE)
- , blend_dest (BLEND_NONE)
- , alpha_test (AT_NONE)
- {}
+ ShaderMapBlock()
+ : blend_src (BLEND_NONE)
+ , blend_dest (BLEND_NONE)
+ , alpha_test (AT_NONE)
+ {}
- //! Name of referenced map
- std::string name;
+ //! Name of referenced map
+ std::string name;
- //! Blend and alpha test settings for texture
- BlendFunc blend_src,blend_dest;
- AlphaTestFunc alpha_test;
+ //! Blend and alpha test settings for texture
+ BlendFunc blend_src,blend_dest;
+ AlphaTestFunc alpha_test;
- //! For std::find()
- bool operator== (const std::string& o) const {
- return !ASSIMP_stricmp(o,name);
- }
+ //! For std::find()
+ bool operator== (const std::string& o) const {
+ return !ASSIMP_stricmp(o,name);
+ }
};
// ---------------------------------------------------------------------------
@@ -144,24 +148,24 @@ struct ShaderMapBlock
*/
struct ShaderDataBlock
{
- ShaderDataBlock()
- : cull (CULL_CW)
- {}
+ ShaderDataBlock()
+ : cull (CULL_CW)
+ {}
- //! Name of referenced data element
- std::string name;
+ //! Name of referenced data element
+ std::string name;
- //! Cull mode for the element
- ShaderCullMode cull;
+ //! Cull mode for the element
+ ShaderCullMode cull;
- //! Maps defined in the shader
- std::list<ShaderMapBlock> maps;
+ //! Maps defined in the shader
+ std::list<ShaderMapBlock> maps;
- //! For std::find()
- bool operator== (const std::string& o) const {
- return !ASSIMP_stricmp(o,name);
- }
+ //! For std::find()
+ bool operator== (const std::string& o) const {
+ return !ASSIMP_stricmp(o,name);
+ }
};
// ---------------------------------------------------------------------------
@@ -169,8 +173,8 @@ struct ShaderDataBlock
*/
struct ShaderData
{
- //! Shader data blocks
- std::list<ShaderDataBlock> blocks;
+ //! Shader data blocks
+ std::list<ShaderDataBlock> blocks;
};
// ---------------------------------------------------------------------------
@@ -212,115 +216,115 @@ bool LoadSkin(SkinData& fill, const std::string& file,IOSystem* io);
class MD3Importer : public BaseImporter
{
public:
- MD3Importer();
- ~MD3Importer();
+ MD3Importer();
+ ~MD3Importer();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
-
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
-
- // -------------------------------------------------------------------
- /** Validate offsets in the header
- */
- void ValidateHeaderOffsets();
- void ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurfHeader);
-
- // -------------------------------------------------------------------
- /** Read a Q3 multipart file
- * @return true if multi part has been processed
- */
- bool ReadMultipartFile();
-
- // -------------------------------------------------------------------
- /** Try to read the skin for a MD3 file
- * @param fill Receives output information
- */
- void ReadSkin(Q3Shader::SkinData& fill) const;
-
- // -------------------------------------------------------------------
- /** Try to read the shader for a MD3 file
- * @param fill Receives output information
- */
- void ReadShader(Q3Shader::ShaderData& fill) const;
-
- // -------------------------------------------------------------------
- /** Convert a texture path in a MD3 file to a proper value
- * @param[in] texture_name Path to be converted
- * @param[in] header_path Base path specified in MD3 header
- * @param[out] out Receives the converted output string
- */
- void ConvertPath(const char* texture_name, const char* header_path,
- std::string& out) const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Validate offsets in the header
+ */
+ void ValidateHeaderOffsets();
+ void ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurfHeader);
+
+ // -------------------------------------------------------------------
+ /** Read a Q3 multipart file
+ * @return true if multi part has been processed
+ */
+ bool ReadMultipartFile();
+
+ // -------------------------------------------------------------------
+ /** Try to read the skin for a MD3 file
+ * @param fill Receives output information
+ */
+ void ReadSkin(Q3Shader::SkinData& fill) const;
+
+ // -------------------------------------------------------------------
+ /** Try to read the shader for a MD3 file
+ * @param fill Receives output information
+ */
+ void ReadShader(Q3Shader::ShaderData& fill) const;
+
+ // -------------------------------------------------------------------
+ /** Convert a texture path in a MD3 file to a proper value
+ * @param[in] texture_name Path to be converted
+ * @param[in] header_path Base path specified in MD3 header
+ * @param[out] out Receives the converted output string
+ */
+ void ConvertPath(const char* texture_name, const char* header_path,
+ std::string& out) const;
protected:
- /** Configuration option: frame to be loaded */
- unsigned int configFrameID;
+ /** Configuration option: frame to be loaded */
+ unsigned int configFrameID;
- /** Configuration option: process multi-part files */
- bool configHandleMP;
+ /** Configuration option: process multi-part files */
+ bool configHandleMP;
- /** Configuration option: name of skin file to be read */
- std::string configSkinFile;
+ /** Configuration option: name of skin file to be read */
+ std::string configSkinFile;
- /** Configuration option: name or path of shader */
- std::string configShaderFile;
+ /** Configuration option: name or path of shader */
+ std::string configShaderFile;
- /** Configuration option: speed flag was set? */
- bool configSpeedFlag;
+ /** Configuration option: speed flag was set? */
+ bool configSpeedFlag;
- /** Header of the MD3 file */
- BE_NCONST MD3::Header* pcHeader;
+ /** Header of the MD3 file */
+ BE_NCONST MD3::Header* pcHeader;
- /** File buffer */
- BE_NCONST unsigned char* mBuffer;
+ /** File buffer */
+ BE_NCONST unsigned char* mBuffer;
- /** Size of the file, in bytes */
- unsigned int fileSize;
+ /** Size of the file, in bytes */
+ unsigned int fileSize;
- /** Current file name */
- std::string mFile;
+ /** Current file name */
+ std::string mFile;
- /** Current base directory */
- std::string path;
+ /** Current base directory */
+ std::string path;
- /** Pure file we're currently reading */
- std::string filename;
+ /** Pure file we're currently reading */
+ std::string filename;
- /** Output scene to be filled */
- aiScene* mScene;
+ /** Output scene to be filled */
+ aiScene* mScene;
- /** IO system to be used to access the data*/
- IOSystem* mIOHandler;
- };
+ /** IO system to be used to access the data*/
+ IOSystem* mIOHandler;
+ };
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/MD4FileData.h b/src/3rdparty/assimp/code/MD4FileData.h
index d5b037d2a..e515808ac 100644
--- a/src/3rdparty/assimp/code/MD4FileData.h
+++ b/src/3rdparty/assimp/code/MD4FileData.h
@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the ASSIMP Development Team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,17 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <sstream>
-#include "../include/aiTypes.h"
-#include "../include/aiMesh.h"
-#include "../include/aiAnim.h"
+#include "../include/assimp/types.h"
+#include "../include/assimp/mesh.h"
+#include "../include/assimp/anim.h"
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
-# pragma pack(push,1)
-# define PACK_STRUCT
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
+# pragma pack(push,1)
+# define PACK_STRUCT
#elif defined( __GNUC__ )
-# define PACK_STRUCT __attribute__((packed))
+# define PACK_STRUCT __attribute__((packed))
#else
-# error Compiler not supported
+# error Compiler not supported
#endif
@@ -66,17 +66,17 @@ namespace Assimp
namespace MD4
{
-#define AI_MD4_MAGIC_NUMBER_BE 'IDP4'
-#define AI_MD4_MAGIC_NUMBER_LE '4PDI'
+#define AI_MD4_MAGIC_NUMBER_BE 'IDP4'
+#define AI_MD4_MAGIC_NUMBER_LE '4PDI'
// common limitations
-#define AI_MD4_VERSION 4
-#define AI_MD4_MAXQPATH 64
-#define AI_MD4_MAX_FRAMES 2028
-#define AI_MD4_MAX_SURFACES 32
-#define AI_MD4_MAX_BONES 256
-#define AI_MD4_MAX_VERTS 4096
-#define AI_MD4_MAX_TRIANGLES 8192
+#define AI_MD4_VERSION 4
+#define AI_MD4_MAXQPATH 64
+#define AI_MD4_MAX_FRAMES 2028
+#define AI_MD4_MAX_SURFACES 32
+#define AI_MD4_MAX_BONES 256
+#define AI_MD4_MAX_VERTS 4096
+#define AI_MD4_MAX_TRIANGLES 8192
// ---------------------------------------------------------------------------
/** \brief Data structure for the MD4 main header
@@ -84,35 +84,35 @@ namespace MD4
// ---------------------------------------------------------------------------
struct Header
{
- //! magic number
- int32_t magic;
+ //! magic number
+ int32_t magic;
- //! file format version
- int32_t version;
+ //! file format version
+ int32_t version;
- //! original name in .pak archive
- unsigned char name[ AI_MD4_MAXQPATH ];
+ //! original name in .pak archive
+ unsigned char name[ AI_MD4_MAXQPATH ];
- //! number of frames in the file
- int32_t NUM_FRAMES;
+ //! number of frames in the file
+ int32_t NUM_FRAMES;
- //! number of bones in the file
- int32_t NUM_BONES;
+ //! number of bones in the file
+ int32_t NUM_BONES;
- //! number of surfaces in the file
- int32_t NUM_SURFACES;
+ //! number of surfaces in the file
+ int32_t NUM_SURFACES;
- //! offset of the first frame
- int32_t OFS_FRAMES;
+ //! offset of the first frame
+ int32_t OFS_FRAMES;
- //! offset of the first bone
- int32_t OFS_BONES;
+ //! offset of the first bone
+ int32_t OFS_BONES;
- //! offset of the first surface
- int32_t OFS_SURFACES;
+ //! offset of the first surface
+ int32_t OFS_SURFACES;
- //! end of file
- int32_t OFS_EOF;
+ //! end of file
+ int32_t OFS_EOF;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -120,8 +120,8 @@ struct Header
*/
// ---------------------------------------------------------------------------
struct BoneFrame
-{
- float matrix[3][4];
+{
+ float matrix[3][4];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -129,10 +129,10 @@ struct BoneFrame
*/
// ---------------------------------------------------------------------------
struct BoneName
-{
- char name[32] ;
- int parent ;
- int flags ;
+{
+ char name[32] ;
+ int parent ;
+ int flags ;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -140,22 +140,22 @@ struct BoneName
*/
// ---------------------------------------------------------------------------
struct Surface
-{
- int32_t ident;
- char name[64];
- char shader[64];
- int32_t shaderIndex;
- int32_t lodBias;
- int32_t minLod;
- int32_t ofsHeader;
- int32_t numVerts;
- int32_t ofsVerts;
- int32_t numTris;
- int32_t ofsTris;
- int32_t numBoneRefs;
- int32_t ofsBoneRefs;
- int32_t ofsCollapseMap;
- int32_t ofsEnd;
+{
+ int32_t ident;
+ char name[64];
+ char shader[64];
+ int32_t shaderIndex;
+ int32_t lodBias;
+ int32_t minLod;
+ int32_t ofsHeader;
+ int32_t numVerts;
+ int32_t ofsVerts;
+ int32_t numTris;
+ int32_t ofsTris;
+ int32_t numBoneRefs;
+ int32_t ofsBoneRefs;
+ int32_t ofsCollapseMap;
+ int32_t ofsEnd;
} PACK_STRUCT;
@@ -164,32 +164,32 @@ struct Surface
*/
// ---------------------------------------------------------------------------
struct Weight
-{
- int32_t boneIndex;
- float boneWeight;
- float offset[3];
-} PACK_STRUCT;
+{
+ int32_t boneIndex;
+ float boneWeight;
+ float offset[3];
+} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a vertex in a MD4 file
*/
// ---------------------------------------------------------------------------
struct Vertex
-{
- float vertex[3];
- float normal[3];
- float texCoords[2];
- int32_t numWeights;
- Weight weights[1];
-} PACK_STRUCT;
+{
+ float vertex[3];
+ float normal[3];
+ float texCoords[2];
+ int32_t numWeights;
+ Weight weights[1];
+} PACK_STRUCT;
// ---------------------------------------------------------------------------
/** \brief Data structure for a triangle in a MD4 file
*/
// ---------------------------------------------------------------------------
-struct Triangle
-{
- int32_t indexes[3];
+struct Triangle
+{
+ int32_t indexes[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -197,17 +197,17 @@ struct Triangle
*/
// ---------------------------------------------------------------------------
struct Frame
-{
- float bounds[3][2];
- float localOrigin[3];
- float radius;
- BoneFrame bones[1];
-} PACK_STRUCT;
+{
+ float bounds[3][2];
+ float localOrigin[3];
+ float radius;
+ BoneFrame bones[1];
+} PACK_STRUCT;
// reset packing to the original value
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
-# pragma pack( pop )
+# pragma pack( pop )
#endif
#undef PACK_STRUCT
@@ -215,4 +215,4 @@ struct Frame
};
};
-#endif // !! AI_MD4FILEHELPER_H_INC \ No newline at end of file
+#endif // !! AI_MD4FILEHELPER_H_INC
diff --git a/src/3rdparty/assimp/code/MD5Loader.cpp b/src/3rdparty/assimp/code/MD5Loader.cpp
index 65911f728..7927c9ab1 100644
--- a/src/3rdparty/assimp/code/MD5Loader.cpp
+++ b/src/3rdparty/assimp/code/MD5Loader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,25 +25,25 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file MD5Loader.cpp
- * @brief Implementation of the MD5 importer class
+ * @brief Implementation of the MD5 importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER
// internal headers
@@ -52,6 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h"
#include "fast_atof.h"
#include "SkeletonMeshBuilder.h"
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <memory>
using namespace Assimp;
@@ -60,495 +65,500 @@ using namespace Assimp;
static const aiImporterDesc desc = {
- "Doom 3 / MD5 Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "md5mesh md5camera md5anim"
+ "Doom 3 / MD5 Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "md5mesh md5camera md5anim"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MD5Importer::MD5Importer()
-: mBuffer()
-, configNoAutoLoad (false)
+ : mIOHandler()
+ , mBuffer()
+ , fileSize()
+ , iLineNumber()
+ , pScene()
+ , pIOHandler()
+ , bHadMD5Mesh()
+ , bHadMD5Anim()
+ , bHadMD5Camera()
+ , configNoAutoLoad (false)
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MD5Importer::~MD5Importer()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
- return true;
- else if (!extension.length() || checkSig) {
- if (!pIOHandler) {
- return true;
- }
- const char* tokens[] = {"MD5Version"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
+ return true;
+ else if (!extension.length() || checkSig) {
+ if (!pIOHandler) {
+ return true;
+ }
+ const char* tokens[] = {"MD5Version"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get list of all supported extensions
const aiImporterDesc* MD5Importer::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup import properties
void MD5Importer::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
- configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0));
+ // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
+ configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0));
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MD5Importer::InternReadFile( const std::string& pFile,
- aiScene* _pScene, IOSystem* _pIOHandler)
+// Imports the given file into the given scene structure.
+void MD5Importer::InternReadFile( const std::string& pFile,
+ aiScene* _pScene, IOSystem* _pIOHandler)
{
- pIOHandler = _pIOHandler;
- pScene = _pScene;
- bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
-
- // remove the file extension
- const std::string::size_type pos = pFile.find_last_of('.');
- mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1));
-
- const std::string extension = GetExtension(pFile);
- try {
- if (extension == "md5camera") {
- LoadMD5CameraFile();
- }
- else if (configNoAutoLoad || extension == "md5anim") {
- // determine file extension and process just *one* file
- if (extension.length() == 0) {
- throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
- }
- if (extension == "md5anim") {
- LoadMD5AnimFile();
- }
- else if (extension == "md5mesh") {
- LoadMD5MeshFile();
- }
- }
- else {
- LoadMD5MeshFile();
- LoadMD5AnimFile();
- }
- }
- catch ( ... ) { // std::exception, Assimp::DeadlyImportError
- UnloadFileFromMemory();
- throw;
- }
-
- // make sure we have at least one file
- if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) {
- throw DeadlyImportError("Failed to read valid contents out of this MD5* file");
- }
-
- // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
-
- // the output scene wouldn't pass the validation without this flag
- if (!bHadMD5Mesh) {
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- }
-
- // clean the instance -- the BaseImporter instance may be reused later.
- UnloadFileFromMemory();
+ pIOHandler = _pIOHandler;
+ pScene = _pScene;
+ bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
+
+ // remove the file extension
+ const std::string::size_type pos = pFile.find_last_of('.');
+ mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1));
+
+ const std::string extension = GetExtension(pFile);
+ try {
+ if (extension == "md5camera") {
+ LoadMD5CameraFile();
+ }
+ else if (configNoAutoLoad || extension == "md5anim") {
+ // determine file extension and process just *one* file
+ if (extension.length() == 0) {
+ throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
+ }
+ if (extension == "md5anim") {
+ LoadMD5AnimFile();
+ }
+ else if (extension == "md5mesh") {
+ LoadMD5MeshFile();
+ }
+ }
+ else {
+ LoadMD5MeshFile();
+ LoadMD5AnimFile();
+ }
+ }
+ catch ( ... ) { // std::exception, Assimp::DeadlyImportError
+ UnloadFileFromMemory();
+ throw;
+ }
+
+ // make sure we have at least one file
+ if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) {
+ throw DeadlyImportError("Failed to read valid contents out of this MD5* file");
+ }
+
+ // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
+ pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+
+ // the output scene wouldn't pass the validation without this flag
+ if (!bHadMD5Mesh) {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+
+ // clean the instance -- the BaseImporter instance may be reused later.
+ UnloadFileFromMemory();
}
// ------------------------------------------------------------------------------------------------
// Load a file into a memory buffer
void MD5Importer::LoadFileIntoMemory (IOStream* file)
{
- // unload the previous buffer, if any
- UnloadFileFromMemory();
+ // unload the previous buffer, if any
+ UnloadFileFromMemory();
- ai_assert(NULL != file);
- fileSize = (unsigned int)file->FileSize();
- ai_assert(fileSize);
+ ai_assert(NULL != file);
+ fileSize = (unsigned int)file->FileSize();
+ ai_assert(fileSize);
- // allocate storage and copy the contents of the file to a memory buffer
- mBuffer = new char[fileSize+1];
- file->Read( (void*)mBuffer, 1, fileSize);
- iLineNumber = 1;
+ // allocate storage and copy the contents of the file to a memory buffer
+ mBuffer = new char[fileSize+1];
+ file->Read( (void*)mBuffer, 1, fileSize);
+ iLineNumber = 1;
- // append a terminal 0
- mBuffer[fileSize] = '\0';
+ // append a terminal 0
+ mBuffer[fileSize] = '\0';
- // now remove all line comments from the file
- CommentRemover::RemoveLineComments("//",mBuffer,' ');
+ // now remove all line comments from the file
+ CommentRemover::RemoveLineComments("//",mBuffer,' ');
}
// ------------------------------------------------------------------------------------------------
// Unload the current memory buffer
void MD5Importer::UnloadFileFromMemory ()
{
- // delete the file buffer
- delete[] mBuffer;
- mBuffer = NULL;
- fileSize = 0;
+ // delete the file buffer
+ delete[] mBuffer;
+ mBuffer = NULL;
+ fileSize = 0;
}
// ------------------------------------------------------------------------------------------------
// Build unique vertices
void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc)
{
- std::vector<bool> abHad(meshSrc.mVertices.size(),false);
-
- // allocate enough storage to keep the output structures
- const unsigned int iNewNum = meshSrc.mFaces.size()*3;
- unsigned int iNewIndex = meshSrc.mVertices.size();
- meshSrc.mVertices.resize(iNewNum);
-
- // try to guess how much storage we'll need for new weights
- const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex;
- const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum);
- meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer
-
- for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){
- const aiFace& face = *iter;
- for (unsigned int i = 0; i < 3;++i) {
- if (face.mIndices[0] >= meshSrc.mVertices.size()) {
- throw DeadlyImportError("MD5MESH: Invalid vertex index");
- }
-
- if (abHad[face.mIndices[i]]) {
- // generate a new vertex
- meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]];
- face.mIndices[i] = iNewIndex++;
- }
- else abHad[face.mIndices[i]] = true;
- }
- // swap face order
- std::swap(face.mIndices[0],face.mIndices[2]);
- }
+ std::vector<bool> abHad(meshSrc.mVertices.size(),false);
+
+ // allocate enough storage to keep the output structures
+ const unsigned int iNewNum = meshSrc.mFaces.size()*3;
+ unsigned int iNewIndex = meshSrc.mVertices.size();
+ meshSrc.mVertices.resize(iNewNum);
+
+ // try to guess how much storage we'll need for new weights
+ const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex;
+ const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum);
+ meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer
+
+ for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){
+ const aiFace& face = *iter;
+ for (unsigned int i = 0; i < 3;++i) {
+ if (face.mIndices[0] >= meshSrc.mVertices.size()) {
+ throw DeadlyImportError("MD5MESH: Invalid vertex index");
+ }
+
+ if (abHad[face.mIndices[i]]) {
+ // generate a new vertex
+ meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]];
+ face.mIndices[i] = iNewIndex++;
+ }
+ else abHad[face.mIndices[i]] = true;
+ }
+ // swap face order
+ std::swap(face.mIndices[0],face.mIndices[2]);
+ }
}
// ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5MESH
void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones)
{
- ai_assert(NULL != piParent && !piParent->mNumChildren);
-
- // First find out how many children we'll have
- for (int i = 0; i < (int)bones.size();++i) {
- if (iParentID != i && bones[i].mParentIndex == iParentID) {
- ++piParent->mNumChildren;
- }
- }
- if (piParent->mNumChildren) {
- piParent->mChildren = new aiNode*[piParent->mNumChildren];
- for (int i = 0; i < (int)bones.size();++i) {
- // (avoid infinite recursion)
- if (iParentID != i && bones[i].mParentIndex == iParentID) {
- aiNode* pc;
- // setup a new node
- *piParent->mChildren++ = pc = new aiNode();
- pc->mName = aiString(bones[i].mName);
- pc->mParent = piParent;
-
- // get the transformation matrix from rotation and translational components
- aiQuaternion quat;
- MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat );
-
- // FIX to get to Assimp's quaternion conventions
- quat.w *= -1.f;
-
- bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix());
- bones[i].mTransform.a4 = bones[i].mPositionXYZ.x;
- bones[i].mTransform.b4 = bones[i].mPositionXYZ.y;
- bones[i].mTransform.c4 = bones[i].mPositionXYZ.z;
-
- // store it for later use
- pc->mTransformation = bones[i].mInvTransform = bones[i].mTransform;
- bones[i].mInvTransform.Inverse();
-
- // the transformations for each bone are absolute, so we need to multiply them
- // with the inverse of the absolute matrix of the parent joint
- if (-1 != iParentID) {
- pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation;
- }
-
- // add children to this node, too
- AttachChilds_Mesh( i, pc, bones);
- }
- }
- // undo offset computations
- piParent->mChildren -= piParent->mNumChildren;
- }
+ ai_assert(NULL != piParent && !piParent->mNumChildren);
+
+ // First find out how many children we'll have
+ for (int i = 0; i < (int)bones.size();++i) {
+ if (iParentID != i && bones[i].mParentIndex == iParentID) {
+ ++piParent->mNumChildren;
+ }
+ }
+ if (piParent->mNumChildren) {
+ piParent->mChildren = new aiNode*[piParent->mNumChildren];
+ for (int i = 0; i < (int)bones.size();++i) {
+ // (avoid infinite recursion)
+ if (iParentID != i && bones[i].mParentIndex == iParentID) {
+ aiNode* pc;
+ // setup a new node
+ *piParent->mChildren++ = pc = new aiNode();
+ pc->mName = aiString(bones[i].mName);
+ pc->mParent = piParent;
+
+ // get the transformation matrix from rotation and translational components
+ aiQuaternion quat;
+ MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat );
+
+ bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix());
+ bones[i].mTransform.a4 = bones[i].mPositionXYZ.x;
+ bones[i].mTransform.b4 = bones[i].mPositionXYZ.y;
+ bones[i].mTransform.c4 = bones[i].mPositionXYZ.z;
+
+ // store it for later use
+ pc->mTransformation = bones[i].mInvTransform = bones[i].mTransform;
+ bones[i].mInvTransform.Inverse();
+
+ // the transformations for each bone are absolute, so we need to multiply them
+ // with the inverse of the absolute matrix of the parent joint
+ if (-1 != iParentID) {
+ pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation;
+ }
+
+ // add children to this node, too
+ AttachChilds_Mesh( i, pc, bones);
+ }
+ }
+ // undo offset computations
+ piParent->mChildren -= piParent->mNumChildren;
+ }
}
// ------------------------------------------------------------------------------------------------
// Recursive node graph construction from a MD5ANIM
void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims)
{
- ai_assert(NULL != piParent && !piParent->mNumChildren);
-
- // First find out how many children we'll have
- for (int i = 0; i < (int)bones.size();++i) {
- if (iParentID != i && bones[i].mParentIndex == iParentID) {
- ++piParent->mNumChildren;
- }
- }
- if (piParent->mNumChildren) {
- piParent->mChildren = new aiNode*[piParent->mNumChildren];
- for (int i = 0; i < (int)bones.size();++i) {
- // (avoid infinite recursion)
- if (iParentID != i && bones[i].mParentIndex == iParentID)
- {
- aiNode* pc;
- // setup a new node
- *piParent->mChildren++ = pc = new aiNode();
- pc->mName = aiString(bones[i].mName);
- pc->mParent = piParent;
-
- // get the corresponding animation channel and its first frame
- const aiNodeAnim** cur = node_anims;
- while ((**cur).mNodeName != pc->mName)++cur;
-
- aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation);
- pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ;
-
- // add children to this node, too
- AttachChilds_Anim( i, pc, bones,node_anims);
- }
- }
- // undo offset computations
- piParent->mChildren -= piParent->mNumChildren;
- }
+ ai_assert(NULL != piParent && !piParent->mNumChildren);
+
+ // First find out how many children we'll have
+ for (int i = 0; i < (int)bones.size();++i) {
+ if (iParentID != i && bones[i].mParentIndex == iParentID) {
+ ++piParent->mNumChildren;
+ }
+ }
+ if (piParent->mNumChildren) {
+ piParent->mChildren = new aiNode*[piParent->mNumChildren];
+ for (int i = 0; i < (int)bones.size();++i) {
+ // (avoid infinite recursion)
+ if (iParentID != i && bones[i].mParentIndex == iParentID)
+ {
+ aiNode* pc;
+ // setup a new node
+ *piParent->mChildren++ = pc = new aiNode();
+ pc->mName = aiString(bones[i].mName);
+ pc->mParent = piParent;
+
+ // get the corresponding animation channel and its first frame
+ const aiNodeAnim** cur = node_anims;
+ while ((**cur).mNodeName != pc->mName)++cur;
+
+ aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation);
+ pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ;
+
+ // add children to this node, too
+ AttachChilds_Anim( i, pc, bones,node_anims);
+ }
+ }
+ // undo offset computations
+ piParent->mChildren -= piParent->mNumChildren;
+ }
}
// ------------------------------------------------------------------------------------------------
// Load a MD5MESH file
void MD5Importer::LoadMD5MeshFile ()
{
- std::string pFile = mFile + "md5mesh";
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL || !file->FileSize()) {
- DefaultLogger::get()->warn("Failed to access MD5MESH file: " + pFile);
- return;
- }
- bHadMD5Mesh = true;
- LoadFileIntoMemory(file.get());
-
- // now construct a parser and parse the file
- MD5::MD5Parser parser(mBuffer,fileSize);
-
- // load the mesh information from it
- MD5::MD5MeshParser meshParser(parser.mSections);
-
- // create the bone hierarchy - first the root node and dummy nodes for all meshes
- pScene->mRootNode = new aiNode("<MD5_Root>");
- pScene->mRootNode->mNumChildren = 2;
- pScene->mRootNode->mChildren = new aiNode*[2];
-
- // build the hierarchy from the MD5MESH file
- aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
- pcNode->mName.Set("<MD5_Hierarchy>");
- pcNode->mParent = pScene->mRootNode;
- AttachChilds_Mesh(-1,pcNode,meshParser.mJoints);
-
- pcNode = pScene->mRootNode->mChildren[0] = new aiNode();
- pcNode->mName.Set("<MD5_Mesh>");
- pcNode->mParent = pScene->mRootNode;
+ std::string pFile = mFile + "md5mesh";
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL || !file->FileSize()) {
+ DefaultLogger::get()->warn("Failed to access MD5MESH file: " + pFile);
+ return;
+ }
+ bHadMD5Mesh = true;
+ LoadFileIntoMemory(file.get());
+
+ // now construct a parser and parse the file
+ MD5::MD5Parser parser(mBuffer,fileSize);
+
+ // load the mesh information from it
+ MD5::MD5MeshParser meshParser(parser.mSections);
+
+ // create the bone hierarchy - first the root node and dummy nodes for all meshes
+ pScene->mRootNode = new aiNode("<MD5_Root>");
+ pScene->mRootNode->mNumChildren = 2;
+ pScene->mRootNode->mChildren = new aiNode*[2];
+
+ // build the hierarchy from the MD5MESH file
+ aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
+ pcNode->mName.Set("<MD5_Hierarchy>");
+ pcNode->mParent = pScene->mRootNode;
+ AttachChilds_Mesh(-1,pcNode,meshParser.mJoints);
+
+ pcNode = pScene->mRootNode->mChildren[0] = new aiNode();
+ pcNode->mName.Set("<MD5_Mesh>");
+ pcNode->mParent = pScene->mRootNode;
#if 0
- if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */
- SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[1]->mChildren[0]);
+ if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */
+ SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[1]->mChildren[0]);
#else
- // FIX: MD5 files exported from Blender can have empty meshes
- for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
- if (!(*it).mFaces.empty() && !(*it).mVertices.empty())
- ++pScene->mNumMaterials;
- }
-
- // generate all meshes
- pScene->mNumMeshes = pScene->mNumMaterials;
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
-
- // storage for node mesh indices
- pcNode->mNumMeshes = pScene->mNumMeshes;
- pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
- for (unsigned int m = 0; m < pcNode->mNumMeshes;++m)
- pcNode->mMeshes[m] = m;
-
- unsigned int n = 0;
- for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
- MD5::MeshDesc& meshSrc = *it;
- if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty())
- continue;
-
- aiMesh* mesh = pScene->mMeshes[n] = new aiMesh();
- mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // generate unique vertices in our internal verbose format
- MakeDataUnique(meshSrc);
-
- mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size();
- mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
- mesh->mNumUVComponents[0] = 2;
-
- // copy texture coordinates
- aiVector3D* pv = mesh->mTextureCoords[0];
- for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
- pv->x = (*iter).mUV.x;
- pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL
- pv->z = 0.0f;
- }
-
- // sort all bone weights - per bone
- unsigned int* piCount = new unsigned int[meshParser.mJoints.size()];
- ::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size());
-
- for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
- for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
- {
- MD5::WeightDesc& desc = meshSrc.mWeights[w];
- /* FIX for some invalid exporters */
- if (!(desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
- ++piCount[desc.mBone];
- }
- }
-
- // check how many we will need
- for (unsigned int p = 0; p < meshParser.mJoints.size();++p)
- if (piCount[p])mesh->mNumBones++;
-
- if (mesh->mNumBones) // just for safety
- {
- mesh->mBones = new aiBone*[mesh->mNumBones];
- for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q)
- {
- if (!piCount[q])continue;
- aiBone* p = mesh->mBones[h] = new aiBone();
- p->mNumWeights = piCount[q];
- p->mWeights = new aiVertexWeight[p->mNumWeights];
- p->mName = aiString(meshParser.mJoints[q].mName);
- p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform;
-
- // store the index for later use
- MD5::BoneDesc& boneSrc = meshParser.mJoints[q];
- boneSrc.mMap = h++;
-
- // compute w-component of quaternion
- MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted );
- }
-
- //unsigned int g = 0;
- pv = mesh->mVertices;
- for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
- // compute the final vertex position from all single weights
- *pv = aiVector3D();
-
- // there are models which have weights which don't sum to 1 ...
- float fSum = 0.0f;
- for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
- fSum += meshSrc.mWeights[w].mWeight;
- if (!fSum) {
- DefaultLogger::get()->error("MD5MESH: The sum of all vertex bone weights is 0");
- continue;
- }
-
- // process bone weights
- for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) {
- if (w >= meshSrc.mWeights.size())
- throw DeadlyImportError("MD5MESH: Invalid weight index");
-
- MD5::WeightDesc& desc = meshSrc.mWeights[w];
- if ( desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
- continue;
- }
-
- const float fNewWeight = desc.mWeight / fSum;
-
- // transform the local position into worldspace
- MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone];
- const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (desc.vOffsetPosition);
-
- // use the original weight to compute the vertex position
- // (some MD5s seem to depend on the invalid weight values ...)
- *pv += ((boneSrc.mPositionXYZ+v)* desc.mWeight);
-
- aiBone* bone = mesh->mBones[boneSrc.mMap];
- *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
- }
- }
-
- // undo our nice offset tricks ...
- for (unsigned int p = 0; p < mesh->mNumBones;++p) {
- mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights;
- }
- }
-
- delete[] piCount;
-
- // now setup all faces - we can directly copy the list
- // (however, take care that the aiFace destructor doesn't delete the mIndices array)
- mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size();
- mesh->mFaces = new aiFace[mesh->mNumFaces];
- for (unsigned int c = 0; c < mesh->mNumFaces;++c) {
- mesh->mFaces[c].mNumIndices = 3;
- mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
- meshSrc.mFaces[c].mIndices = NULL;
- }
-
- // generate a material for the mesh
- aiMaterial* mat = new aiMaterial();
- pScene->mMaterials[n] = mat;
-
- // insert the typical doom3 textures:
- // nnn_local.tga - normal map
- // nnn_h.tga - height map
- // nnn_s.tga - specular map
- // nnn_d.tga - diffuse map
- if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) {
-
- aiString temp(meshSrc.mShader);
- temp.Append("_local.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0));
-
- temp = aiString(meshSrc.mShader);
- temp.Append("_s.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0));
-
- temp = aiString(meshSrc.mShader);
- temp.Append("_d.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
- temp = aiString(meshSrc.mShader);
- temp.Append("_h.tga");
- mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0));
-
- // set this also as material name
- mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME);
- }
- else mat->AddProperty(&meshSrc.mShader,AI_MATKEY_TEXTURE_DIFFUSE(0));
- mesh->mMaterialIndex = n++;
- }
+ // FIX: MD5 files exported from Blender can have empty meshes
+ for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
+ if (!(*it).mFaces.empty() && !(*it).mVertices.empty())
+ ++pScene->mNumMaterials;
+ }
+
+ // generate all meshes
+ pScene->mNumMeshes = pScene->mNumMaterials;
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes];
+
+ // storage for node mesh indices
+ pcNode->mNumMeshes = pScene->mNumMeshes;
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+ for (unsigned int m = 0; m < pcNode->mNumMeshes;++m)
+ pcNode->mMeshes[m] = m;
+
+ unsigned int n = 0;
+ for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) {
+ MD5::MeshDesc& meshSrc = *it;
+ if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty())
+ continue;
+
+ aiMesh* mesh = pScene->mMeshes[n] = new aiMesh();
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // generate unique vertices in our internal verbose format
+ MakeDataUnique(meshSrc);
+
+ mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size();
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+ mesh->mNumUVComponents[0] = 2;
+
+ // copy texture coordinates
+ aiVector3D* pv = mesh->mTextureCoords[0];
+ for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
+ pv->x = (*iter).mUV.x;
+ pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL
+ pv->z = 0.0f;
+ }
+
+ // sort all bone weights - per bone
+ unsigned int* piCount = new unsigned int[meshParser.mJoints.size()];
+ ::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size());
+
+ for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
+ for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
+ {
+ MD5::WeightDesc& desc = meshSrc.mWeights[w];
+ /* FIX for some invalid exporters */
+ if (!(desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
+ ++piCount[desc.mBone];
+ }
+ }
+
+ // check how many we will need
+ for (unsigned int p = 0; p < meshParser.mJoints.size();++p)
+ if (piCount[p])mesh->mNumBones++;
+
+ if (mesh->mNumBones) // just for safety
+ {
+ mesh->mBones = new aiBone*[mesh->mNumBones];
+ for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q)
+ {
+ if (!piCount[q])continue;
+ aiBone* p = mesh->mBones[h] = new aiBone();
+ p->mNumWeights = piCount[q];
+ p->mWeights = new aiVertexWeight[p->mNumWeights];
+ p->mName = aiString(meshParser.mJoints[q].mName);
+ p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform;
+
+ // store the index for later use
+ MD5::BoneDesc& boneSrc = meshParser.mJoints[q];
+ boneSrc.mMap = h++;
+
+ // compute w-component of quaternion
+ MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted );
+ }
+
+ //unsigned int g = 0;
+ pv = mesh->mVertices;
+ for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
+ // compute the final vertex position from all single weights
+ *pv = aiVector3D();
+
+ // there are models which have weights which don't sum to 1 ...
+ float fSum = 0.0f;
+ for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
+ fSum += meshSrc.mWeights[w].mWeight;
+ if (!fSum) {
+ DefaultLogger::get()->error("MD5MESH: The sum of all vertex bone weights is 0");
+ continue;
+ }
+
+ // process bone weights
+ for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) {
+ if (w >= meshSrc.mWeights.size())
+ throw DeadlyImportError("MD5MESH: Invalid weight index");
+
+ MD5::WeightDesc& desc = meshSrc.mWeights[w];
+ if ( desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
+ continue;
+ }
+
+ const float fNewWeight = desc.mWeight / fSum;
+
+ // transform the local position into worldspace
+ MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone];
+ const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (desc.vOffsetPosition);
+
+ // use the original weight to compute the vertex position
+ // (some MD5s seem to depend on the invalid weight values ...)
+ *pv += ((boneSrc.mPositionXYZ+v)* desc.mWeight);
+
+ aiBone* bone = mesh->mBones[boneSrc.mMap];
+ *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);
+ }
+ }
+
+ // undo our nice offset tricks ...
+ for (unsigned int p = 0; p < mesh->mNumBones;++p) {
+ mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights;
+ }
+ }
+
+ delete[] piCount;
+
+ // now setup all faces - we can directly copy the list
+ // (however, take care that the aiFace destructor doesn't delete the mIndices array)
+ mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size();
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+ for (unsigned int c = 0; c < mesh->mNumFaces;++c) {
+ mesh->mFaces[c].mNumIndices = 3;
+ mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
+ meshSrc.mFaces[c].mIndices = NULL;
+ }
+
+ // generate a material for the mesh
+ aiMaterial* mat = new aiMaterial();
+ pScene->mMaterials[n] = mat;
+
+ // insert the typical doom3 textures:
+ // nnn_local.tga - normal map
+ // nnn_h.tga - height map
+ // nnn_s.tga - specular map
+ // nnn_d.tga - diffuse map
+ if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) {
+
+ aiString temp(meshSrc.mShader);
+ temp.Append("_local.tga");
+ mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0));
+
+ temp = aiString(meshSrc.mShader);
+ temp.Append("_s.tga");
+ mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0));
+
+ temp = aiString(meshSrc.mShader);
+ temp.Append("_d.tga");
+ mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+ temp = aiString(meshSrc.mShader);
+ temp.Append("_h.tga");
+ mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0));
+
+ // set this also as material name
+ mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME);
+ }
+ else mat->AddProperty(&meshSrc.mShader,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ mesh->mMaterialIndex = n++;
+ }
#endif
}
@@ -556,193 +566,190 @@ void MD5Importer::LoadMD5MeshFile ()
// Load an MD5ANIM file
void MD5Importer::LoadMD5AnimFile ()
{
- std::string pFile = mFile + "md5anim";
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( !file.get() || !file->FileSize()) {
- DefaultLogger::get()->warn("Failed to read MD5ANIM file: " + pFile);
- return;
- }
- LoadFileIntoMemory(file.get());
-
- // parse the basic file structure
- MD5::MD5Parser parser(mBuffer,fileSize);
-
- // load the animation information from the parse tree
- MD5::MD5AnimParser animParser(parser.mSections);
-
- // generate and fill the output animation
- if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
- animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
-
- DefaultLogger::get()->error("MD5ANIM: No frames or animated bones loaded");
- }
- else {
- bHadMD5Anim = true;
-
- pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1];
- aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation();
- anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
- for (unsigned int i = 0; i < anim->mNumChannels;++i) {
- aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim();
- node->mNodeName = aiString( animParser.mAnimatedBones[i].mName );
-
- // allocate storage for the keyframes
- node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()];
- node->mRotationKeys = new aiQuatKey[animParser.mFrames.size()];
- }
-
- // 1 tick == 1 frame
- anim->mTicksPerSecond = animParser.fFrameRate;
-
- for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){
- double dTime = (double)(*iter).iIndex;
- aiNodeAnim** pcAnimNode = anim->mChannels;
- if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */
- {
- // now process all values in there ... read all joints
- MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0];
- for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2,
- ++pcAnimNode,++pcBaseFrame)
- {
- if((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
-
- // Allow for empty frames
- if ((*iter2).iFlags != 0) {
- throw DeadlyImportError("MD5: Keyframe index is out of range");
-
- }
- continue;
- }
- const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
- aiNodeAnim* pcCurAnimBone = *pcAnimNode;
-
- aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
- aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++];
- aiVector3D vTemp;
-
- // translational component
- for (unsigned int i = 0; i < 3; ++i) {
- if ((*iter2).iFlags & (1u << i)) {
- vKey->mValue[i] = *fpCur++;
- }
- else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
- }
-
- // orientation component
- for (unsigned int i = 0; i < 3; ++i) {
- if ((*iter2).iFlags & (8u << i)) {
- vTemp[i] = *fpCur++;
- }
- else vTemp[i] = pcBaseFrame->vRotationQuat[i];
- }
-
- MD5::ConvertQuaternion(vTemp, qKey->mValue);
- qKey->mTime = vKey->mTime = dTime;
-
- // we need this to get to Assimp quaternion conventions
- qKey->mValue.w *= -1.f;
- }
- }
-
- // compute the duration of the animation
- anim->mDuration = std::max(dTime,anim->mDuration);
- }
-
- // If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
- // construct it now from the data given in the MD5ANIM.
- if (!pScene->mRootNode) {
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
-
- AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels);
-
- // Call SkeletonMeshBuilder to construct a mesh to represent the shape
- if (pScene->mRootNode->mNumChildren) {
- SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]);
- }
- }
- }
+ std::string pFile = mFile + "md5anim";
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( !file.get() || !file->FileSize()) {
+ DefaultLogger::get()->warn("Failed to read MD5ANIM file: " + pFile);
+ return;
+ }
+ LoadFileIntoMemory(file.get());
+
+ // parse the basic file structure
+ MD5::MD5Parser parser(mBuffer,fileSize);
+
+ // load the animation information from the parse tree
+ MD5::MD5AnimParser animParser(parser.mSections);
+
+ // generate and fill the output animation
+ if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
+ animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
+
+ DefaultLogger::get()->error("MD5ANIM: No frames or animated bones loaded");
+ }
+ else {
+ bHadMD5Anim = true;
+
+ pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1];
+ aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation();
+ anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+ for (unsigned int i = 0; i < anim->mNumChannels;++i) {
+ aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim();
+ node->mNodeName = aiString( animParser.mAnimatedBones[i].mName );
+
+ // allocate storage for the keyframes
+ node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()];
+ node->mRotationKeys = new aiQuatKey[animParser.mFrames.size()];
+ }
+
+ // 1 tick == 1 frame
+ anim->mTicksPerSecond = animParser.fFrameRate;
+
+ for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){
+ double dTime = (double)(*iter).iIndex;
+ aiNodeAnim** pcAnimNode = anim->mChannels;
+ if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */
+ {
+ // now process all values in there ... read all joints
+ MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0];
+ for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2,
+ ++pcAnimNode,++pcBaseFrame)
+ {
+ if((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) {
+
+ // Allow for empty frames
+ if ((*iter2).iFlags != 0) {
+ throw DeadlyImportError("MD5: Keyframe index is out of range");
+
+ }
+ continue;
+ }
+ const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex];
+ aiNodeAnim* pcCurAnimBone = *pcAnimNode;
+
+ aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++];
+ aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++];
+ aiVector3D vTemp;
+
+ // translational component
+ for (unsigned int i = 0; i < 3; ++i) {
+ if ((*iter2).iFlags & (1u << i)) {
+ vKey->mValue[i] = *fpCur++;
+ }
+ else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i];
+ }
+
+ // orientation component
+ for (unsigned int i = 0; i < 3; ++i) {
+ if ((*iter2).iFlags & (8u << i)) {
+ vTemp[i] = *fpCur++;
+ }
+ else vTemp[i] = pcBaseFrame->vRotationQuat[i];
+ }
+
+ MD5::ConvertQuaternion(vTemp, qKey->mValue);
+ qKey->mTime = vKey->mTime = dTime;
+ }
+ }
+
+ // compute the duration of the animation
+ anim->mDuration = std::max(dTime,anim->mDuration);
+ }
+
+ // If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
+ // construct it now from the data given in the MD5ANIM.
+ if (!pScene->mRootNode) {
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
+
+ AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels);
+
+ // Call SkeletonMeshBuilder to construct a mesh to represent the shape
+ if (pScene->mRootNode->mNumChildren) {
+ SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]);
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Load an MD5CAMERA file
void MD5Importer::LoadMD5CameraFile ()
{
- std::string pFile = mFile + "md5camera";
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( !file.get() || !file->FileSize()) {
- throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
- }
- bHadMD5Camera = true;
- LoadFileIntoMemory(file.get());
-
- // parse the basic file structure
- MD5::MD5Parser parser(mBuffer,fileSize);
-
- // load the camera animation data from the parse tree
- MD5::MD5CameraParser cameraParser(parser.mSections);
-
- if (cameraParser.frames.empty()) {
- throw DeadlyImportError("MD5CAMERA: No frames parsed");
- }
-
- std::vector<unsigned int>& cuts = cameraParser.cuts;
- std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames;
-
- // Construct output graph - a simple root with a dummy child.
- // The root node performs the coordinate system conversion
- aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
- root->mChildren = new aiNode*[root->mNumChildren = 1];
- root->mChildren[0] = new aiNode("<MD5Camera>");
- root->mChildren[0]->mParent = root;
-
- // ... but with one camera assigned to it
- pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1];
- aiCamera* cam = pScene->mCameras[0] = new aiCamera();
- cam->mName = "<MD5Camera>";
-
- // FIXME: Fov is currently set to the first frame's value
- cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV );
-
- // every cut is written to a separate aiAnimation
- if (!cuts.size()) {
- cuts.push_back(0);
- cuts.push_back(frames.size()-1);
- }
- else {
- cuts.insert(cuts.begin(),0);
-
- if (cuts.back() < frames.size()-1)
- cuts.push_back(frames.size()-1);
- }
-
- pScene->mNumAnimations = cuts.size()-1;
- aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations];
- for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) {
-
- aiAnimation* anim = *tmp++ = new aiAnimation();
- anim->mName.length = ::sprintf(anim->mName.data,"anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1));
-
- anim->mTicksPerSecond = cameraParser.fFrameRate;
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1];
- aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim();
- nd->mNodeName.Set("<MD5Camera>");
-
- nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it);
- nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
- nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys];
- for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) {
-
- nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ;
- MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue);
- nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i;
- }
- }
+ std::string pFile = mFile + "md5camera";
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( !file.get() || !file->FileSize()) {
+ throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
+ }
+ bHadMD5Camera = true;
+ LoadFileIntoMemory(file.get());
+
+ // parse the basic file structure
+ MD5::MD5Parser parser(mBuffer,fileSize);
+
+ // load the camera animation data from the parse tree
+ MD5::MD5CameraParser cameraParser(parser.mSections);
+
+ if (cameraParser.frames.empty()) {
+ throw DeadlyImportError("MD5CAMERA: No frames parsed");
+ }
+
+ std::vector<unsigned int>& cuts = cameraParser.cuts;
+ std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames;
+
+ // Construct output graph - a simple root with a dummy child.
+ // The root node performs the coordinate system conversion
+ aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
+ root->mChildren = new aiNode*[root->mNumChildren = 1];
+ root->mChildren[0] = new aiNode("<MD5Camera>");
+ root->mChildren[0]->mParent = root;
+
+ // ... but with one camera assigned to it
+ pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1];
+ aiCamera* cam = pScene->mCameras[0] = new aiCamera();
+ cam->mName = "<MD5Camera>";
+
+ // FIXME: Fov is currently set to the first frame's value
+ cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV );
+
+ // every cut is written to a separate aiAnimation
+ if (!cuts.size()) {
+ cuts.push_back(0);
+ cuts.push_back(frames.size()-1);
+ }
+ else {
+ cuts.insert(cuts.begin(),0);
+
+ if (cuts.back() < frames.size()-1)
+ cuts.push_back(frames.size()-1);
+ }
+
+ pScene->mNumAnimations = cuts.size()-1;
+ aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations];
+ for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) {
+
+ aiAnimation* anim = *tmp++ = new aiAnimation();
+ anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1));
+
+ anim->mTicksPerSecond = cameraParser.fFrameRate;
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1];
+ aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim();
+ nd->mNodeName.Set("<MD5Camera>");
+
+ nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it);
+ nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+ nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys];
+ for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) {
+
+ nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ;
+ MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue);
+ nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i;
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_MD5_IMPORTER
diff --git a/src/3rdparty/assimp/code/MD5Loader.h b/src/3rdparty/assimp/code/MD5Loader.h
index c9563bddb..9dfc08226 100644
--- a/src/3rdparty/assimp/code/MD5Loader.h
+++ b/src/3rdparty/assimp/code/MD5Loader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,9 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "MD5Parser.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
-namespace Assimp {
+struct aiNode;
+struct aiNodeAnim;
+
+namespace Assimp {
class IOStream;
using namespace Assimp::MD5;
@@ -62,127 +65,127 @@ using namespace Assimp::MD5;
class MD5Importer : public BaseImporter
{
public:
- MD5Importer();
- ~MD5Importer();
+ MD5Importer();
+ ~MD5Importer();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
-
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
-
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Load a *.MD5MESH file.
- */
- void LoadMD5MeshFile ();
-
- // -------------------------------------------------------------------
- /** Load a *.MD5ANIM file.
- */
- void LoadMD5AnimFile ();
-
- // -------------------------------------------------------------------
- /** Load a *.MD5CAMERA file.
- */
- void LoadMD5CameraFile ();
-
- // -------------------------------------------------------------------
- /** Construct node hierarchy from a given MD5ANIM
- * @param iParentID Current parent ID
- * @param piParent Parent node to attach to
- * @param bones Input bones
- * @param node_anims Generated node animations
- */
- void AttachChilds_Anim(int iParentID,aiNode* piParent,
- AnimBoneList& bones,const aiNodeAnim** node_anims);
-
- // -------------------------------------------------------------------
- /** Construct node hierarchy from a given MD5MESH
- * @param iParentID Current parent ID
- * @param piParent Parent node to attach to
- * @param bones Input bones
- */
- void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones);
-
- // -------------------------------------------------------------------
- /** Build unique vertex buffers from a given MD5ANIM
- * @param meshSrc Input data
- */
- void MakeDataUnique (MD5::MeshDesc& meshSrc);
-
- // -------------------------------------------------------------------
- /** Load the contents of a specific file into memory and
- * alocates a buffer to keep it.
- *
- * mBuffer is modified to point to this buffer.
- * @param pFile File stream to be read
- */
- void LoadFileIntoMemory (IOStream* pFile);
- void UnloadFileFromMemory ();
-
-
- /** IOSystem to be used to access files */
- IOSystem* mIOHandler;
-
- /** Path to the file, excluding the file extension but
- with the dot */
- std::string mFile;
-
- /** Buffer to hold the loaded file */
- char* mBuffer;
-
- /** Size of the file */
- unsigned int fileSize;
-
- /** Current line number. For debugging purposes */
- unsigned int iLineNumber;
-
- /** Scene to be filled */
- aiScene* pScene;
-
- /** (Custom) I/O handler implementation */
- IOSystem* pIOHandler;
-
- /** true if a MD5MESH file has already been parsed */
- bool bHadMD5Mesh;
-
- /** true if a MD5ANIM file has already been parsed */
- bool bHadMD5Anim;
-
- /** true if a MD5CAMERA file has already been parsed */
- bool bHadMD5Camera;
-
- /** configuration option: prevent anim autoload */
- bool configNoAutoLoad;
+ // -------------------------------------------------------------------
+ /** Load a *.MD5MESH file.
+ */
+ void LoadMD5MeshFile ();
+
+ // -------------------------------------------------------------------
+ /** Load a *.MD5ANIM file.
+ */
+ void LoadMD5AnimFile ();
+
+ // -------------------------------------------------------------------
+ /** Load a *.MD5CAMERA file.
+ */
+ void LoadMD5CameraFile ();
+
+ // -------------------------------------------------------------------
+ /** Construct node hierarchy from a given MD5ANIM
+ * @param iParentID Current parent ID
+ * @param piParent Parent node to attach to
+ * @param bones Input bones
+ * @param node_anims Generated node animations
+ */
+ void AttachChilds_Anim(int iParentID,aiNode* piParent,
+ AnimBoneList& bones,const aiNodeAnim** node_anims);
+
+ // -------------------------------------------------------------------
+ /** Construct node hierarchy from a given MD5MESH
+ * @param iParentID Current parent ID
+ * @param piParent Parent node to attach to
+ * @param bones Input bones
+ */
+ void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones);
+
+ // -------------------------------------------------------------------
+ /** Build unique vertex buffers from a given MD5ANIM
+ * @param meshSrc Input data
+ */
+ void MakeDataUnique (MD5::MeshDesc& meshSrc);
+
+ // -------------------------------------------------------------------
+ /** Load the contents of a specific file into memory and
+ * alocates a buffer to keep it.
+ *
+ * mBuffer is modified to point to this buffer.
+ * @param pFile File stream to be read
+ */
+ void LoadFileIntoMemory (IOStream* pFile);
+ void UnloadFileFromMemory ();
+
+
+ /** IOSystem to be used to access files */
+ IOSystem* mIOHandler;
+
+ /** Path to the file, excluding the file extension but
+ with the dot */
+ std::string mFile;
+
+ /** Buffer to hold the loaded file */
+ char* mBuffer;
+
+ /** Size of the file */
+ unsigned int fileSize;
+
+ /** Current line number. For debugging purposes */
+ unsigned int iLineNumber;
+
+ /** Scene to be filled */
+ aiScene* pScene;
+
+ /** (Custom) I/O handler implementation */
+ IOSystem* pIOHandler;
+
+ /** true if a MD5MESH file has already been parsed */
+ bool bHadMD5Mesh;
+
+ /** true if a MD5ANIM file has already been parsed */
+ bool bHadMD5Anim;
+
+ /** true if a MD5CAMERA file has already been parsed */
+ bool bHadMD5Camera;
+
+ /** configuration option: prevent anim autoload */
+ bool configNoAutoLoad;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/MD5Parser.cpp b/src/3rdparty/assimp/code/MD5Parser.cpp
index db29dc9cc..df666751b 100644
--- a/src/3rdparty/assimp/code/MD5Parser.cpp
+++ b/src/3rdparty/assimp/code/MD5Parser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,24 +25,24 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file MD5Parser.cpp
+/** @file MD5Parser.cpp
* @brief Implementation of the MD5 parser class
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "MD5Loader.h"
@@ -50,6 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "fast_atof.h"
#include "ParsingUtils.h"
#include "StringComparison.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/mesh.h>
+
+
using namespace Assimp;
using namespace Assimp::MD5;
@@ -58,416 +62,416 @@ using namespace Assimp::MD5;
// Parse the segment structure fo a MD5 file
MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
{
- ai_assert(NULL != _buffer && 0 != _fileSize);
-
- buffer = _buffer;
- fileSize = _fileSize;
- lineNumber = 0;
-
- DefaultLogger::get()->debug("MD5Parser begin");
-
- // parse the file header
- ParseHeader();
-
- // and read all sections until we're finished
- bool running = true;
- while (running) {
- mSections.push_back(Section());
- Section& sec = mSections.back();
- if(!ParseSection(sec)) {
- break;
- }
- }
-
- if ( !DefaultLogger::isNullLogger()) {
- char szBuffer[128]; // should be sufficiently large
- ::sprintf(szBuffer,"MD5Parser end. Parsed %i sections",(int)mSections.size());
- DefaultLogger::get()->debug(szBuffer);
- }
+ ai_assert(NULL != _buffer && 0 != _fileSize);
+
+ buffer = _buffer;
+ fileSize = _fileSize;
+ lineNumber = 0;
+
+ DefaultLogger::get()->debug("MD5Parser begin");
+
+ // parse the file header
+ ParseHeader();
+
+ // and read all sections until we're finished
+ bool running = true;
+ while (running) {
+ mSections.push_back(Section());
+ Section& sec = mSections.back();
+ if(!ParseSection(sec)) {
+ break;
+ }
+ }
+
+ if ( !DefaultLogger::isNullLogger()) {
+ char szBuffer[128]; // should be sufficiently large
+ ::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size());
+ DefaultLogger::get()->debug(szBuffer);
+ }
}
// ------------------------------------------------------------------------------------------------
// Report error to the log stream
-/*static*/ void MD5Parser::ReportError (const char* error, unsigned int line)
+/*static*/ AI_WONT_RETURN void MD5Parser::ReportError (const char* error, unsigned int line)
{
- char szBuffer[1024];
- ::sprintf(szBuffer,"[MD5] Line %i: %s",line,error);
- throw DeadlyImportError(szBuffer);
+ char szBuffer[1024];
+ ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s",line,error);
+ throw DeadlyImportError(szBuffer);
}
// ------------------------------------------------------------------------------------------------
// Report warning to the log stream
/*static*/ void MD5Parser::ReportWarning (const char* warn, unsigned int line)
{
- char szBuffer[1024];
- ::sprintf(szBuffer,"[MD5] Line %i: %s",line,warn);
- DefaultLogger::get()->warn(szBuffer);
+ char szBuffer[1024];
+ ::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn);
+ DefaultLogger::get()->warn(szBuffer);
}
// ------------------------------------------------------------------------------------------------
// Parse and validate the MD5 header
void MD5Parser::ParseHeader()
{
- // parse and validate the file version
- SkipSpaces();
- if (!TokenMatch(buffer,"MD5Version",10)) {
- ReportError("Invalid MD5 file: MD5Version tag has not been found");
- }
- SkipSpaces();
- unsigned int iVer = ::strtoul10(buffer,(const char**)&buffer);
- if (10 != iVer) {
- ReportError("MD5 version tag is unknown (10 is expected)");
- }
- SkipLine();
-
- // print the command line options to the console
- // FIX: can break the log length limit, so we need to be careful
- char* sz = buffer;
- while (!IsLineEnd( *buffer++));
- DefaultLogger::get()->info(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz))));
- SkipSpacesAndLineEnd();
+ // parse and validate the file version
+ SkipSpaces();
+ if (!TokenMatch(buffer,"MD5Version",10)) {
+ ReportError("Invalid MD5 file: MD5Version tag has not been found");
+ }
+ SkipSpaces();
+ unsigned int iVer = ::strtoul10(buffer,(const char**)&buffer);
+ if (10 != iVer) {
+ ReportError("MD5 version tag is unknown (10 is expected)");
+ }
+ SkipLine();
+
+ // print the command line options to the console
+ // FIX: can break the log length limit, so we need to be careful
+ char* sz = buffer;
+ while (!IsLineEnd( *buffer++));
+ DefaultLogger::get()->info(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz))));
+ SkipSpacesAndLineEnd();
}
// ------------------------------------------------------------------------------------------------
// Recursive MD5 parsing function
bool MD5Parser::ParseSection(Section& out)
{
- // store the current line number for use in error messages
- out.iLineNumber = lineNumber;
-
- // first parse the name of the section
- char* sz = buffer;
- while (!IsSpaceOrNewLine( *buffer))buffer++;
- out.mName = std::string(sz,(uintptr_t)(buffer-sz));
- SkipSpaces();
-
- bool running = true;
- while (running) {
- if ('{' == *buffer) {
- // it is a normal section so read all lines
- buffer++;
- bool run = true;
- while (run)
- {
- if (!SkipSpacesAndLineEnd()) {
- return false; // seems this was the last section
- }
- if ('}' == *buffer) {
- buffer++;
- break;
- }
-
- out.mElements.push_back(Element());
- Element& elem = out.mElements.back();
-
- elem.iLineNumber = lineNumber;
- elem.szStart = buffer;
-
- // terminate the line with zero
- while (!IsLineEnd( *buffer))buffer++;
- if (*buffer) {
- ++lineNumber;
- *buffer++ = '\0';
- }
- }
- break;
- }
- else if (!IsSpaceOrNewLine(*buffer)) {
- // it is an element at global scope. Parse its value and go on
- sz = buffer;
- while (!IsSpaceOrNewLine( *buffer++));
- out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz));
- continue;
- }
- break;
- }
- return SkipSpacesAndLineEnd();
+ // store the current line number for use in error messages
+ out.iLineNumber = lineNumber;
+
+ // first parse the name of the section
+ char* sz = buffer;
+ while (!IsSpaceOrNewLine( *buffer))buffer++;
+ out.mName = std::string(sz,(uintptr_t)(buffer-sz));
+ SkipSpaces();
+
+ bool running = true;
+ while (running) {
+ if ('{' == *buffer) {
+ // it is a normal section so read all lines
+ buffer++;
+ bool run = true;
+ while (run)
+ {
+ if (!SkipSpacesAndLineEnd()) {
+ return false; // seems this was the last section
+ }
+ if ('}' == *buffer) {
+ buffer++;
+ break;
+ }
+
+ out.mElements.push_back(Element());
+ Element& elem = out.mElements.back();
+
+ elem.iLineNumber = lineNumber;
+ elem.szStart = buffer;
+
+ // terminate the line with zero
+ while (!IsLineEnd( *buffer))buffer++;
+ if (*buffer) {
+ ++lineNumber;
+ *buffer++ = '\0';
+ }
+ }
+ break;
+ }
+ else if (!IsSpaceOrNewLine(*buffer)) {
+ // it is an element at global scope. Parse its value and go on
+ sz = buffer;
+ while (!IsSpaceOrNewLine( *buffer++));
+ out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz));
+ continue;
+ }
+ break;
+ }
+ return SkipSpacesAndLineEnd();
}
// ------------------------------------------------------------------------------------------------
// Some dirty macros just because they're so funny and easy to debug
// skip all spaces ... handle EOL correctly
-#define AI_MD5_SKIP_SPACES() if(!SkipSpaces(&sz)) \
- MD5Parser::ReportWarning("Unexpected end of line",(*eit).iLineNumber);
+#define AI_MD5_SKIP_SPACES() if(!SkipSpaces(&sz)) \
+ MD5Parser::ReportWarning("Unexpected end of line",elem.iLineNumber);
- // read a triple float in brackets: (1.0 1.0 1.0)
+ // read a triple float in brackets: (1.0 1.0 1.0)
#define AI_MD5_READ_TRIPLE(vec) \
- AI_MD5_SKIP_SPACES(); \
- if ('(' != *sz++) \
- MD5Parser::ReportWarning("Unexpected token: ( was expected",(*eit).iLineNumber); \
- AI_MD5_SKIP_SPACES(); \
- sz = fast_atoreal_move<float>(sz,(float&)vec.x); \
- AI_MD5_SKIP_SPACES(); \
- sz = fast_atoreal_move<float>(sz,(float&)vec.y); \
- AI_MD5_SKIP_SPACES(); \
- sz = fast_atoreal_move<float>(sz,(float&)vec.z); \
- AI_MD5_SKIP_SPACES(); \
- if (')' != *sz++) \
- MD5Parser::ReportWarning("Unexpected token: ) was expected",(*eit).iLineNumber);
-
- // parse a string, enclosed in quotation marks or not
+ AI_MD5_SKIP_SPACES(); \
+ if ('(' != *sz++) \
+ MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); \
+ AI_MD5_SKIP_SPACES(); \
+ sz = fast_atoreal_move<float>(sz,(float&)vec.x); \
+ AI_MD5_SKIP_SPACES(); \
+ sz = fast_atoreal_move<float>(sz,(float&)vec.y); \
+ AI_MD5_SKIP_SPACES(); \
+ sz = fast_atoreal_move<float>(sz,(float&)vec.z); \
+ AI_MD5_SKIP_SPACES(); \
+ if (')' != *sz++) \
+ MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber);
+
+ // parse a string, enclosed in quotation marks or not
#define AI_MD5_PARSE_STRING(out) \
- bool bQuota = (*sz == '\"'); \
- const char* szStart = sz; \
- while (!IsSpaceOrNewLine(*sz))++sz; \
- const char* szEnd = sz; \
- if (bQuota) { \
- szStart++; \
- if ('\"' != *(szEnd-=1)) { \
- MD5Parser::ReportWarning("Expected closing quotation marks in string", \
- (*eit).iLineNumber); \
- continue; \
- } \
- } \
- out.length = (size_t)(szEnd - szStart); \
- ::memcpy(out.data,szStart,out.length); \
- out.data[out.length] = '\0';
+ bool bQuota = (*sz == '\"'); \
+ const char* szStart = sz; \
+ while (!IsSpaceOrNewLine(*sz))++sz; \
+ const char* szEnd = sz; \
+ if (bQuota) { \
+ szStart++; \
+ if ('\"' != *(szEnd-=1)) { \
+ MD5Parser::ReportWarning("Expected closing quotation marks in string", \
+ elem.iLineNumber); \
+ continue; \
+ } \
+ } \
+ out.length = (size_t)(szEnd - szStart); \
+ ::memcpy(out.data,szStart,out.length); \
+ out.data[out.length] = '\0';
// ------------------------------------------------------------------------------------------------
// .MD5MESH parsing function
MD5MeshParser::MD5MeshParser(SectionList& mSections)
{
- DefaultLogger::get()->debug("MD5MeshParser begin");
-
- // now parse all sections
- for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){
- if ( (*iter).mName == "numMeshes") {
- mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if ( (*iter).mName == "numJoints") {
- mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if ((*iter).mName == "joints") {
- // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit){
- mJoints.push_back(BoneDesc());
- BoneDesc& desc = mJoints.back();
-
- const char* sz = (*eit).szStart;
- AI_MD5_PARSE_STRING(desc.mName);
- AI_MD5_SKIP_SPACES();
-
- // negative values, at least -1, is allowed here
- desc.mParentIndex = (int)strtol10(sz,&sz);
-
- AI_MD5_READ_TRIPLE(desc.mPositionXYZ);
- AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
- }
- }
- else if ((*iter).mName == "mesh") {
- mMeshes.push_back(MeshDesc());
- MeshDesc& desc = mMeshes.back();
-
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit){
- const char* sz = (*eit).szStart;
-
- // shader attribute
- if (TokenMatch(sz,"shader",6)) {
- AI_MD5_SKIP_SPACES();
- AI_MD5_PARSE_STRING(desc.mShader);
- }
- // numverts attribute
- else if (TokenMatch(sz,"numverts",8)) {
- AI_MD5_SKIP_SPACES();
- desc.mVertices.resize(strtoul10(sz));
- }
- // numtris attribute
- else if (TokenMatch(sz,"numtris",7)) {
- AI_MD5_SKIP_SPACES();
- desc.mFaces.resize(strtoul10(sz));
- }
- // numweights attribute
- else if (TokenMatch(sz,"numweights",10)) {
- AI_MD5_SKIP_SPACES();
- desc.mWeights.resize(strtoul10(sz));
- }
- // vert attribute
- // "vert 0 ( 0.394531 0.513672 ) 0 1"
- else if (TokenMatch(sz,"vert",4)) {
- AI_MD5_SKIP_SPACES();
- const unsigned int idx = ::strtoul10(sz,&sz);
- AI_MD5_SKIP_SPACES();
- if (idx >= desc.mVertices.size())
- desc.mVertices.resize(idx+1);
-
- VertexDesc& vert = desc.mVertices[idx];
- if ('(' != *sz++)
- MD5Parser::ReportWarning("Unexpected token: ( was expected",(*eit).iLineNumber);
- AI_MD5_SKIP_SPACES();
- sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.x);
- AI_MD5_SKIP_SPACES();
- sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.y);
- AI_MD5_SKIP_SPACES();
- if (')' != *sz++)
- MD5Parser::ReportWarning("Unexpected token: ) was expected",(*eit).iLineNumber);
- AI_MD5_SKIP_SPACES();
- vert.mFirstWeight = ::strtoul10(sz,&sz);
- AI_MD5_SKIP_SPACES();
- vert.mNumWeights = ::strtoul10(sz,&sz);
- }
- // tri attribute
- // "tri 0 15 13 12"
- else if (TokenMatch(sz,"tri",3)) {
- AI_MD5_SKIP_SPACES();
- const unsigned int idx = strtoul10(sz,&sz);
- if (idx >= desc.mFaces.size())
- desc.mFaces.resize(idx+1);
-
- aiFace& face = desc.mFaces[idx];
- face.mIndices = new unsigned int[face.mNumIndices = 3];
- for (unsigned int i = 0; i < 3;++i) {
- AI_MD5_SKIP_SPACES();
- face.mIndices[i] = strtoul10(sz,&sz);
- }
- }
- // weight attribute
- // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )"
- else if (TokenMatch(sz,"weight",6)) {
- AI_MD5_SKIP_SPACES();
- const unsigned int idx = strtoul10(sz,&sz);
- AI_MD5_SKIP_SPACES();
- if (idx >= desc.mWeights.size())
- desc.mWeights.resize(idx+1);
-
- WeightDesc& weight = desc.mWeights[idx];
- weight.mBone = strtoul10(sz,&sz);
- AI_MD5_SKIP_SPACES();
- sz = fast_atoreal_move<float>(sz,weight.mWeight);
- AI_MD5_READ_TRIPLE(weight.vOffsetPosition);
- }
- }
- }
- }
- DefaultLogger::get()->debug("MD5MeshParser end");
+ DefaultLogger::get()->debug("MD5MeshParser begin");
+
+ // now parse all sections
+ for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){
+ if ( (*iter).mName == "numMeshes") {
+ mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if ( (*iter).mName == "numJoints") {
+ mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if ((*iter).mName == "joints") {
+ // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
+ for (const auto & elem : (*iter).mElements){
+ mJoints.push_back(BoneDesc());
+ BoneDesc& desc = mJoints.back();
+
+ const char* sz = elem.szStart;
+ AI_MD5_PARSE_STRING(desc.mName);
+ AI_MD5_SKIP_SPACES();
+
+ // negative values, at least -1, is allowed here
+ desc.mParentIndex = (int)strtol10(sz,&sz);
+
+ AI_MD5_READ_TRIPLE(desc.mPositionXYZ);
+ AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
+ }
+ }
+ else if ((*iter).mName == "mesh") {
+ mMeshes.push_back(MeshDesc());
+ MeshDesc& desc = mMeshes.back();
+
+ for (const auto & elem : (*iter).mElements){
+ const char* sz = elem.szStart;
+
+ // shader attribute
+ if (TokenMatch(sz,"shader",6)) {
+ AI_MD5_SKIP_SPACES();
+ AI_MD5_PARSE_STRING(desc.mShader);
+ }
+ // numverts attribute
+ else if (TokenMatch(sz,"numverts",8)) {
+ AI_MD5_SKIP_SPACES();
+ desc.mVertices.resize(strtoul10(sz));
+ }
+ // numtris attribute
+ else if (TokenMatch(sz,"numtris",7)) {
+ AI_MD5_SKIP_SPACES();
+ desc.mFaces.resize(strtoul10(sz));
+ }
+ // numweights attribute
+ else if (TokenMatch(sz,"numweights",10)) {
+ AI_MD5_SKIP_SPACES();
+ desc.mWeights.resize(strtoul10(sz));
+ }
+ // vert attribute
+ // "vert 0 ( 0.394531 0.513672 ) 0 1"
+ else if (TokenMatch(sz,"vert",4)) {
+ AI_MD5_SKIP_SPACES();
+ const unsigned int idx = ::strtoul10(sz,&sz);
+ AI_MD5_SKIP_SPACES();
+ if (idx >= desc.mVertices.size())
+ desc.mVertices.resize(idx+1);
+
+ VertexDesc& vert = desc.mVertices[idx];
+ if ('(' != *sz++)
+ MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber);
+ AI_MD5_SKIP_SPACES();
+ sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.x);
+ AI_MD5_SKIP_SPACES();
+ sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.y);
+ AI_MD5_SKIP_SPACES();
+ if (')' != *sz++)
+ MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber);
+ AI_MD5_SKIP_SPACES();
+ vert.mFirstWeight = ::strtoul10(sz,&sz);
+ AI_MD5_SKIP_SPACES();
+ vert.mNumWeights = ::strtoul10(sz,&sz);
+ }
+ // tri attribute
+ // "tri 0 15 13 12"
+ else if (TokenMatch(sz,"tri",3)) {
+ AI_MD5_SKIP_SPACES();
+ const unsigned int idx = strtoul10(sz,&sz);
+ if (idx >= desc.mFaces.size())
+ desc.mFaces.resize(idx+1);
+
+ aiFace& face = desc.mFaces[idx];
+ face.mIndices = new unsigned int[face.mNumIndices = 3];
+ for (unsigned int i = 0; i < 3;++i) {
+ AI_MD5_SKIP_SPACES();
+ face.mIndices[i] = strtoul10(sz,&sz);
+ }
+ }
+ // weight attribute
+ // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )"
+ else if (TokenMatch(sz,"weight",6)) {
+ AI_MD5_SKIP_SPACES();
+ const unsigned int idx = strtoul10(sz,&sz);
+ AI_MD5_SKIP_SPACES();
+ if (idx >= desc.mWeights.size())
+ desc.mWeights.resize(idx+1);
+
+ WeightDesc& weight = desc.mWeights[idx];
+ weight.mBone = strtoul10(sz,&sz);
+ AI_MD5_SKIP_SPACES();
+ sz = fast_atoreal_move<float>(sz,weight.mWeight);
+ AI_MD5_READ_TRIPLE(weight.vOffsetPosition);
+ }
+ }
+ }
+ }
+ DefaultLogger::get()->debug("MD5MeshParser end");
}
// ------------------------------------------------------------------------------------------------
// .MD5ANIM parsing function
MD5AnimParser::MD5AnimParser(SectionList& mSections)
{
- DefaultLogger::get()->debug("MD5AnimParser begin");
-
- fFrameRate = 24.0f;
- mNumAnimatedComponents = UINT_MAX;
- for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
- if ((*iter).mName == "hierarchy") {
- // "sheath" 0 63 6
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit) {
- mAnimatedBones.push_back ( AnimBoneDesc () );
- AnimBoneDesc& desc = mAnimatedBones.back();
-
- const char* sz = (*eit).szStart;
- AI_MD5_PARSE_STRING(desc.mName);
- AI_MD5_SKIP_SPACES();
-
- // parent index - negative values are allowed (at least -1)
- desc.mParentIndex = ::strtol10(sz,&sz);
-
- // flags (highest is 2^6-1)
- AI_MD5_SKIP_SPACES();
- if(63 < (desc.iFlags = ::strtoul10(sz,&sz))){
- MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",(*eit).iLineNumber);
- }
- AI_MD5_SKIP_SPACES();
-
- // index of the first animation keyframe component for this joint
- desc.iFirstKeyIndex = ::strtoul10(sz,&sz);
- }
- }
- else if((*iter).mName == "baseframe") {
- // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 )
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit) {
- const char* sz = (*eit).szStart;
-
- mBaseFrames.push_back ( BaseFrameDesc () );
- BaseFrameDesc& desc = mBaseFrames.back();
-
- AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
- AI_MD5_READ_TRIPLE(desc.vRotationQuat);
- }
- }
- else if((*iter).mName == "frame") {
- if (!(*iter).mGlobalValue.length()) {
- MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber);
- continue;
- }
-
- mFrames.push_back ( FrameDesc () );
- FrameDesc& desc = mFrames.back();
- desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
-
- // we do already know how much storage we will presumably need
- if (UINT_MAX != mNumAnimatedComponents) {
- desc.mValues.reserve(mNumAnimatedComponents);
- }
-
- // now read all elements (continous list of floats)
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){
- const char* sz = (*eit).szStart;
- while (SkipSpacesAndLineEnd(&sz)) {
- float f;sz = fast_atoreal_move<float>(sz,f);
- desc.mValues.push_back(f);
- }
- }
- }
- else if((*iter).mName == "numFrames") {
- mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if((*iter).mName == "numJoints") {
- const unsigned int num = strtoul10((*iter).mGlobalValue.c_str());
- mAnimatedBones.reserve(num);
-
- // try to guess the number of animated components if that element is not given
- if (UINT_MAX == mNumAnimatedComponents) {
- mNumAnimatedComponents = num * 6;
- }
- }
- else if((*iter).mName == "numAnimatedComponents") {
- mAnimatedBones.reserve( strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if((*iter).mName == "frameRate") {
- fast_atoreal_move<float>((*iter).mGlobalValue.c_str(),fFrameRate);
- }
- }
- DefaultLogger::get()->debug("MD5AnimParser end");
+ DefaultLogger::get()->debug("MD5AnimParser begin");
+
+ fFrameRate = 24.0f;
+ mNumAnimatedComponents = UINT_MAX;
+ for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
+ if ((*iter).mName == "hierarchy") {
+ // "sheath" 0 63 6
+ for (const auto & elem : (*iter).mElements) {
+ mAnimatedBones.push_back ( AnimBoneDesc () );
+ AnimBoneDesc& desc = mAnimatedBones.back();
+
+ const char* sz = elem.szStart;
+ AI_MD5_PARSE_STRING(desc.mName);
+ AI_MD5_SKIP_SPACES();
+
+ // parent index - negative values are allowed (at least -1)
+ desc.mParentIndex = ::strtol10(sz,&sz);
+
+ // flags (highest is 2^6-1)
+ AI_MD5_SKIP_SPACES();
+ if(63 < (desc.iFlags = ::strtoul10(sz,&sz))){
+ MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",elem.iLineNumber);
+ }
+ AI_MD5_SKIP_SPACES();
+
+ // index of the first animation keyframe component for this joint
+ desc.iFirstKeyIndex = ::strtoul10(sz,&sz);
+ }
+ }
+ else if((*iter).mName == "baseframe") {
+ // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 )
+ for (const auto & elem : (*iter).mElements) {
+ const char* sz = elem.szStart;
+
+ mBaseFrames.push_back ( BaseFrameDesc () );
+ BaseFrameDesc& desc = mBaseFrames.back();
+
+ AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
+ AI_MD5_READ_TRIPLE(desc.vRotationQuat);
+ }
+ }
+ else if((*iter).mName == "frame") {
+ if (!(*iter).mGlobalValue.length()) {
+ MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber);
+ continue;
+ }
+
+ mFrames.push_back ( FrameDesc () );
+ FrameDesc& desc = mFrames.back();
+ desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
+
+ // we do already know how much storage we will presumably need
+ if (UINT_MAX != mNumAnimatedComponents) {
+ desc.mValues.reserve(mNumAnimatedComponents);
+ }
+
+ // now read all elements (continuous list of floats)
+ for (const auto & elem : (*iter).mElements){
+ const char* sz = elem.szStart;
+ while (SkipSpacesAndLineEnd(&sz)) {
+ float f;sz = fast_atoreal_move<float>(sz,f);
+ desc.mValues.push_back(f);
+ }
+ }
+ }
+ else if((*iter).mName == "numFrames") {
+ mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if((*iter).mName == "numJoints") {
+ const unsigned int num = strtoul10((*iter).mGlobalValue.c_str());
+ mAnimatedBones.reserve(num);
+
+ // try to guess the number of animated components if that element is not given
+ if (UINT_MAX == mNumAnimatedComponents) {
+ mNumAnimatedComponents = num * 6;
+ }
+ }
+ else if((*iter).mName == "numAnimatedComponents") {
+ mAnimatedBones.reserve( strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if((*iter).mName == "frameRate") {
+ fast_atoreal_move<float>((*iter).mGlobalValue.c_str(),fFrameRate);
+ }
+ }
+ DefaultLogger::get()->debug("MD5AnimParser end");
}
// ------------------------------------------------------------------------------------------------
// .MD5CAMERA parsing function
MD5CameraParser::MD5CameraParser(SectionList& mSections)
{
- DefaultLogger::get()->debug("MD5CameraParser begin");
- fFrameRate = 24.0f;
-
- for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
- if ((*iter).mName == "numFrames") {
- frames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if ((*iter).mName == "frameRate") {
- fFrameRate = fast_atof ((*iter).mGlobalValue.c_str());
- }
- else if ((*iter).mName == "numCuts") {
- cuts.reserve(strtoul10((*iter).mGlobalValue.c_str()));
- }
- else if ((*iter).mName == "cuts") {
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){
- cuts.push_back(strtoul10((*eit).szStart)+1);
- }
- }
- else if ((*iter).mName == "camera") {
- for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){
- const char* sz = (*eit).szStart;
-
- frames.push_back(CameraAnimFrameDesc());
- CameraAnimFrameDesc& cur = frames.back();
- AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
- AI_MD5_READ_TRIPLE(cur.vRotationQuat);
- AI_MD5_SKIP_SPACES();
- cur.fFOV = fast_atof(sz);
- }
- }
- }
- DefaultLogger::get()->debug("MD5CameraParser end");
+ DefaultLogger::get()->debug("MD5CameraParser begin");
+ fFrameRate = 24.0f;
+
+ for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
+ if ((*iter).mName == "numFrames") {
+ frames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if ((*iter).mName == "frameRate") {
+ fFrameRate = fast_atof ((*iter).mGlobalValue.c_str());
+ }
+ else if ((*iter).mName == "numCuts") {
+ cuts.reserve(strtoul10((*iter).mGlobalValue.c_str()));
+ }
+ else if ((*iter).mName == "cuts") {
+ for (const auto & elem : (*iter).mElements){
+ cuts.push_back(strtoul10(elem.szStart)+1);
+ }
+ }
+ else if ((*iter).mName == "camera") {
+ for (const auto & elem : (*iter).mElements){
+ const char* sz = elem.szStart;
+
+ frames.push_back(CameraAnimFrameDesc());
+ CameraAnimFrameDesc& cur = frames.back();
+ AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
+ AI_MD5_READ_TRIPLE(cur.vRotationQuat);
+ AI_MD5_SKIP_SPACES();
+ cur.fFOV = fast_atof(sz);
+ }
+ }
+ }
+ DefaultLogger::get()->debug("MD5CameraParser end");
}
diff --git a/src/3rdparty/assimp/code/MD5Parser.h b/src/3rdparty/assimp/code/MD5Parser.h
index 4fd147d3a..78ade8430 100644
--- a/src/3rdparty/assimp/code/MD5Parser.h
+++ b/src/3rdparty/assimp/code/MD5Parser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,53 +46,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MD5PARSER_H_INCLUDED
#define AI_MD5PARSER_H_INCLUDED
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include "ParsingUtils.h"
+#include <vector>
+#include <stdint.h>
struct aiFace;
-namespace Assimp {
-namespace MD5 {
+namespace Assimp {
+namespace MD5 {
// ---------------------------------------------------------------------------
/** Represents a single element in a MD5 file
- *
+ *
* Elements are always contained in sections.
*/
struct Element
{
- //! Points to the starting point of the element
- //! Whitespace at the beginning and at the end have been removed,
- //! Elements are terminated with \0
- char* szStart;
-
- //! Original line number (can be used in error messages
- //! if a parsing error occurs)
- unsigned int iLineNumber;
+ //! Points to the starting point of the element
+ //! Whitespace at the beginning and at the end have been removed,
+ //! Elements are terminated with \0
+ char* szStart;
+
+ //! Original line number (can be used in error messages
+ //! if a parsing error occurs)
+ unsigned int iLineNumber;
};
typedef std::vector< Element > ElementList;
// ---------------------------------------------------------------------------
/** Represents a section of a MD5 file (such as the mesh or the joints section)
- *
+ *
* A section is always enclosed in { and } brackets.
*/
struct Section
{
- //! Original line number (can be used in error messages
- //! if a parsing error occurs)
- unsigned int iLineNumber;
+ //! Original line number (can be used in error messages
+ //! if a parsing error occurs)
+ unsigned int iLineNumber;
- //! List of all elements which have been parsed in this section.
- ElementList mElements;
+ //! List of all elements which have been parsed in this section.
+ ElementList mElements;
- //! Name of the section
- std::string mName;
+ //! Name of the section
+ std::string mName;
- //! For global elements: the value of the element as string
- //! Iif !length() the section is not a global element
- std::string mGlobalValue;
+ //! For global elements: the value of the element as string
+ //! Iif !length() the section is not a global element
+ std::string mGlobalValue;
};
typedef std::vector< Section> SectionList;
@@ -102,11 +104,11 @@ typedef std::vector< Section> SectionList;
*/
struct BaseJointDescription
{
- //! Name of the bone
- aiString mName;
+ //! Name of the bone
+ aiString mName;
- //! Parent index of the bone
- int mParentIndex;
+ //! Parent index of the bone
+ int mParentIndex;
};
// ---------------------------------------------------------------------------
@@ -114,23 +116,23 @@ struct BaseJointDescription
*/
struct BoneDesc : BaseJointDescription
{
- //! Absolute position of the bone
- aiVector3D mPositionXYZ;
+ //! Absolute position of the bone
+ aiVector3D mPositionXYZ;
- //! Absolute rotation of the bone
- aiVector3D mRotationQuat;
- aiQuaternion mRotationQuatConverted;
+ //! Absolute rotation of the bone
+ aiVector3D mRotationQuat;
+ aiQuaternion mRotationQuatConverted;
- //! Absolute transformation of the bone
- //! (temporary)
- aiMatrix4x4 mTransform;
+ //! Absolute transformation of the bone
+ //! (temporary)
+ aiMatrix4x4 mTransform;
- //! Inverse transformation of the bone
- //! (temporary)
- aiMatrix4x4 mInvTransform;
+ //! Inverse transformation of the bone
+ //! (temporary)
+ aiMatrix4x4 mInvTransform;
- //! Internal
- unsigned int mMap;
+ //! Internal
+ unsigned int mMap;
};
typedef std::vector< BoneDesc > BoneList;
@@ -140,11 +142,11 @@ typedef std::vector< BoneDesc > BoneList;
*/
struct AnimBoneDesc : BaseJointDescription
{
- //! Flags (AI_MD5_ANIMATION_FLAG_xxx)
- unsigned int iFlags;
+ //! Flags (AI_MD5_ANIMATION_FLAG_xxx)
+ unsigned int iFlags;
- //! Index of the first key that corresponds to this anim bone
- unsigned int iFirstKeyIndex;
+ //! Index of the first key that corresponds to this anim bone
+ unsigned int iFirstKeyIndex;
};
typedef std::vector< AnimBoneDesc > AnimBoneList;
@@ -155,8 +157,8 @@ typedef std::vector< AnimBoneDesc > AnimBoneList;
*/
struct BaseFrameDesc
{
- aiVector3D vPositionXYZ;
- aiVector3D vRotationQuat;
+ aiVector3D vPositionXYZ;
+ aiVector3D vRotationQuat;
};
typedef std::vector< BaseFrameDesc > BaseFrameList;
@@ -166,7 +168,7 @@ typedef std::vector< BaseFrameDesc > BaseFrameList;
*/
struct CameraAnimFrameDesc : BaseFrameDesc
{
- float fFOV;
+ float fFOV;
};
typedef std::vector< CameraAnimFrameDesc > CameraFrameList;
@@ -176,11 +178,11 @@ typedef std::vector< CameraAnimFrameDesc > CameraFrameList;
*/
struct FrameDesc
{
- //! Index of the frame
- unsigned int iIndex;
+ //! Index of the frame
+ unsigned int iIndex;
- //! Animation keyframes - a large blob of data at first
- std::vector< float > mValues;
+ //! Animation keyframes - a large blob of data at first
+ std::vector< float > mValues;
};
typedef std::vector< FrameDesc > FrameList;
@@ -190,20 +192,20 @@ typedef std::vector< FrameDesc > FrameList;
*/
struct VertexDesc
{
- VertexDesc()
- : mFirstWeight (0)
- , mNumWeights (0)
- {}
+ VertexDesc()
+ : mFirstWeight (0)
+ , mNumWeights (0)
+ {}
- //! UV cordinate of the vertex
- aiVector2D mUV;
+ //! UV cordinate of the vertex
+ aiVector2D mUV;
- //! Index of the first weight of the vertex in
- //! the vertex weight list
- unsigned int mFirstWeight;
+ //! Index of the first weight of the vertex in
+ //! the vertex weight list
+ unsigned int mFirstWeight;
- //! Number of weights assigned to this vertex
- unsigned int mNumWeights;
+ //! Number of weights assigned to this vertex
+ unsigned int mNumWeights;
};
typedef std::vector< VertexDesc > VertexList;
@@ -213,15 +215,15 @@ typedef std::vector< VertexDesc > VertexList;
*/
struct WeightDesc
{
- //! Index of the bone to which this weight refers
- unsigned int mBone;
+ //! Index of the bone to which this weight refers
+ unsigned int mBone;
- //! The weight value
- float mWeight;
+ //! The weight value
+ float mWeight;
- //! The offset position of this weight
- // ! (in the coordinate system defined by the parent bone)
- aiVector3D vOffsetPosition;
+ //! The offset position of this weight
+ // ! (in the coordinate system defined by the parent bone)
+ aiVector3D vOffsetPosition;
};
typedef std::vector< WeightDesc > WeightList;
@@ -232,17 +234,17 @@ typedef std::vector< aiFace > FaceList;
*/
struct MeshDesc
{
- //! Weights of the mesh
- WeightList mWeights;
+ //! Weights of the mesh
+ WeightList mWeights;
- //! Vertices of the mesh
- VertexList mVertices;
+ //! Vertices of the mesh
+ VertexList mVertices;
- //! Faces of the mesh
- FaceList mFaces;
+ //! Faces of the mesh
+ FaceList mFaces;
- //! Name of the shader (=texture) to be assigned to the mesh
- aiString mShader;
+ //! Name of the shader (=texture) to be assigned to the mesh
+ aiString mShader;
};
typedef std::vector< MeshDesc > MeshList;
@@ -251,15 +253,18 @@ typedef std::vector< MeshDesc > MeshList;
// Convert a quaternion to its usual representation
inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
- out.x = in.x;
- out.y = in.y;
- out.z = in.z;
+ out.x = in.x;
+ out.y = in.y;
+ out.z = in.z;
- const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z);
+ const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z);
- if (t < 0.0f)
- out.w = 0.0f;
- else out.w = std::sqrt (t);
+ if (t < 0.0f)
+ out.w = 0.0f;
+ else out.w = std::sqrt (t);
+
+ // Assimp convention.
+ out.w *= -1.f;
}
// ---------------------------------------------------------------------------
@@ -269,19 +274,19 @@ class MD5MeshParser
{
public:
- // -------------------------------------------------------------------
- /** Constructs a new MD5MeshParser instance from an existing
- * preparsed list of file sections.
- *
- * @param mSections List of file sections (output of MD5Parser)
- */
- MD5MeshParser(SectionList& mSections);
+ // -------------------------------------------------------------------
+ /** Constructs a new MD5MeshParser instance from an existing
+ * preparsed list of file sections.
+ *
+ * @param mSections List of file sections (output of MD5Parser)
+ */
+ explicit MD5MeshParser(SectionList& mSections);
- //! List of all meshes
- MeshList mMeshes;
+ //! List of all meshes
+ MeshList mMeshes;
- //! List of all joints
- BoneList mJoints;
+ //! List of all joints
+ BoneList mJoints;
};
// remove this flag if you need to the bounding box data
@@ -294,29 +299,29 @@ class MD5AnimParser
{
public:
- // -------------------------------------------------------------------
- /** Constructs a new MD5AnimParser instance from an existing
- * preparsed list of file sections.
- *
- * @param mSections List of file sections (output of MD5Parser)
- */
- MD5AnimParser(SectionList& mSections);
+ // -------------------------------------------------------------------
+ /** Constructs a new MD5AnimParser instance from an existing
+ * preparsed list of file sections.
+ *
+ * @param mSections List of file sections (output of MD5Parser)
+ */
+ explicit MD5AnimParser(SectionList& mSections);
+
-
- //! Output frame rate
- float fFrameRate;
+ //! Output frame rate
+ float fFrameRate;
- //! List of animation bones
- AnimBoneList mAnimatedBones;
+ //! List of animation bones
+ AnimBoneList mAnimatedBones;
- //! List of base frames
- BaseFrameList mBaseFrames;
+ //! List of base frames
+ BaseFrameList mBaseFrames;
- //! List of animation frames
- FrameList mFrames;
+ //! List of animation frames
+ FrameList mFrames;
- //! Number of animated components
- unsigned int mNumAnimatedComponents;
+ //! Number of animated components
+ unsigned int mNumAnimatedComponents;
};
// ---------------------------------------------------------------------------
@@ -326,23 +331,23 @@ class MD5CameraParser
{
public:
- // -------------------------------------------------------------------
- /** Constructs a new MD5CameraParser instance from an existing
- * preparsed list of file sections.
- *
- * @param mSections List of file sections (output of MD5Parser)
- */
- MD5CameraParser(SectionList& mSections);
+ // -------------------------------------------------------------------
+ /** Constructs a new MD5CameraParser instance from an existing
+ * preparsed list of file sections.
+ *
+ * @param mSections List of file sections (output of MD5Parser)
+ */
+ explicit MD5CameraParser(SectionList& mSections);
+
-
- //! Output frame rate
- float fFrameRate;
+ //! Output frame rate
+ float fFrameRate;
- //! List of cuts
- std::vector<unsigned int> cuts;
+ //! List of cuts
+ std::vector<unsigned int> cuts;
- //! Frames
- CameraFrameList frames;
+ //! Frames
+ CameraFrameList frames;
};
// ---------------------------------------------------------------------------
@@ -353,107 +358,107 @@ class MD5Parser
{
public:
- // -------------------------------------------------------------------
- /** Constructs a new MD5Parser instance from an existing buffer.
- *
- * @param buffer File buffer
- * @param fileSize Length of the file in bytes (excluding a terminal 0)
- */
- MD5Parser(char* buffer, unsigned int fileSize);
-
-
- // -------------------------------------------------------------------
- /** Report a specific error message and throw an exception
- * @param error Error message to be reported
- * @param line Index of the line where the error occured
- */
- static void ReportError (const char* error, unsigned int line);
-
- // -------------------------------------------------------------------
- /** Report a specific warning
- * @param warn Warn message to be reported
- * @param line Index of the line where the error occured
- */
- static void ReportWarning (const char* warn, unsigned int line);
-
-
- void ReportError (const char* error) {
- return ReportError(error, lineNumber);
- }
-
- void ReportWarning (const char* warn) {
- return ReportWarning(warn, lineNumber);
- }
+ // -------------------------------------------------------------------
+ /** Constructs a new MD5Parser instance from an existing buffer.
+ *
+ * @param buffer File buffer
+ * @param fileSize Length of the file in bytes (excluding a terminal 0)
+ */
+ MD5Parser(char* buffer, unsigned int fileSize);
+
+
+ // -------------------------------------------------------------------
+ /** Report a specific error message and throw an exception
+ * @param error Error message to be reported
+ * @param line Index of the line where the error occurred
+ */
+ AI_WONT_RETURN static void ReportError (const char* error, unsigned int line) AI_WONT_RETURN_SUFFIX;
+
+ // -------------------------------------------------------------------
+ /** Report a specific warning
+ * @param warn Warn message to be reported
+ * @param line Index of the line where the error occurred
+ */
+ static void ReportWarning (const char* warn, unsigned int line);
+
+
+ void ReportError (const char* error) {
+ return ReportError(error, lineNumber);
+ }
+
+ void ReportWarning (const char* warn) {
+ return ReportWarning(warn, lineNumber);
+ }
public:
- //! List of all sections which have been read
- SectionList mSections;
+ //! List of all sections which have been read
+ SectionList mSections;
private:
- // -------------------------------------------------------------------
- /** Parses a file section. The current file pointer must be outside
- * of a section.
- * @param out Receives the section data
- * @return true if the end of the file has been reached
- * @throws ImportErrorException if an error occurs
- */
- bool ParseSection(Section& out);
-
- // -------------------------------------------------------------------
- /** Parses the file header
- * @throws ImportErrorException if an error occurs
- */
- void ParseHeader();
-
-
- // override these functions to make sure the line counter gets incremented
- // -------------------------------------------------------------------
- bool SkipLine( const char* in, const char** out)
- {
- ++lineNumber;
- return Assimp::SkipLine(in,out);
- }
- // -------------------------------------------------------------------
- bool SkipLine( )
- {
- return SkipLine(buffer,(const char**)&buffer);
- }
- // -------------------------------------------------------------------
- bool SkipSpacesAndLineEnd( const char* in, const char** out)
- {
- bool bHad = false;
- bool running = true;
- while (running) {
- if( *in == '\r' || *in == '\n') {
- // we open files in binary mode, so there could be \r\n sequences ...
- if (!bHad) {
- bHad = true;
- ++lineNumber;
- }
- }
- else if (*in == '\t' || *in == ' ')bHad = false;
- else break;
- in++;
- }
- *out = in;
- return *in != '\0';
- }
- // -------------------------------------------------------------------
- bool SkipSpacesAndLineEnd( )
- {
- return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
- }
- // -------------------------------------------------------------------
- bool SkipSpaces( )
- {
- return Assimp::SkipSpaces((const char**)&buffer);
- }
-
- char* buffer;
- unsigned int fileSize;
- unsigned int lineNumber;
+ // -------------------------------------------------------------------
+ /** Parses a file section. The current file pointer must be outside
+ * of a section.
+ * @param out Receives the section data
+ * @return true if the end of the file has been reached
+ * @throws ImportErrorException if an error occurs
+ */
+ bool ParseSection(Section& out);
+
+ // -------------------------------------------------------------------
+ /** Parses the file header
+ * @throws ImportErrorException if an error occurs
+ */
+ void ParseHeader();
+
+
+ // override these functions to make sure the line counter gets incremented
+ // -------------------------------------------------------------------
+ bool SkipLine( const char* in, const char** out)
+ {
+ ++lineNumber;
+ return Assimp::SkipLine(in,out);
+ }
+ // -------------------------------------------------------------------
+ bool SkipLine( )
+ {
+ return SkipLine(buffer,(const char**)&buffer);
+ }
+ // -------------------------------------------------------------------
+ bool SkipSpacesAndLineEnd( const char* in, const char** out)
+ {
+ bool bHad = false;
+ bool running = true;
+ while (running) {
+ if( *in == '\r' || *in == '\n') {
+ // we open files in binary mode, so there could be \r\n sequences ...
+ if (!bHad) {
+ bHad = true;
+ ++lineNumber;
+ }
+ }
+ else if (*in == '\t' || *in == ' ')bHad = false;
+ else break;
+ in++;
+ }
+ *out = in;
+ return *in != '\0';
+ }
+ // -------------------------------------------------------------------
+ bool SkipSpacesAndLineEnd( )
+ {
+ return SkipSpacesAndLineEnd(buffer,(const char**)&buffer);
+ }
+ // -------------------------------------------------------------------
+ bool SkipSpaces( )
+ {
+ return Assimp::SkipSpaces((const char**)&buffer);
+ }
+
+ char* buffer;
+ unsigned int fileSize;
+ unsigned int lineNumber;
};
}}
diff --git a/src/3rdparty/assimp/code/MDCFileData.h b/src/3rdparty/assimp/code/MDCFileData.h
index 0f110f9e9..c98828c28 100644
--- a/src/3rdparty/assimp/code/MDCFileData.h
+++ b/src/3rdparty/assimp/code/MDCFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,25 +23,25 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines the helper data structures for importing MDC files
+/** @file Defines the helper data structures for importing MDC files
**********************************************************************
-File format specification:
+File format specification:
http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
**********************************************************************
@@ -49,29 +49,29 @@ http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf
#ifndef AI_MDCFILEHELPER_H_INC
#define AI_MDCFILEHELPER_H_INC
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/anim.h"
-
-#include "./../include/assimp/Compiler/pushpack1.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
+#include <assimp/Compiler/pushpack1.h>
+#include <stdint.h>
namespace Assimp {
namespace MDC {
// to make it easier for us, we test the magic word against both "endianesses"
-#define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI")
-#define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC")
+#define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI")
+#define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC")
// common limitations
-#define AI_MDC_VERSION 2
-#define AI_MDC_MAXQPATH 64
-#define AI_MDC_MAX_BONES 128
+#define AI_MDC_VERSION 2
+#define AI_MDC_MAXQPATH 64
+#define AI_MDC_MAX_BONES 128
-#define AI_MDC_CVERT_BIAS 127.0f
-#define AI_MDC_DELTA_SCALING 4.0f
-#define AI_MDC_BASE_SCALING (1.0f / 64.0f)
+#define AI_MDC_CVERT_BIAS 127.0f
+#define AI_MDC_DELTA_SCALING 4.0f
+#define AI_MDC_BASE_SCALING (1.0f / 64.0f)
// ---------------------------------------------------------------------------
@@ -79,19 +79,19 @@ namespace MDC {
*/
struct Header
{
- uint32_t ulIdent ;
- uint32_t ulVersion ;
- char ucName [ AI_MDC_MAXQPATH ] ;
- uint32_t ulFlags ;
- uint32_t ulNumFrames ;
- uint32_t ulNumTags ;
- uint32_t ulNumSurfaces ;
- uint32_t ulNumSkins ;
- uint32_t ulOffsetBorderFrames ;
- uint32_t ulOffsetTagNames ;
- uint32_t ulOffsetTagFrames ;
- uint32_t ulOffsetSurfaces ;
- uint32_t ulOffsetEnd ;
+ uint32_t ulIdent ;
+ uint32_t ulVersion ;
+ char ucName [ AI_MDC_MAXQPATH ] ;
+ uint32_t ulFlags ;
+ uint32_t ulNumFrames ;
+ uint32_t ulNumTags ;
+ uint32_t ulNumSurfaces ;
+ uint32_t ulNumSkins ;
+ uint32_t ulOffsetBorderFrames ;
+ uint32_t ulOffsetTagNames ;
+ uint32_t ulOffsetTagFrames ;
+ uint32_t ulOffsetSurfaces ;
+ uint32_t ulOffsetEnd ;
} PACK_STRUCT ;
@@ -100,26 +100,41 @@ struct Header
*/
struct Surface
{
- uint32_t ulIdent ;
- char ucName [ AI_MDC_MAXQPATH ] ;
- uint32_t ulFlags ;
- uint32_t ulNumCompFrames ;
- uint32_t ulNumBaseFrames ;
- uint32_t ulNumShaders ;
- uint32_t ulNumVertices ;
- uint32_t ulNumTriangles ;
- uint32_t ulOffsetTriangles ;
- uint32_t ulOffsetShaders ;
- uint32_t ulOffsetTexCoords ;
- uint32_t ulOffsetBaseVerts ;
- uint32_t ulOffsetCompVerts ;
- uint32_t ulOffsetFrameBaseFrames ;
- uint32_t ulOffsetFrameCompFrames ;
- uint32_t ulOffsetEnd;
- Surface()
- {
- ucName[AI_MDC_MAXQPATH-1] = '\0';
- }
+ uint32_t ulIdent ;
+ char ucName [ AI_MDC_MAXQPATH ] ;
+ uint32_t ulFlags ;
+ uint32_t ulNumCompFrames ;
+ uint32_t ulNumBaseFrames ;
+ uint32_t ulNumShaders ;
+ uint32_t ulNumVertices ;
+ uint32_t ulNumTriangles ;
+ uint32_t ulOffsetTriangles ;
+ uint32_t ulOffsetShaders ;
+ uint32_t ulOffsetTexCoords ;
+ uint32_t ulOffsetBaseVerts ;
+ uint32_t ulOffsetCompVerts ;
+ uint32_t ulOffsetFrameBaseFrames ;
+ uint32_t ulOffsetFrameCompFrames ;
+ uint32_t ulOffsetEnd;
+ Surface()
+ : ulIdent(),
+ ulFlags(),
+ ulNumCompFrames(),
+ ulNumBaseFrames(),
+ ulNumShaders(),
+ ulNumVertices(),
+ ulNumTriangles(),
+ ulOffsetTriangles(),
+ ulOffsetShaders(),
+ ulOffsetTexCoords(),
+ ulOffsetBaseVerts(),
+ ulOffsetCompVerts(),
+ ulOffsetFrameBaseFrames(),
+ ulOffsetFrameCompFrames(),
+ ulOffsetEnd()
+ {
+ ucName[AI_MDC_MAXQPATH-1] = '\0';
+ }
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -127,20 +142,20 @@ struct Surface
*/
struct Frame
{
- //! bounding box minimum coords
- aiVector3D bboxMin ;
+ //! bounding box minimum coords
+ aiVector3D bboxMin ;
- //! bounding box maximum coords
- aiVector3D bboxMax ;
+ //! bounding box maximum coords
+ aiVector3D bboxMax ;
- //! local origin of the frame
- aiVector3D localOrigin ;
+ //! local origin of the frame
+ aiVector3D localOrigin ;
- //! radius of the BB
- float radius ;
+ //! radius of the BB
+ float radius ;
- //! Name of the frame
- char name [ 16 ] ;
+ //! Name of the frame
+ char name [ 16 ] ;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -148,7 +163,7 @@ struct Frame
*/
struct Triangle
{
- uint32_t aiIndices[3];
+ uint32_t aiIndices[3];
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -156,7 +171,7 @@ struct Triangle
*/
struct TexturCoord
{
- float u,v;
+ float u,v;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -164,8 +179,8 @@ struct TexturCoord
*/
struct BaseVertex
{
- int16_t x,y,z;
- uint16_t normal;
+ int16_t x,y,z;
+ uint16_t normal;
} PACK_STRUCT;
// ---------------------------------------------------------------------------
@@ -173,7 +188,7 @@ struct BaseVertex
*/
struct CompressedVertex
{
- uint8_t xd,yd,zd,nd;
+ uint8_t xd,yd,zd,nd;
} PACK_STRUCT;
@@ -182,22 +197,22 @@ struct CompressedVertex
*/
struct Shader
{
- char ucName [ AI_MDC_MAXQPATH ] ;
- uint32_t ulPath;
+ char ucName [ AI_MDC_MAXQPATH ] ;
+ uint32_t ulPath;
} PACK_STRUCT;
-#include "./../include/assimp/Compiler/poppack1.h"
+#include <assimp/Compiler/poppack1.h>
// ---------------------------------------------------------------------------
/** Build a floating point vertex from the compressed data in MDC files
*/
void BuildVertex(const Frame& frame,
- const BaseVertex& bvert,
- const CompressedVertex& cvert,
- aiVector3D& vXYZOut,
- aiVector3D& vNorOut);
+ const BaseVertex& bvert,
+ const CompressedVertex& cvert,
+ aiVector3D& vXYZOut,
+ aiVector3D& vNorOut);
}}
#endif // !! AI_MDCFILEHELPER_H_INC
diff --git a/src/3rdparty/assimp/code/MDCLoader.cpp b/src/3rdparty/assimp/code/MDCLoader.cpp
index 45574361a..661447acf 100644
--- a/src/3rdparty/assimp/code/MDCLoader.cpp
+++ b/src/3rdparty/assimp/code/MDCLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,168 +25,178 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the MDC importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
// internal headers
#include "MDCLoader.h"
#include "MD3FileData.h"
#include "MDCNormalTable.h" // shouldn't be included by other units
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <memory>
+
using namespace Assimp;
using namespace Assimp::MDC;
static const aiImporterDesc desc = {
- "Return To Castle Wolfenstein Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "mdc"
+ "Return To Castle Wolfenstein Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "mdc"
};
// ------------------------------------------------------------------------------------------------
void MDC::BuildVertex(const Frame& frame,
- const BaseVertex& bvert,
- const CompressedVertex& cvert,
- aiVector3D& vXYZOut,
- aiVector3D& vNorOut)
+ const BaseVertex& bvert,
+ const CompressedVertex& cvert,
+ aiVector3D& vXYZOut,
+ aiVector3D& vNorOut)
{
- // compute the position
- const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
- const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
- const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
- vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd);
- vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd);
- vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd);
-
- // compute the normal vector .. ehm ... lookup it in the table :-)
- vNorOut.x = mdcNormals[cvert.nd][0];
- vNorOut.y = mdcNormals[cvert.nd][1];
- vNorOut.z = mdcNormals[cvert.nd][2];
+ // compute the position
+ const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+ const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+ const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
+ vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd);
+ vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd);
+ vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd);
+
+ // compute the normal vector .. ehm ... lookup it in the table :-)
+ vNorOut.x = mdcNormals[cvert.nd][0];
+ vNorOut.y = mdcNormals[cvert.nd][1];
+ vNorOut.z = mdcNormals[cvert.nd][2];
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MDCImporter::MDCImporter()
+ : configFrameID(),
+ pcHeader(),
+ mBuffer(),
+ fileSize()
{
}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MDCImporter::~MDCImporter()
{
}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MDCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
- if (extension == "mdc")
- return true;
-
- // if check for extension is not enough, check for the magic tokens
- if (!extension.length() || checkSig) {
- uint32_t tokens[1];
- tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+ if (extension == "mdc")
+ return true;
+
+ // if check for extension is not enough, check for the magic tokens
+ if (!extension.length() || checkSig) {
+ uint32_t tokens[1];
+ tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
+ return CheckMagicToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* MDCImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Validate the header of the given MDC file
void MDCImporter::ValidateHeader()
{
- AI_SWAP4( this->pcHeader->ulVersion );
- AI_SWAP4( this->pcHeader->ulFlags );
- AI_SWAP4( this->pcHeader->ulNumFrames );
- AI_SWAP4( this->pcHeader->ulNumTags );
- AI_SWAP4( this->pcHeader->ulNumSurfaces );
- AI_SWAP4( this->pcHeader->ulNumSkins );
- AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
-
- if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
- pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
- {
- char szBuffer[5];
- szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
- szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
- szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
- szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
- szBuffer[4] = '\0';
-
- throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
- "magic word found is " + std::string( szBuffer ));
- }
-
- if (pcHeader->ulVersion != AI_MDC_VERSION)
- DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
-
- if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
- pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
- {
- throw DeadlyImportError("Some of the offset values in the MDC header are invalid "
- "and point to something behind the file.");
- }
-
- if (this->configFrameID >= this->pcHeader->ulNumFrames)
- throw DeadlyImportError("The requested frame is not available");
+ AI_SWAP4( this->pcHeader->ulVersion );
+ AI_SWAP4( this->pcHeader->ulFlags );
+ AI_SWAP4( this->pcHeader->ulNumFrames );
+ AI_SWAP4( this->pcHeader->ulNumTags );
+ AI_SWAP4( this->pcHeader->ulNumSurfaces );
+ AI_SWAP4( this->pcHeader->ulNumSkins );
+ AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
+
+ if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
+ pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
+ {
+ char szBuffer[5];
+ szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
+ szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
+ szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
+ szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
+ szBuffer[4] = '\0';
+
+ throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
+ "magic word found is " + std::string( szBuffer ));
+ }
+
+ if (pcHeader->ulVersion != AI_MDC_VERSION)
+ DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
+
+ if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
+ pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
+ {
+ throw DeadlyImportError("Some of the offset values in the MDC header are invalid "
+ "and point to something behind the file.");
+ }
+
+ if (this->configFrameID >= this->pcHeader->ulNumFrames)
+ throw DeadlyImportError("The requested frame is not available");
}
// ------------------------------------------------------------------------------------------------
// Validate the header of a given MDC file surface
void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
{
- AI_SWAP4(pcSurf->ulFlags);
- AI_SWAP4(pcSurf->ulNumCompFrames);
- AI_SWAP4(pcSurf->ulNumBaseFrames);
- AI_SWAP4(pcSurf->ulNumShaders);
- AI_SWAP4(pcSurf->ulNumVertices);
- AI_SWAP4(pcSurf->ulNumTriangles);
- AI_SWAP4(pcSurf->ulOffsetTriangles);
- AI_SWAP4(pcSurf->ulOffsetTexCoords);
- AI_SWAP4(pcSurf->ulOffsetBaseVerts);
- AI_SWAP4(pcSurf->ulOffsetCompVerts);
- AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames);
- AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
- AI_SWAP4(pcSurf->ulOffsetEnd);
+ AI_SWAP4(pcSurf->ulFlags);
+ AI_SWAP4(pcSurf->ulNumCompFrames);
+ AI_SWAP4(pcSurf->ulNumBaseFrames);
+ AI_SWAP4(pcSurf->ulNumShaders);
+ AI_SWAP4(pcSurf->ulNumVertices);
+ AI_SWAP4(pcSurf->ulNumTriangles);
+ AI_SWAP4(pcSurf->ulOffsetTriangles);
+ AI_SWAP4(pcSurf->ulOffsetTexCoords);
+ AI_SWAP4(pcSurf->ulOffsetBaseVerts);
+ AI_SWAP4(pcSurf->ulOffsetCompVerts);
+ AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames);
+ AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
+ AI_SWAP4(pcSurf->ulOffsetEnd);
const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
- if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
- (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
- pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
- pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
- pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
- pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
- (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
+ if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
+ (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
+ pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
+ pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
+ pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
+ pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
+ (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
{
throw DeadlyImportError("Some of the offset values in the MDC surface header "
"are invalid and point somewhere behind the file.");
@@ -197,286 +207,286 @@ void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
// Setup configuration properties
void MDCImporter::SetupProperties(const Importer* pImp)
{
- // The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- if(static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME,-1))){
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ if(static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME,-1))){
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MDCImporter::InternReadFile(
- const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void MDCImporter::InternReadFile(
+ const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open MDC file " + pFile + ".");
-
- // check whether the mdc file is large enough to contain the file header
- fileSize = (unsigned int)file->FileSize();
- if( fileSize < sizeof(MDC::Header))
- throw DeadlyImportError( "MDC File is too small.");
-
- std::vector<unsigned char> mBuffer2(fileSize);
- file->Read( &mBuffer2[0], 1, fileSize);
- mBuffer = &mBuffer2[0];
-
- // validate the file header
- this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
- this->ValidateHeader();
-
- std::vector<std::string> aszShaders;
-
- // get a pointer to the frame we want to read
- BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
- this->pcHeader->ulOffsetBorderFrames);
-
- // no need to swap the other members, we won't need them
- pcFrame += configFrameID;
- AI_SWAP4( pcFrame->localOrigin[0] );
- AI_SWAP4( pcFrame->localOrigin[1] );
- AI_SWAP4( pcFrame->localOrigin[2] );
-
- // get the number of valid surfaces
- BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
- pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
- unsigned int iNumShaders = 0;
- for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
- {
- // validate the surface header
- this->ValidateSurfaceHeader(pcSurface2);
-
- if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
- iNumShaders += pcSurface2->ulNumShaders;
- pcSurface2 = new ((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
- }
- aszShaders.reserve(iNumShaders);
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-
- // necessary that we don't crash if an exception occurs
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mMeshes[i] = NULL;
-
- // now read all surfaces
- unsigned int iDefaultMatIndex = UINT_MAX;
- for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
- {
- if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
- aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
-
- pcMesh->mNumFaces = pcSurface->ulNumTriangles;
- pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
-
- // store the name of the surface for use as node name.
- // FIX: make sure there is a 0 termination
- const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0';
- pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName;
-
- // go to the first shader in the file. ignore the others.
- if (pcSurface->ulNumShaders)
- {
- const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
- pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
-
- // create a new shader
- aszShaders.push_back(std::string( pcShader->ucName, std::min(
- ::strlen(pcShader->ucName),sizeof(pcShader->ucName)) ));
- }
- // need to create a default material
- else if (UINT_MAX == iDefaultMatIndex)
- {
- pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
- aszShaders.push_back(std::string());
- }
- // otherwise assign a reference to the default material
- else pcMesh->mMaterialIndex = iDefaultMatIndex;
-
- // allocate output storage for the mesh
- aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- // create all vertices/faces
- BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
-
- BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
-
- // get a pointer to the uncompressed vertices
- int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
- pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
-
- AI_SWAP2(iOfs);
-
- BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
- ((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
- ((int)iOfs * pcSurface->ulNumVertices * 4);
-
- // do the main swapping stuff ...
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open MDC file " + pFile + ".");
+
+ // check whether the mdc file is large enough to contain the file header
+ fileSize = (unsigned int)file->FileSize();
+ if( fileSize < sizeof(MDC::Header))
+ throw DeadlyImportError( "MDC File is too small.");
+
+ std::vector<unsigned char> mBuffer2(fileSize);
+ file->Read( &mBuffer2[0], 1, fileSize);
+ mBuffer = &mBuffer2[0];
+
+ // validate the file header
+ this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
+ this->ValidateHeader();
+
+ std::vector<std::string> aszShaders;
+
+ // get a pointer to the frame we want to read
+ BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
+ this->pcHeader->ulOffsetBorderFrames);
+
+ // no need to swap the other members, we won't need them
+ pcFrame += configFrameID;
+ AI_SWAP4( pcFrame->localOrigin[0] );
+ AI_SWAP4( pcFrame->localOrigin[1] );
+ AI_SWAP4( pcFrame->localOrigin[2] );
+
+ // get the number of valid surfaces
+ BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
+ pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
+ unsigned int iNumShaders = 0;
+ for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
+ {
+ // validate the surface header
+ this->ValidateSurfaceHeader(pcSurface2);
+
+ if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
+ iNumShaders += pcSurface2->ulNumShaders;
+ pcSurface2 = new ((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
+ }
+ aszShaders.reserve(iNumShaders);
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+
+ // necessary that we don't crash if an exception occurs
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mMeshes[i] = NULL;
+
+ // now read all surfaces
+ unsigned int iDefaultMatIndex = UINT_MAX;
+ for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
+ {
+ if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
+ aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
+
+ pcMesh->mNumFaces = pcSurface->ulNumTriangles;
+ pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
+
+ // store the name of the surface for use as node name.
+ // FIX: make sure there is a 0 termination
+ const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0';
+ pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName;
+
+ // go to the first shader in the file. ignore the others.
+ if (pcSurface->ulNumShaders)
+ {
+ const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
+ pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
+
+ // create a new shader
+ aszShaders.push_back(std::string( pcShader->ucName, std::min(
+ ::strlen(pcShader->ucName),sizeof(pcShader->ucName)) ));
+ }
+ // need to create a default material
+ else if (UINT_MAX == iDefaultMatIndex)
+ {
+ pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
+ aszShaders.push_back(std::string());
+ }
+ // otherwise assign a reference to the default material
+ else pcMesh->mMaterialIndex = iDefaultMatIndex;
+
+ // allocate output storage for the mesh
+ aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ // create all vertices/faces
+ BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
+ ((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
+
+ BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
+ ((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
+
+ // get a pointer to the uncompressed vertices
+ int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
+ pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
+
+ AI_SWAP2(iOfs);
+
+ BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
+ ((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
+ ((int)iOfs * pcSurface->ulNumVertices * 4);
+
+ // do the main swapping stuff ...
#if (defined AI_BUILD_BIG_ENDIAN)
- // swap all triangles
- for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
- {
- AI_SWAP4( pcTriangle[i].aiIndices[0] );
- AI_SWAP4( pcTriangle[i].aiIndices[1] );
- AI_SWAP4( pcTriangle[i].aiIndices[2] );
- }
-
- // swap all vertices
- for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
- {
- AI_SWAP2( pcVerts->normal );
- AI_SWAP2( pcVerts->x );
- AI_SWAP2( pcVerts->y );
- AI_SWAP2( pcVerts->z );
- }
-
- // swap all texture coordinates
- for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
- {
- AI_SWAP4( pcUVs->v );
- AI_SWAP4( pcUVs->v );
- }
+ // swap all triangles
+ for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
+ {
+ AI_SWAP4( pcTriangle[i].aiIndices[0] );
+ AI_SWAP4( pcTriangle[i].aiIndices[1] );
+ AI_SWAP4( pcTriangle[i].aiIndices[2] );
+ }
+
+ // swap all vertices
+ for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
+ {
+ AI_SWAP2( pcVerts->normal );
+ AI_SWAP2( pcVerts->x );
+ AI_SWAP2( pcVerts->y );
+ AI_SWAP2( pcVerts->z );
+ }
+
+ // swap all texture coordinates
+ for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
+ {
+ AI_SWAP4( pcUVs->v );
+ AI_SWAP4( pcUVs->v );
+ }
#endif
- const MDC::CompressedVertex* pcCVerts = NULL;
- int16_t* mdcCompVert = NULL;
-
- // access compressed frames for large frame numbers, but never for the first
- if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
- {
- mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
- AI_SWAP2P(mdcCompVert);
- if( *mdcCompVert >= 0 )
- {
- pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
- pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
- }
- else mdcCompVert = NULL;
- }
-
- // copy all faces
- for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
- ++pcTriangle,++pcFaceCur)
- {
- const unsigned int iOutIndex = iFace*3;
- pcFaceCur->mNumIndices = 3;
- pcFaceCur->mIndices = new unsigned int[3];
-
- for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
- ++pcVertCur,++pcUVCur,++pcNorCur)
- {
- uint32_t quak = pcTriangle->aiIndices[iIndex];
- if (quak >= pcSurface->ulNumVertices)
- {
- DefaultLogger::get()->error("MDC vertex index is out of range");
- quak = pcSurface->ulNumVertices-1;
- }
-
- // compressed vertices?
- if (mdcCompVert)
- {
- MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
- *pcVertCur,*pcNorCur);
- }
- else
- {
- // copy position
- pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
- pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
- pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
-
- // copy normals
- MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
-
- // copy texture coordinates
- pcUVCur->x = pcUVs[quak].u;
- pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
- }
- pcVertCur->x += pcFrame->localOrigin[0] ;
- pcVertCur->y += pcFrame->localOrigin[1] ;
- pcVertCur->z += pcFrame->localOrigin[2] ;
- }
-
- // swap the face order - DX to OGL
- pcFaceCur->mIndices[0] = iOutIndex + 2;
- pcFaceCur->mIndices[1] = iOutIndex + 1;
- pcFaceCur->mIndices[2] = iOutIndex + 0;
- }
-
- pcSurface = new ((int8_t*)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
- }
-
- // create a flat node graph with a root node and one child for each surface
- if (!pScene->mNumMeshes)
- throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh");
- else if (1 == pScene->mNumMeshes)
- {
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3]));
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- }
- else
- {
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
- pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
- pScene->mRootNode->mName.Set("<root>");
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- {
- aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
- pcNode->mParent = pScene->mRootNode;
- pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3]));
- pcNode->mNumMeshes = 1;
- pcNode->mMeshes = new unsigned int[1];
- pcNode->mMeshes[0] = i;
- }
- }
-
- // make sure we invalidate the pointer to the mesh name
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mMeshes[i]->mTextureCoords[3] = NULL;
-
- // create materials
- pScene->mNumMaterials = (unsigned int)aszShaders.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- {
- aiMaterial* pcMat = new aiMaterial();
- pScene->mMaterials[i] = pcMat;
-
- const std::string& name = aszShaders[i];
-
- int iMode = (int)aiShadingMode_Gouraud;
- pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- // add a small ambient color value - RtCW seems to have one
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.05f;
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- if (name.length())clr.b = clr.g = clr.r = 1.0f;
- else clr.b = clr.g = clr.r = 0.6f;
-
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- if (name.length())
- {
- aiString path;
- path.Set(name);
- pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- }
+ const MDC::CompressedVertex* pcCVerts = NULL;
+ int16_t* mdcCompVert = NULL;
+
+ // access compressed frames for large frame numbers, but never for the first
+ if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
+ {
+ mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
+ AI_SWAP2P(mdcCompVert);
+ if( *mdcCompVert >= 0 )
+ {
+ pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
+ pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
+ }
+ else mdcCompVert = NULL;
+ }
+
+ // copy all faces
+ for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
+ ++pcTriangle,++pcFaceCur)
+ {
+ const unsigned int iOutIndex = iFace*3;
+ pcFaceCur->mNumIndices = 3;
+ pcFaceCur->mIndices = new unsigned int[3];
+
+ for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
+ ++pcVertCur,++pcUVCur,++pcNorCur)
+ {
+ uint32_t quak = pcTriangle->aiIndices[iIndex];
+ if (quak >= pcSurface->ulNumVertices)
+ {
+ DefaultLogger::get()->error("MDC vertex index is out of range");
+ quak = pcSurface->ulNumVertices-1;
+ }
+
+ // compressed vertices?
+ if (mdcCompVert)
+ {
+ MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
+ *pcVertCur,*pcNorCur);
+ }
+ else
+ {
+ // copy position
+ pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
+ pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
+ pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
+
+ // copy normals
+ MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
+
+ // copy texture coordinates
+ pcUVCur->x = pcUVs[quak].u;
+ pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
+ }
+ pcVertCur->x += pcFrame->localOrigin[0] ;
+ pcVertCur->y += pcFrame->localOrigin[1] ;
+ pcVertCur->z += pcFrame->localOrigin[2] ;
+ }
+
+ // swap the face order - DX to OGL
+ pcFaceCur->mIndices[0] = iOutIndex + 2;
+ pcFaceCur->mIndices[1] = iOutIndex + 1;
+ pcFaceCur->mIndices[2] = iOutIndex + 0;
+ }
+
+ pcSurface = new ((int8_t*)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
+ }
+
+ // create a flat node graph with a root node and one child for each surface
+ if (!pScene->mNumMeshes)
+ throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh");
+ else if (1 == pScene->mNumMeshes)
+ {
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3]));
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ }
+ else
+ {
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
+ pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
+ pScene->mRootNode->mName.Set("<root>");
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3]));
+ pcNode->mNumMeshes = 1;
+ pcNode->mMeshes = new unsigned int[1];
+ pcNode->mMeshes[0] = i;
+ }
+ }
+
+ // make sure we invalidate the pointer to the mesh name
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mMeshes[i]->mTextureCoords[3] = NULL;
+
+ // create materials
+ pScene->mNumMaterials = (unsigned int)aszShaders.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ {
+ aiMaterial* pcMat = new aiMaterial();
+ pScene->mMaterials[i] = pcMat;
+
+ const std::string& name = aszShaders[i];
+
+ int iMode = (int)aiShadingMode_Gouraud;
+ pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ // add a small ambient color value - RtCW seems to have one
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.05f;
+ pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ if (name.length())clr.b = clr.g = clr.r = 1.0f;
+ else clr.b = clr.g = clr.r = 0.6f;
+
+ pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ if (name.length())
+ {
+ aiString path;
+ path.Set(name);
+ pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER
diff --git a/src/3rdparty/assimp/code/MDCLoader.h b/src/3rdparty/assimp/code/MDCLoader.h
index 49d8d418e..fcfbc642d 100644
--- a/src/3rdparty/assimp/code/MDCLoader.h
+++ b/src/3rdparty/assimp/code/MDCLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,34 +23,35 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file MDCLoader.h
- * @brief Definition of the MDC importer class.
+ * @brief Definition of the MDC importer class.
*/
#ifndef AI_MDCLOADER_H_INCLUDED
#define AI_MDCLOADER_H_INCLUDED
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include "BaseImporter.h"
#include "MDCFileData.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
+
+namespace Assimp {
-namespace Assimp {
using namespace MDC;
// ---------------------------------------------------------------------------
@@ -59,70 +60,69 @@ using namespace MDC;
class MDCImporter : public BaseImporter
{
public:
- MDCImporter();
- ~MDCImporter();
+ MDCImporter();
+ ~MDCImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Validate the header of the file
- */
- void ValidateHeader();
+ // -------------------------------------------------------------------
+ /** Validate the header of the file
+ */
+ void ValidateHeader();
- // -------------------------------------------------------------------
- /** Validate the header of a MDC surface
- */
- void ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf);
+ // -------------------------------------------------------------------
+ /** Validate the header of a MDC surface
+ */
+ void ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf);
protected:
- /** Configuration option: frame to be loaded */
- unsigned int configFrameID;
+ /** Configuration option: frame to be loaded */
+ unsigned int configFrameID;
- /** Header of the MDC file */
- BE_NCONST MDC::Header* pcHeader;
+ /** Header of the MDC file */
+ BE_NCONST MDC::Header* pcHeader;
- /** Buffer to hold the loaded file */
- unsigned char* mBuffer;
+ /** Buffer to hold the loaded file */
+ unsigned char* mBuffer;
- /** size of the file, in bytes */
- unsigned int fileSize;
+ /** size of the file, in bytes */
+ unsigned int fileSize;
};
} // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC
-
diff --git a/src/3rdparty/assimp/code/MDCNormalTable.h b/src/3rdparty/assimp/code/MDCNormalTable.h
index 385528682..f47e97f33 100644
--- a/src/3rdparty/assimp/code/MDCNormalTable.h
+++ b/src/3rdparty/assimp/code/MDCNormalTable.h
@@ -1,6 +1,6 @@
/* -----------------------------------------------------------------------------
-PicoModel Library
+PicoModel Library
Copyright (c) 2002, Randy Reddig & seaw0lf
All rights reserved.
@@ -17,7 +17,7 @@ other materials provided with the distribution.
Neither the names of the copyright holders nor the names of its contributors may
be used to endorse or promote products derived from this software without
-specific prior written permission.
+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
@@ -38,262 +38,262 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* mdc decoding normal table */
float mdcNormals[ 256 ][ 3 ] =
{
- { 1.000000f, 0.000000f, 0.000000f },
- { 0.980785f, 0.195090f, 0.000000f },
- { 0.923880f, 0.382683f, 0.000000f },
- { 0.831470f, 0.555570f, 0.000000f },
- { 0.707107f, 0.707107f, 0.000000f },
- { 0.555570f, 0.831470f, 0.000000f },
- { 0.382683f, 0.923880f, 0.000000f },
- { 0.195090f, 0.980785f, 0.000000f },
- { -0.000000f, 1.000000f, 0.000000f },
- { -0.195090f, 0.980785f, 0.000000f },
- { -0.382683f, 0.923880f, 0.000000f },
- { -0.555570f, 0.831470f, 0.000000f },
- { -0.707107f, 0.707107f, 0.000000f },
- { -0.831470f, 0.555570f, 0.000000f },
- { -0.923880f, 0.382683f, 0.000000f },
- { -0.980785f, 0.195090f, 0.000000f },
- { -1.000000f, -0.000000f, 0.000000f },
- { -0.980785f, -0.195090f, 0.000000f },
- { -0.923880f, -0.382683f, 0.000000f },
- { -0.831470f, -0.555570f, 0.000000f },
- { -0.707107f, -0.707107f, 0.000000f },
- { -0.555570f, -0.831469f, 0.000000f },
- { -0.382684f, -0.923880f, 0.000000f },
- { -0.195090f, -0.980785f, 0.000000f },
- { 0.000000f, -1.000000f, 0.000000f },
- { 0.195090f, -0.980785f, 0.000000f },
- { 0.382684f, -0.923879f, 0.000000f },
- { 0.555570f, -0.831470f, 0.000000f },
- { 0.707107f, -0.707107f, 0.000000f },
- { 0.831470f, -0.555570f, 0.000000f },
- { 0.923880f, -0.382683f, 0.000000f },
- { 0.980785f, -0.195090f, 0.000000f },
- { 0.980785f, 0.000000f, -0.195090f },
- { 0.956195f, 0.218245f, -0.195090f },
- { 0.883657f, 0.425547f, -0.195090f },
- { 0.766809f, 0.611510f, -0.195090f },
- { 0.611510f, 0.766809f, -0.195090f },
- { 0.425547f, 0.883657f, -0.195090f },
- { 0.218245f, 0.956195f, -0.195090f },
- { -0.000000f, 0.980785f, -0.195090f },
- { -0.218245f, 0.956195f, -0.195090f },
- { -0.425547f, 0.883657f, -0.195090f },
- { -0.611510f, 0.766809f, -0.195090f },
- { -0.766809f, 0.611510f, -0.195090f },
- { -0.883657f, 0.425547f, -0.195090f },
- { -0.956195f, 0.218245f, -0.195090f },
- { -0.980785f, -0.000000f, -0.195090f },
- { -0.956195f, -0.218245f, -0.195090f },
- { -0.883657f, -0.425547f, -0.195090f },
- { -0.766809f, -0.611510f, -0.195090f },
- { -0.611510f, -0.766809f, -0.195090f },
- { -0.425547f, -0.883657f, -0.195090f },
- { -0.218245f, -0.956195f, -0.195090f },
- { 0.000000f, -0.980785f, -0.195090f },
- { 0.218245f, -0.956195f, -0.195090f },
- { 0.425547f, -0.883657f, -0.195090f },
- { 0.611510f, -0.766809f, -0.195090f },
- { 0.766809f, -0.611510f, -0.195090f },
- { 0.883657f, -0.425547f, -0.195090f },
- { 0.956195f, -0.218245f, -0.195090f },
- { 0.923880f, 0.000000f, -0.382683f },
- { 0.892399f, 0.239118f, -0.382683f },
- { 0.800103f, 0.461940f, -0.382683f },
- { 0.653281f, 0.653281f, -0.382683f },
- { 0.461940f, 0.800103f, -0.382683f },
- { 0.239118f, 0.892399f, -0.382683f },
- { -0.000000f, 0.923880f, -0.382683f },
- { -0.239118f, 0.892399f, -0.382683f },
- { -0.461940f, 0.800103f, -0.382683f },
- { -0.653281f, 0.653281f, -0.382683f },
- { -0.800103f, 0.461940f, -0.382683f },
- { -0.892399f, 0.239118f, -0.382683f },
- { -0.923880f, -0.000000f, -0.382683f },
- { -0.892399f, -0.239118f, -0.382683f },
- { -0.800103f, -0.461940f, -0.382683f },
- { -0.653282f, -0.653281f, -0.382683f },
- { -0.461940f, -0.800103f, -0.382683f },
- { -0.239118f, -0.892399f, -0.382683f },
- { 0.000000f, -0.923880f, -0.382683f },
- { 0.239118f, -0.892399f, -0.382683f },
- { 0.461940f, -0.800103f, -0.382683f },
- { 0.653281f, -0.653282f, -0.382683f },
- { 0.800103f, -0.461940f, -0.382683f },
- { 0.892399f, -0.239117f, -0.382683f },
- { 0.831470f, 0.000000f, -0.555570f },
- { 0.790775f, 0.256938f, -0.555570f },
- { 0.672673f, 0.488726f, -0.555570f },
- { 0.488726f, 0.672673f, -0.555570f },
- { 0.256938f, 0.790775f, -0.555570f },
- { -0.000000f, 0.831470f, -0.555570f },
- { -0.256938f, 0.790775f, -0.555570f },
- { -0.488726f, 0.672673f, -0.555570f },
- { -0.672673f, 0.488726f, -0.555570f },
- { -0.790775f, 0.256938f, -0.555570f },
- { -0.831470f, -0.000000f, -0.555570f },
- { -0.790775f, -0.256938f, -0.555570f },
- { -0.672673f, -0.488726f, -0.555570f },
- { -0.488725f, -0.672673f, -0.555570f },
- { -0.256938f, -0.790775f, -0.555570f },
- { 0.000000f, -0.831470f, -0.555570f },
- { 0.256938f, -0.790775f, -0.555570f },
- { 0.488725f, -0.672673f, -0.555570f },
- { 0.672673f, -0.488726f, -0.555570f },
- { 0.790775f, -0.256938f, -0.555570f },
- { 0.707107f, 0.000000f, -0.707107f },
- { 0.653281f, 0.270598f, -0.707107f },
- { 0.500000f, 0.500000f, -0.707107f },
- { 0.270598f, 0.653281f, -0.707107f },
- { -0.000000f, 0.707107f, -0.707107f },
- { -0.270598f, 0.653282f, -0.707107f },
- { -0.500000f, 0.500000f, -0.707107f },
- { -0.653281f, 0.270598f, -0.707107f },
- { -0.707107f, -0.000000f, -0.707107f },
- { -0.653281f, -0.270598f, -0.707107f },
- { -0.500000f, -0.500000f, -0.707107f },
- { -0.270598f, -0.653281f, -0.707107f },
- { 0.000000f, -0.707107f, -0.707107f },
- { 0.270598f, -0.653281f, -0.707107f },
- { 0.500000f, -0.500000f, -0.707107f },
- { 0.653282f, -0.270598f, -0.707107f },
- { 0.555570f, 0.000000f, -0.831470f },
- { 0.481138f, 0.277785f, -0.831470f },
- { 0.277785f, 0.481138f, -0.831470f },
- { -0.000000f, 0.555570f, -0.831470f },
- { -0.277785f, 0.481138f, -0.831470f },
- { -0.481138f, 0.277785f, -0.831470f },
- { -0.555570f, -0.000000f, -0.831470f },
- { -0.481138f, -0.277785f, -0.831470f },
- { -0.277785f, -0.481138f, -0.831470f },
- { 0.000000f, -0.555570f, -0.831470f },
- { 0.277785f, -0.481138f, -0.831470f },
- { 0.481138f, -0.277785f, -0.831470f },
- { 0.382683f, 0.000000f, -0.923880f },
- { 0.270598f, 0.270598f, -0.923880f },
- { -0.000000f, 0.382683f, -0.923880f },
- { -0.270598f, 0.270598f, -0.923880f },
- { -0.382683f, -0.000000f, -0.923880f },
- { -0.270598f, -0.270598f, -0.923880f },
- { 0.000000f, -0.382683f, -0.923880f },
- { 0.270598f, -0.270598f, -0.923880f },
- { 0.195090f, 0.000000f, -0.980785f },
- { -0.000000f, 0.195090f, -0.980785f },
- { -0.195090f, -0.000000f, -0.980785f },
- { 0.000000f, -0.195090f, -0.980785f },
- { 0.980785f, 0.000000f, 0.195090f },
- { 0.956195f, 0.218245f, 0.195090f },
- { 0.883657f, 0.425547f, 0.195090f },
- { 0.766809f, 0.611510f, 0.195090f },
- { 0.611510f, 0.766809f, 0.195090f },
- { 0.425547f, 0.883657f, 0.195090f },
- { 0.218245f, 0.956195f, 0.195090f },
- { -0.000000f, 0.980785f, 0.195090f },
- { -0.218245f, 0.956195f, 0.195090f },
- { -0.425547f, 0.883657f, 0.195090f },
- { -0.611510f, 0.766809f, 0.195090f },
- { -0.766809f, 0.611510f, 0.195090f },
- { -0.883657f, 0.425547f, 0.195090f },
- { -0.956195f, 0.218245f, 0.195090f },
- { -0.980785f, -0.000000f, 0.195090f },
- { -0.956195f, -0.218245f, 0.195090f },
- { -0.883657f, -0.425547f, 0.195090f },
- { -0.766809f, -0.611510f, 0.195090f },
- { -0.611510f, -0.766809f, 0.195090f },
- { -0.425547f, -0.883657f, 0.195090f },
- { -0.218245f, -0.956195f, 0.195090f },
- { 0.000000f, -0.980785f, 0.195090f },
- { 0.218245f, -0.956195f, 0.195090f },
- { 0.425547f, -0.883657f, 0.195090f },
- { 0.611510f, -0.766809f, 0.195090f },
- { 0.766809f, -0.611510f, 0.195090f },
- { 0.883657f, -0.425547f, 0.195090f },
- { 0.956195f, -0.218245f, 0.195090f },
- { 0.923880f, 0.000000f, 0.382683f },
- { 0.892399f, 0.239118f, 0.382683f },
- { 0.800103f, 0.461940f, 0.382683f },
- { 0.653281f, 0.653281f, 0.382683f },
- { 0.461940f, 0.800103f, 0.382683f },
- { 0.239118f, 0.892399f, 0.382683f },
- { -0.000000f, 0.923880f, 0.382683f },
- { -0.239118f, 0.892399f, 0.382683f },
- { -0.461940f, 0.800103f, 0.382683f },
- { -0.653281f, 0.653281f, 0.382683f },
- { -0.800103f, 0.461940f, 0.382683f },
- { -0.892399f, 0.239118f, 0.382683f },
- { -0.923880f, -0.000000f, 0.382683f },
- { -0.892399f, -0.239118f, 0.382683f },
- { -0.800103f, -0.461940f, 0.382683f },
- { -0.653282f, -0.653281f, 0.382683f },
- { -0.461940f, -0.800103f, 0.382683f },
- { -0.239118f, -0.892399f, 0.382683f },
- { 0.000000f, -0.923880f, 0.382683f },
- { 0.239118f, -0.892399f, 0.382683f },
- { 0.461940f, -0.800103f, 0.382683f },
- { 0.653281f, -0.653282f, 0.382683f },
- { 0.800103f, -0.461940f, 0.382683f },
- { 0.892399f, -0.239117f, 0.382683f },
- { 0.831470f, 0.000000f, 0.555570f },
- { 0.790775f, 0.256938f, 0.555570f },
- { 0.672673f, 0.488726f, 0.555570f },
- { 0.488726f, 0.672673f, 0.555570f },
- { 0.256938f, 0.790775f, 0.555570f },
- { -0.000000f, 0.831470f, 0.555570f },
- { -0.256938f, 0.790775f, 0.555570f },
- { -0.488726f, 0.672673f, 0.555570f },
- { -0.672673f, 0.488726f, 0.555570f },
- { -0.790775f, 0.256938f, 0.555570f },
- { -0.831470f, -0.000000f, 0.555570f },
- { -0.790775f, -0.256938f, 0.555570f },
- { -0.672673f, -0.488726f, 0.555570f },
- { -0.488725f, -0.672673f, 0.555570f },
- { -0.256938f, -0.790775f, 0.555570f },
- { 0.000000f, -0.831470f, 0.555570f },
- { 0.256938f, -0.790775f, 0.555570f },
- { 0.488725f, -0.672673f, 0.555570f },
- { 0.672673f, -0.488726f, 0.555570f },
- { 0.790775f, -0.256938f, 0.555570f },
- { 0.707107f, 0.000000f, 0.707107f },
- { 0.653281f, 0.270598f, 0.707107f },
- { 0.500000f, 0.500000f, 0.707107f },
- { 0.270598f, 0.653281f, 0.707107f },
- { -0.000000f, 0.707107f, 0.707107f },
- { -0.270598f, 0.653282f, 0.707107f },
- { -0.500000f, 0.500000f, 0.707107f },
- { -0.653281f, 0.270598f, 0.707107f },
- { -0.707107f, -0.000000f, 0.707107f },
- { -0.653281f, -0.270598f, 0.707107f },
- { -0.500000f, -0.500000f, 0.707107f },
- { -0.270598f, -0.653281f, 0.707107f },
- { 0.000000f, -0.707107f, 0.707107f },
- { 0.270598f, -0.653281f, 0.707107f },
- { 0.500000f, -0.500000f, 0.707107f },
- { 0.653282f, -0.270598f, 0.707107f },
- { 0.555570f, 0.000000f, 0.831470f },
- { 0.481138f, 0.277785f, 0.831470f },
- { 0.277785f, 0.481138f, 0.831470f },
- { -0.000000f, 0.555570f, 0.831470f },
- { -0.277785f, 0.481138f, 0.831470f },
- { -0.481138f, 0.277785f, 0.831470f },
- { -0.555570f, -0.000000f, 0.831470f },
- { -0.481138f, -0.277785f, 0.831470f },
- { -0.277785f, -0.481138f, 0.831470f },
- { 0.000000f, -0.555570f, 0.831470f },
- { 0.277785f, -0.481138f, 0.831470f },
- { 0.481138f, -0.277785f, 0.831470f },
- { 0.382683f, 0.000000f, 0.923880f },
- { 0.270598f, 0.270598f, 0.923880f },
- { -0.000000f, 0.382683f, 0.923880f },
- { -0.270598f, 0.270598f, 0.923880f },
- { -0.382683f, -0.000000f, 0.923880f },
- { -0.270598f, -0.270598f, 0.923880f },
- { 0.000000f, -0.382683f, 0.923880f },
- { 0.270598f, -0.270598f, 0.923880f },
- { 0.195090f, 0.000000f, 0.980785f },
- { -0.000000f, 0.195090f, 0.980785f },
- { -0.195090f, -0.000000f, 0.980785f },
- { 0.000000f, -0.195090f, 0.980785f }
+ { 1.000000f, 0.000000f, 0.000000f },
+ { 0.980785f, 0.195090f, 0.000000f },
+ { 0.923880f, 0.382683f, 0.000000f },
+ { 0.831470f, 0.555570f, 0.000000f },
+ { 0.707107f, 0.707107f, 0.000000f },
+ { 0.555570f, 0.831470f, 0.000000f },
+ { 0.382683f, 0.923880f, 0.000000f },
+ { 0.195090f, 0.980785f, 0.000000f },
+ { -0.000000f, 1.000000f, 0.000000f },
+ { -0.195090f, 0.980785f, 0.000000f },
+ { -0.382683f, 0.923880f, 0.000000f },
+ { -0.555570f, 0.831470f, 0.000000f },
+ { -0.707107f, 0.707107f, 0.000000f },
+ { -0.831470f, 0.555570f, 0.000000f },
+ { -0.923880f, 0.382683f, 0.000000f },
+ { -0.980785f, 0.195090f, 0.000000f },
+ { -1.000000f, -0.000000f, 0.000000f },
+ { -0.980785f, -0.195090f, 0.000000f },
+ { -0.923880f, -0.382683f, 0.000000f },
+ { -0.831470f, -0.555570f, 0.000000f },
+ { -0.707107f, -0.707107f, 0.000000f },
+ { -0.555570f, -0.831469f, 0.000000f },
+ { -0.382684f, -0.923880f, 0.000000f },
+ { -0.195090f, -0.980785f, 0.000000f },
+ { 0.000000f, -1.000000f, 0.000000f },
+ { 0.195090f, -0.980785f, 0.000000f },
+ { 0.382684f, -0.923879f, 0.000000f },
+ { 0.555570f, -0.831470f, 0.000000f },
+ { 0.707107f, -0.707107f, 0.000000f },
+ { 0.831470f, -0.555570f, 0.000000f },
+ { 0.923880f, -0.382683f, 0.000000f },
+ { 0.980785f, -0.195090f, 0.000000f },
+ { 0.980785f, 0.000000f, -0.195090f },
+ { 0.956195f, 0.218245f, -0.195090f },
+ { 0.883657f, 0.425547f, -0.195090f },
+ { 0.766809f, 0.611510f, -0.195090f },
+ { 0.611510f, 0.766809f, -0.195090f },
+ { 0.425547f, 0.883657f, -0.195090f },
+ { 0.218245f, 0.956195f, -0.195090f },
+ { -0.000000f, 0.980785f, -0.195090f },
+ { -0.218245f, 0.956195f, -0.195090f },
+ { -0.425547f, 0.883657f, -0.195090f },
+ { -0.611510f, 0.766809f, -0.195090f },
+ { -0.766809f, 0.611510f, -0.195090f },
+ { -0.883657f, 0.425547f, -0.195090f },
+ { -0.956195f, 0.218245f, -0.195090f },
+ { -0.980785f, -0.000000f, -0.195090f },
+ { -0.956195f, -0.218245f, -0.195090f },
+ { -0.883657f, -0.425547f, -0.195090f },
+ { -0.766809f, -0.611510f, -0.195090f },
+ { -0.611510f, -0.766809f, -0.195090f },
+ { -0.425547f, -0.883657f, -0.195090f },
+ { -0.218245f, -0.956195f, -0.195090f },
+ { 0.000000f, -0.980785f, -0.195090f },
+ { 0.218245f, -0.956195f, -0.195090f },
+ { 0.425547f, -0.883657f, -0.195090f },
+ { 0.611510f, -0.766809f, -0.195090f },
+ { 0.766809f, -0.611510f, -0.195090f },
+ { 0.883657f, -0.425547f, -0.195090f },
+ { 0.956195f, -0.218245f, -0.195090f },
+ { 0.923880f, 0.000000f, -0.382683f },
+ { 0.892399f, 0.239118f, -0.382683f },
+ { 0.800103f, 0.461940f, -0.382683f },
+ { 0.653281f, 0.653281f, -0.382683f },
+ { 0.461940f, 0.800103f, -0.382683f },
+ { 0.239118f, 0.892399f, -0.382683f },
+ { -0.000000f, 0.923880f, -0.382683f },
+ { -0.239118f, 0.892399f, -0.382683f },
+ { -0.461940f, 0.800103f, -0.382683f },
+ { -0.653281f, 0.653281f, -0.382683f },
+ { -0.800103f, 0.461940f, -0.382683f },
+ { -0.892399f, 0.239118f, -0.382683f },
+ { -0.923880f, -0.000000f, -0.382683f },
+ { -0.892399f, -0.239118f, -0.382683f },
+ { -0.800103f, -0.461940f, -0.382683f },
+ { -0.653282f, -0.653281f, -0.382683f },
+ { -0.461940f, -0.800103f, -0.382683f },
+ { -0.239118f, -0.892399f, -0.382683f },
+ { 0.000000f, -0.923880f, -0.382683f },
+ { 0.239118f, -0.892399f, -0.382683f },
+ { 0.461940f, -0.800103f, -0.382683f },
+ { 0.653281f, -0.653282f, -0.382683f },
+ { 0.800103f, -0.461940f, -0.382683f },
+ { 0.892399f, -0.239117f, -0.382683f },
+ { 0.831470f, 0.000000f, -0.555570f },
+ { 0.790775f, 0.256938f, -0.555570f },
+ { 0.672673f, 0.488726f, -0.555570f },
+ { 0.488726f, 0.672673f, -0.555570f },
+ { 0.256938f, 0.790775f, -0.555570f },
+ { -0.000000f, 0.831470f, -0.555570f },
+ { -0.256938f, 0.790775f, -0.555570f },
+ { -0.488726f, 0.672673f, -0.555570f },
+ { -0.672673f, 0.488726f, -0.555570f },
+ { -0.790775f, 0.256938f, -0.555570f },
+ { -0.831470f, -0.000000f, -0.555570f },
+ { -0.790775f, -0.256938f, -0.555570f },
+ { -0.672673f, -0.488726f, -0.555570f },
+ { -0.488725f, -0.672673f, -0.555570f },
+ { -0.256938f, -0.790775f, -0.555570f },
+ { 0.000000f, -0.831470f, -0.555570f },
+ { 0.256938f, -0.790775f, -0.555570f },
+ { 0.488725f, -0.672673f, -0.555570f },
+ { 0.672673f, -0.488726f, -0.555570f },
+ { 0.790775f, -0.256938f, -0.555570f },
+ { 0.707107f, 0.000000f, -0.707107f },
+ { 0.653281f, 0.270598f, -0.707107f },
+ { 0.500000f, 0.500000f, -0.707107f },
+ { 0.270598f, 0.653281f, -0.707107f },
+ { -0.000000f, 0.707107f, -0.707107f },
+ { -0.270598f, 0.653282f, -0.707107f },
+ { -0.500000f, 0.500000f, -0.707107f },
+ { -0.653281f, 0.270598f, -0.707107f },
+ { -0.707107f, -0.000000f, -0.707107f },
+ { -0.653281f, -0.270598f, -0.707107f },
+ { -0.500000f, -0.500000f, -0.707107f },
+ { -0.270598f, -0.653281f, -0.707107f },
+ { 0.000000f, -0.707107f, -0.707107f },
+ { 0.270598f, -0.653281f, -0.707107f },
+ { 0.500000f, -0.500000f, -0.707107f },
+ { 0.653282f, -0.270598f, -0.707107f },
+ { 0.555570f, 0.000000f, -0.831470f },
+ { 0.481138f, 0.277785f, -0.831470f },
+ { 0.277785f, 0.481138f, -0.831470f },
+ { -0.000000f, 0.555570f, -0.831470f },
+ { -0.277785f, 0.481138f, -0.831470f },
+ { -0.481138f, 0.277785f, -0.831470f },
+ { -0.555570f, -0.000000f, -0.831470f },
+ { -0.481138f, -0.277785f, -0.831470f },
+ { -0.277785f, -0.481138f, -0.831470f },
+ { 0.000000f, -0.555570f, -0.831470f },
+ { 0.277785f, -0.481138f, -0.831470f },
+ { 0.481138f, -0.277785f, -0.831470f },
+ { 0.382683f, 0.000000f, -0.923880f },
+ { 0.270598f, 0.270598f, -0.923880f },
+ { -0.000000f, 0.382683f, -0.923880f },
+ { -0.270598f, 0.270598f, -0.923880f },
+ { -0.382683f, -0.000000f, -0.923880f },
+ { -0.270598f, -0.270598f, -0.923880f },
+ { 0.000000f, -0.382683f, -0.923880f },
+ { 0.270598f, -0.270598f, -0.923880f },
+ { 0.195090f, 0.000000f, -0.980785f },
+ { -0.000000f, 0.195090f, -0.980785f },
+ { -0.195090f, -0.000000f, -0.980785f },
+ { 0.000000f, -0.195090f, -0.980785f },
+ { 0.980785f, 0.000000f, 0.195090f },
+ { 0.956195f, 0.218245f, 0.195090f },
+ { 0.883657f, 0.425547f, 0.195090f },
+ { 0.766809f, 0.611510f, 0.195090f },
+ { 0.611510f, 0.766809f, 0.195090f },
+ { 0.425547f, 0.883657f, 0.195090f },
+ { 0.218245f, 0.956195f, 0.195090f },
+ { -0.000000f, 0.980785f, 0.195090f },
+ { -0.218245f, 0.956195f, 0.195090f },
+ { -0.425547f, 0.883657f, 0.195090f },
+ { -0.611510f, 0.766809f, 0.195090f },
+ { -0.766809f, 0.611510f, 0.195090f },
+ { -0.883657f, 0.425547f, 0.195090f },
+ { -0.956195f, 0.218245f, 0.195090f },
+ { -0.980785f, -0.000000f, 0.195090f },
+ { -0.956195f, -0.218245f, 0.195090f },
+ { -0.883657f, -0.425547f, 0.195090f },
+ { -0.766809f, -0.611510f, 0.195090f },
+ { -0.611510f, -0.766809f, 0.195090f },
+ { -0.425547f, -0.883657f, 0.195090f },
+ { -0.218245f, -0.956195f, 0.195090f },
+ { 0.000000f, -0.980785f, 0.195090f },
+ { 0.218245f, -0.956195f, 0.195090f },
+ { 0.425547f, -0.883657f, 0.195090f },
+ { 0.611510f, -0.766809f, 0.195090f },
+ { 0.766809f, -0.611510f, 0.195090f },
+ { 0.883657f, -0.425547f, 0.195090f },
+ { 0.956195f, -0.218245f, 0.195090f },
+ { 0.923880f, 0.000000f, 0.382683f },
+ { 0.892399f, 0.239118f, 0.382683f },
+ { 0.800103f, 0.461940f, 0.382683f },
+ { 0.653281f, 0.653281f, 0.382683f },
+ { 0.461940f, 0.800103f, 0.382683f },
+ { 0.239118f, 0.892399f, 0.382683f },
+ { -0.000000f, 0.923880f, 0.382683f },
+ { -0.239118f, 0.892399f, 0.382683f },
+ { -0.461940f, 0.800103f, 0.382683f },
+ { -0.653281f, 0.653281f, 0.382683f },
+ { -0.800103f, 0.461940f, 0.382683f },
+ { -0.892399f, 0.239118f, 0.382683f },
+ { -0.923880f, -0.000000f, 0.382683f },
+ { -0.892399f, -0.239118f, 0.382683f },
+ { -0.800103f, -0.461940f, 0.382683f },
+ { -0.653282f, -0.653281f, 0.382683f },
+ { -0.461940f, -0.800103f, 0.382683f },
+ { -0.239118f, -0.892399f, 0.382683f },
+ { 0.000000f, -0.923880f, 0.382683f },
+ { 0.239118f, -0.892399f, 0.382683f },
+ { 0.461940f, -0.800103f, 0.382683f },
+ { 0.653281f, -0.653282f, 0.382683f },
+ { 0.800103f, -0.461940f, 0.382683f },
+ { 0.892399f, -0.239117f, 0.382683f },
+ { 0.831470f, 0.000000f, 0.555570f },
+ { 0.790775f, 0.256938f, 0.555570f },
+ { 0.672673f, 0.488726f, 0.555570f },
+ { 0.488726f, 0.672673f, 0.555570f },
+ { 0.256938f, 0.790775f, 0.555570f },
+ { -0.000000f, 0.831470f, 0.555570f },
+ { -0.256938f, 0.790775f, 0.555570f },
+ { -0.488726f, 0.672673f, 0.555570f },
+ { -0.672673f, 0.488726f, 0.555570f },
+ { -0.790775f, 0.256938f, 0.555570f },
+ { -0.831470f, -0.000000f, 0.555570f },
+ { -0.790775f, -0.256938f, 0.555570f },
+ { -0.672673f, -0.488726f, 0.555570f },
+ { -0.488725f, -0.672673f, 0.555570f },
+ { -0.256938f, -0.790775f, 0.555570f },
+ { 0.000000f, -0.831470f, 0.555570f },
+ { 0.256938f, -0.790775f, 0.555570f },
+ { 0.488725f, -0.672673f, 0.555570f },
+ { 0.672673f, -0.488726f, 0.555570f },
+ { 0.790775f, -0.256938f, 0.555570f },
+ { 0.707107f, 0.000000f, 0.707107f },
+ { 0.653281f, 0.270598f, 0.707107f },
+ { 0.500000f, 0.500000f, 0.707107f },
+ { 0.270598f, 0.653281f, 0.707107f },
+ { -0.000000f, 0.707107f, 0.707107f },
+ { -0.270598f, 0.653282f, 0.707107f },
+ { -0.500000f, 0.500000f, 0.707107f },
+ { -0.653281f, 0.270598f, 0.707107f },
+ { -0.707107f, -0.000000f, 0.707107f },
+ { -0.653281f, -0.270598f, 0.707107f },
+ { -0.500000f, -0.500000f, 0.707107f },
+ { -0.270598f, -0.653281f, 0.707107f },
+ { 0.000000f, -0.707107f, 0.707107f },
+ { 0.270598f, -0.653281f, 0.707107f },
+ { 0.500000f, -0.500000f, 0.707107f },
+ { 0.653282f, -0.270598f, 0.707107f },
+ { 0.555570f, 0.000000f, 0.831470f },
+ { 0.481138f, 0.277785f, 0.831470f },
+ { 0.277785f, 0.481138f, 0.831470f },
+ { -0.000000f, 0.555570f, 0.831470f },
+ { -0.277785f, 0.481138f, 0.831470f },
+ { -0.481138f, 0.277785f, 0.831470f },
+ { -0.555570f, -0.000000f, 0.831470f },
+ { -0.481138f, -0.277785f, 0.831470f },
+ { -0.277785f, -0.481138f, 0.831470f },
+ { 0.000000f, -0.555570f, 0.831470f },
+ { 0.277785f, -0.481138f, 0.831470f },
+ { 0.481138f, -0.277785f, 0.831470f },
+ { 0.382683f, 0.000000f, 0.923880f },
+ { 0.270598f, 0.270598f, 0.923880f },
+ { -0.000000f, 0.382683f, 0.923880f },
+ { -0.270598f, 0.270598f, 0.923880f },
+ { -0.382683f, -0.000000f, 0.923880f },
+ { -0.270598f, -0.270598f, 0.923880f },
+ { 0.000000f, -0.382683f, 0.923880f },
+ { 0.270598f, -0.270598f, 0.923880f },
+ { 0.195090f, 0.000000f, 0.980785f },
+ { -0.000000f, 0.195090f, 0.980785f },
+ { -0.195090f, -0.000000f, 0.980785f },
+ { 0.000000f, -0.195090f, 0.980785f }
};
#endif // !! MDC_NORMAL_TABLE_INCLUDED
diff --git a/src/3rdparty/assimp/code/MDLDefaultColorMap.h b/src/3rdparty/assimp/code/MDLDefaultColorMap.h
index e40e4b1b0..6db696af0 100644
--- a/src/3rdparty/assimp/code/MDLDefaultColorMap.h
+++ b/src/3rdparty/assimp/code/MDLDefaultColorMap.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,69 +49,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MDL_DEFAULTLMP_H_INC
const unsigned char g_aclrDefaultColorMap[256][3] = {
-{ 0, 0, 0}, { 15, 15, 15}, { 31, 31, 31}, { 47, 47, 47},
-{ 63, 63, 63}, { 75, 75, 75}, { 91, 91, 91}, {107, 107, 107},
-{123, 123, 123}, {139, 139, 139}, {155, 155, 155}, {171, 171, 171},
-{187, 187, 187}, {203, 203, 203}, {219, 219, 219}, {235, 235, 235},
-{ 15, 11, 7}, { 23, 15, 11}, { 31, 23, 11}, { 39, 27, 15},
-{ 47, 35, 19}, { 55, 43, 23}, { 63, 47, 23}, { 75, 55, 27},
-{ 83, 59, 27}, { 91, 67, 31}, { 99, 75, 31}, {107, 83, 31},
-{115, 87, 31}, {123, 95, 35}, {131, 103, 35}, {143, 111, 35},
-{ 11, 11, 15}, { 19, 19, 27}, { 27, 27, 39}, { 39, 39, 51},
-{ 47, 47, 63}, { 55, 55, 75}, { 63, 63, 87}, { 71, 71, 103},
-{ 79, 79, 115}, { 91, 91, 127}, { 99, 99, 139}, {107, 107, 151},
-{115, 115, 163}, {123, 123, 175}, {131, 131, 187}, {139, 139, 203},
-{ 0, 0, 0}, { 7, 7, 0}, { 11, 11, 0}, { 19, 19, 0},
-{ 27, 27, 0}, { 35, 35, 0}, { 43, 43, 7}, { 47, 47, 7},
-{ 55, 55, 7}, { 63, 63, 7}, { 71, 71, 7}, { 75, 75, 11},
-{ 83, 83, 11}, { 91, 91, 11}, { 99, 99, 11}, {107, 107, 15},
-{ 7, 0, 0}, { 15, 0, 0}, { 23, 0, 0}, { 31, 0, 0},
-{ 39, 0, 0}, { 47, 0, 0}, { 55, 0, 0}, { 63, 0, 0},
-{ 71, 0, 0}, { 79, 0, 0}, { 87, 0, 0}, { 95, 0, 0},
-{103, 0, 0}, {111, 0, 0}, {119, 0, 0}, {127, 0, 0},
-{ 19, 19, 0}, { 27, 27, 0}, { 35, 35, 0}, { 47, 43, 0},
-{ 55, 47, 0}, { 67, 55, 0}, { 75, 59, 7}, { 87, 67, 7},
-{ 95, 71, 7}, {107, 75, 11}, {119, 83, 15}, {131, 87, 19},
-{139, 91, 19}, {151, 95, 27}, {163, 99, 31}, {175, 103, 35},
-{ 35, 19, 7}, { 47, 23, 11}, { 59, 31, 15}, { 75, 35, 19},
-{ 87, 43, 23}, { 99, 47, 31}, {115, 55, 35}, {127, 59, 43},
-{143, 67, 51}, {159, 79, 51}, {175, 99, 47}, {191, 119, 47},
-{207, 143, 43}, {223, 171, 39}, {239, 203, 31}, {255, 243, 27},
-{ 11, 7, 0}, { 27, 19, 0}, { 43, 35, 15}, { 55, 43, 19},
-{ 71, 51, 27}, { 83, 55, 35}, { 99, 63, 43}, {111, 71, 51},
-{127, 83, 63}, {139, 95, 71}, {155, 107, 83}, {167, 123, 95},
-{183, 135, 107}, {195, 147, 123}, {211, 163, 139}, {227, 179, 151},
-{171, 139, 163}, {159, 127, 151}, {147, 115, 135}, {139, 103, 123},
-{127, 91, 111}, {119, 83, 99}, {107, 75, 87}, { 95, 63, 75},
-{ 87, 55, 67}, { 75, 47, 55}, { 67, 39, 47}, { 55, 31, 35},
-{ 43, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7},
-{187, 115, 159}, {175, 107, 143}, {163, 95, 131}, {151, 87, 119},
-{139, 79, 107}, {127, 75, 95}, {115, 67, 83}, {107, 59, 75},
-{ 95, 51, 63}, { 83, 43, 55}, { 71, 35, 43}, { 59, 31, 35},
-{ 47, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7},
-{219, 195, 187}, {203, 179, 167}, {191, 163, 155}, {175, 151, 139},
-{163, 135, 123}, {151, 123, 111}, {135, 111, 95}, {123, 99, 83},
-{107, 87, 71}, { 95, 75, 59}, { 83, 63, 51}, { 67, 51, 39},
-{ 55, 43, 31}, { 39, 31, 23}, { 27, 19, 15}, { 15, 11, 7},
-{111, 131, 123}, {103, 123, 111}, { 95, 115, 103}, { 87, 107, 95},
-{ 79, 99, 87}, { 71, 91, 79}, { 63, 83, 71}, { 55, 75, 63},
-{ 47, 67, 55}, { 43, 59, 47}, { 35, 51, 39}, { 31, 43, 31},
-{ 23, 35, 23}, { 15, 27, 19}, { 11, 19, 11}, { 7, 11, 7},
-{255, 243, 27}, {239, 223, 23}, {219, 203, 19}, {203, 183, 15},
-{187, 167, 15}, {171, 151, 11}, {155, 131, 7}, {139, 115, 7},
-{123, 99, 7}, {107, 83, 0}, { 91, 71, 0}, { 75, 55, 0},
-{ 59, 43, 0}, { 43, 31, 0}, { 27, 15, 0}, { 11, 7, 0},
-{ 0, 0, 255}, { 11, 11, 239}, { 19, 19, 223}, { 27, 27, 207},
-{ 35, 35, 191}, { 43, 43, 175}, { 47, 47, 159}, { 47, 47, 143},
-{ 47, 47, 127}, { 47, 47, 111}, { 47, 47, 95}, { 43, 43, 79},
-{ 35, 35, 63}, { 27, 27, 47}, { 19, 19, 31}, { 11, 11, 15},
-{ 43, 0, 0}, { 59, 0, 0}, { 75, 7, 0}, { 95, 7, 0},
-{111, 15, 0}, {127, 23, 7}, {147, 31, 7}, {163, 39, 11},
-{183, 51, 15}, {195, 75, 27}, {207, 99, 43}, {219, 127, 59},
-{227, 151, 79}, {231, 171, 95}, {239, 191, 119}, {247, 211, 139},
-{167, 123, 59}, {183, 155, 55}, {199, 195, 55}, {231, 227, 87},
-{127, 191, 255}, {171, 231, 255}, {215, 255, 255}, {103, 0, 0},
-{139, 0, 0}, {179, 0, 0}, {215, 0, 0}, {255, 0, 0},
+{ 0, 0, 0}, { 15, 15, 15}, { 31, 31, 31}, { 47, 47, 47},
+{ 63, 63, 63}, { 75, 75, 75}, { 91, 91, 91}, {107, 107, 107},
+{123, 123, 123}, {139, 139, 139}, {155, 155, 155}, {171, 171, 171},
+{187, 187, 187}, {203, 203, 203}, {219, 219, 219}, {235, 235, 235},
+{ 15, 11, 7}, { 23, 15, 11}, { 31, 23, 11}, { 39, 27, 15},
+{ 47, 35, 19}, { 55, 43, 23}, { 63, 47, 23}, { 75, 55, 27},
+{ 83, 59, 27}, { 91, 67, 31}, { 99, 75, 31}, {107, 83, 31},
+{115, 87, 31}, {123, 95, 35}, {131, 103, 35}, {143, 111, 35},
+{ 11, 11, 15}, { 19, 19, 27}, { 27, 27, 39}, { 39, 39, 51},
+{ 47, 47, 63}, { 55, 55, 75}, { 63, 63, 87}, { 71, 71, 103},
+{ 79, 79, 115}, { 91, 91, 127}, { 99, 99, 139}, {107, 107, 151},
+{115, 115, 163}, {123, 123, 175}, {131, 131, 187}, {139, 139, 203},
+{ 0, 0, 0}, { 7, 7, 0}, { 11, 11, 0}, { 19, 19, 0},
+{ 27, 27, 0}, { 35, 35, 0}, { 43, 43, 7}, { 47, 47, 7},
+{ 55, 55, 7}, { 63, 63, 7}, { 71, 71, 7}, { 75, 75, 11},
+{ 83, 83, 11}, { 91, 91, 11}, { 99, 99, 11}, {107, 107, 15},
+{ 7, 0, 0}, { 15, 0, 0}, { 23, 0, 0}, { 31, 0, 0},
+{ 39, 0, 0}, { 47, 0, 0}, { 55, 0, 0}, { 63, 0, 0},
+{ 71, 0, 0}, { 79, 0, 0}, { 87, 0, 0}, { 95, 0, 0},
+{103, 0, 0}, {111, 0, 0}, {119, 0, 0}, {127, 0, 0},
+{ 19, 19, 0}, { 27, 27, 0}, { 35, 35, 0}, { 47, 43, 0},
+{ 55, 47, 0}, { 67, 55, 0}, { 75, 59, 7}, { 87, 67, 7},
+{ 95, 71, 7}, {107, 75, 11}, {119, 83, 15}, {131, 87, 19},
+{139, 91, 19}, {151, 95, 27}, {163, 99, 31}, {175, 103, 35},
+{ 35, 19, 7}, { 47, 23, 11}, { 59, 31, 15}, { 75, 35, 19},
+{ 87, 43, 23}, { 99, 47, 31}, {115, 55, 35}, {127, 59, 43},
+{143, 67, 51}, {159, 79, 51}, {175, 99, 47}, {191, 119, 47},
+{207, 143, 43}, {223, 171, 39}, {239, 203, 31}, {255, 243, 27},
+{ 11, 7, 0}, { 27, 19, 0}, { 43, 35, 15}, { 55, 43, 19},
+{ 71, 51, 27}, { 83, 55, 35}, { 99, 63, 43}, {111, 71, 51},
+{127, 83, 63}, {139, 95, 71}, {155, 107, 83}, {167, 123, 95},
+{183, 135, 107}, {195, 147, 123}, {211, 163, 139}, {227, 179, 151},
+{171, 139, 163}, {159, 127, 151}, {147, 115, 135}, {139, 103, 123},
+{127, 91, 111}, {119, 83, 99}, {107, 75, 87}, { 95, 63, 75},
+{ 87, 55, 67}, { 75, 47, 55}, { 67, 39, 47}, { 55, 31, 35},
+{ 43, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7},
+{187, 115, 159}, {175, 107, 143}, {163, 95, 131}, {151, 87, 119},
+{139, 79, 107}, {127, 75, 95}, {115, 67, 83}, {107, 59, 75},
+{ 95, 51, 63}, { 83, 43, 55}, { 71, 35, 43}, { 59, 31, 35},
+{ 47, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7},
+{219, 195, 187}, {203, 179, 167}, {191, 163, 155}, {175, 151, 139},
+{163, 135, 123}, {151, 123, 111}, {135, 111, 95}, {123, 99, 83},
+{107, 87, 71}, { 95, 75, 59}, { 83, 63, 51}, { 67, 51, 39},
+{ 55, 43, 31}, { 39, 31, 23}, { 27, 19, 15}, { 15, 11, 7},
+{111, 131, 123}, {103, 123, 111}, { 95, 115, 103}, { 87, 107, 95},
+{ 79, 99, 87}, { 71, 91, 79}, { 63, 83, 71}, { 55, 75, 63},
+{ 47, 67, 55}, { 43, 59, 47}, { 35, 51, 39}, { 31, 43, 31},
+{ 23, 35, 23}, { 15, 27, 19}, { 11, 19, 11}, { 7, 11, 7},
+{255, 243, 27}, {239, 223, 23}, {219, 203, 19}, {203, 183, 15},
+{187, 167, 15}, {171, 151, 11}, {155, 131, 7}, {139, 115, 7},
+{123, 99, 7}, {107, 83, 0}, { 91, 71, 0}, { 75, 55, 0},
+{ 59, 43, 0}, { 43, 31, 0}, { 27, 15, 0}, { 11, 7, 0},
+{ 0, 0, 255}, { 11, 11, 239}, { 19, 19, 223}, { 27, 27, 207},
+{ 35, 35, 191}, { 43, 43, 175}, { 47, 47, 159}, { 47, 47, 143},
+{ 47, 47, 127}, { 47, 47, 111}, { 47, 47, 95}, { 43, 43, 79},
+{ 35, 35, 63}, { 27, 27, 47}, { 19, 19, 31}, { 11, 11, 15},
+{ 43, 0, 0}, { 59, 0, 0}, { 75, 7, 0}, { 95, 7, 0},
+{111, 15, 0}, {127, 23, 7}, {147, 31, 7}, {163, 39, 11},
+{183, 51, 15}, {195, 75, 27}, {207, 99, 43}, {219, 127, 59},
+{227, 151, 79}, {231, 171, 95}, {239, 191, 119}, {247, 211, 139},
+{167, 123, 59}, {183, 155, 55}, {199, 195, 55}, {231, 227, 87},
+{127, 191, 255}, {171, 231, 255}, {215, 255, 255}, {103, 0, 0},
+{139, 0, 0}, {179, 0, 0}, {215, 0, 0}, {255, 0, 0},
{255, 243, 147}, {255, 247, 199}, {255, 255, 255}, {159, 91, 83} };
diff --git a/src/3rdparty/assimp/code/MDLFileData.h b/src/3rdparty/assimp/code/MDLFileData.h
index 10799ba6b..536bf082a 100644
--- a/src/3rdparty/assimp/code/MDLFileData.h
+++ b/src/3rdparty/assimp/code/MDLFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* @file MDLFileData.h
- * @brief Definition of in-memory structures for the MDL file format.
+ * @brief Definition of in-memory structures for the MDL file format.
*
* The specification has been taken from various sources on the internet.
* - http://tfc.duke.free.fr/coding/mdl-specs-en.html
@@ -52,59 +52,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MDLFILEHELPER_H_INC
#define AI_MDLFILEHELPER_H_INC
+#include "ByteSwapper.h"
+#include "./../include/assimp/anim.h"
+#include "./../include/assimp/mesh.h"
#include "./../include/assimp/Compiler/pushpack1.h"
+#include <stdint.h>
+#include <vector>
-namespace Assimp {
-namespace MDL {
+struct aiMaterial;
+
+namespace Assimp {
+namespace MDL {
// -------------------------------------------------------------------------------------
// to make it easier for us, we test the magic word against both "endianesses"
// magic bytes used in Quake 1 MDL meshes
-#define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO")
-#define AI_MDL_MAGIC_NUMBER_LE AI_MAKE_MAGIC("OPDI")
+#define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO")
+#define AI_MDL_MAGIC_NUMBER_LE AI_MAKE_MAGIC("OPDI")
// magic bytes used in GameStudio A<very low> MDL meshes
-#define AI_MDL_MAGIC_NUMBER_BE_GS3 AI_MAKE_MAGIC("MDL2")
-#define AI_MDL_MAGIC_NUMBER_LE_GS3 AI_MAKE_MAGIC("2LDM")
+#define AI_MDL_MAGIC_NUMBER_BE_GS3 AI_MAKE_MAGIC("MDL2")
+#define AI_MDL_MAGIC_NUMBER_LE_GS3 AI_MAKE_MAGIC("2LDM")
// magic bytes used in GameStudio A4 MDL meshes
-#define AI_MDL_MAGIC_NUMBER_BE_GS4 AI_MAKE_MAGIC("MDL3")
-#define AI_MDL_MAGIC_NUMBER_LE_GS4 AI_MAKE_MAGIC("3LDM")
+#define AI_MDL_MAGIC_NUMBER_BE_GS4 AI_MAKE_MAGIC("MDL3")
+#define AI_MDL_MAGIC_NUMBER_LE_GS4 AI_MAKE_MAGIC("3LDM")
// magic bytes used in GameStudio A5+ MDL meshes
-#define AI_MDL_MAGIC_NUMBER_BE_GS5a AI_MAKE_MAGIC("MDL4")
-#define AI_MDL_MAGIC_NUMBER_LE_GS5a AI_MAKE_MAGIC("4LDM")
-#define AI_MDL_MAGIC_NUMBER_BE_GS5b AI_MAKE_MAGIC("MDL5")
-#define AI_MDL_MAGIC_NUMBER_LE_GS5b AI_MAKE_MAGIC("5LDM")
+#define AI_MDL_MAGIC_NUMBER_BE_GS5a AI_MAKE_MAGIC("MDL4")
+#define AI_MDL_MAGIC_NUMBER_LE_GS5a AI_MAKE_MAGIC("4LDM")
+#define AI_MDL_MAGIC_NUMBER_BE_GS5b AI_MAKE_MAGIC("MDL5")
+#define AI_MDL_MAGIC_NUMBER_LE_GS5b AI_MAKE_MAGIC("5LDM")
// magic bytes used in GameStudio A7+ MDL meshes
-#define AI_MDL_MAGIC_NUMBER_BE_GS7 AI_MAKE_MAGIC("MDL7")
-#define AI_MDL_MAGIC_NUMBER_LE_GS7 AI_MAKE_MAGIC("7LDM")
+#define AI_MDL_MAGIC_NUMBER_BE_GS7 AI_MAKE_MAGIC("MDL7")
+#define AI_MDL_MAGIC_NUMBER_LE_GS7 AI_MAKE_MAGIC("7LDM")
// common limitations for Quake1 meshes. The loader does not check them,
// (however it warns) but models should not exceed these limits.
#if (!defined AI_MDL_VERSION)
-# define AI_MDL_VERSION 6
+# define AI_MDL_VERSION 6
#endif
#if (!defined AI_MDL_MAX_FRAMES)
-# define AI_MDL_MAX_FRAMES 256
+# define AI_MDL_MAX_FRAMES 256
#endif
#if (!defined AI_MDL_MAX_UVS)
-# define AI_MDL_MAX_UVS 1024
+# define AI_MDL_MAX_UVS 1024
#endif
#if (!defined AI_MDL_MAX_VERTS)
-# define AI_MDL_MAX_VERTS 1024
+# define AI_MDL_MAX_VERTS 1024
#endif
#if (!defined AI_MDL_MAX_TRIANGLES)
-# define AI_MDL_MAX_TRIANGLES 2048
+# define AI_MDL_MAX_TRIANGLES 2048
#endif
// material key that is set for dummy materials that are
// just referencing another material
#if (!defined AI_MDL7_REFERRER_MATERIAL)
-# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&",0,0
+# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&",0,0
#endif
// -------------------------------------------------------------------------------------
@@ -113,51 +120,51 @@ namespace MDL {
*/
struct Header
{
- //! magic number: "IDPO"
- uint32_t ident;
+ //! magic number: "IDPO"
+ uint32_t ident;
+
+ //! version number: 6
+ int32_t version;
- //! version number: 6
- int32_t version;
+ //! scale factors for each axis
+ aiVector3D scale;
- //! scale factors for each axis
- aiVector3D scale;
+ //! translation factors for each axis
+ aiVector3D translate;
- //! translation factors for each axis
- aiVector3D translate;
+ //! bounding radius of the mesh
+ float boundingradius;
- //! bounding radius of the mesh
- float boundingradius;
-
- //! Position of the viewer's exe. Ignored
- aiVector3D vEyePos;
+ //! Position of the viewer's exe. Ignored
+ aiVector3D vEyePos;
- //! Number of textures
- int32_t num_skins;
+ //! Number of textures
+ int32_t num_skins;
- //! Texture width in pixels
- int32_t skinwidth;
+ //! Texture width in pixels
+ int32_t skinwidth;
- //! Texture height in pixels
- int32_t skinheight;
+ //! Texture height in pixels
+ int32_t skinheight;
- //! Number of vertices contained in the file
- int32_t num_verts;
+ //! Number of vertices contained in the file
+ int32_t num_verts;
- //! Number of triangles contained in the file
- int32_t num_tris;
+ //! Number of triangles contained in the file
+ int32_t num_tris;
- //! Number of frames contained in the file
- int32_t num_frames;
+ //! Number of frames contained in the file
+ int32_t num_frames;
- //! 0 = synchron, 1 = random . Ignored
- //! (MDLn formats: number of texture coordinates)
- int32_t synctype;
+ //! 0 = synchron, 1 = random . Ignored
+ //! (MDLn formats: number of texture coordinates)
+ int32_t synctype;
- //! State flag
- int32_t flags;
+ //! State flag
+ int32_t flags;
- //! Could be the total size of the file (and not a float)
- float size;
+ //! Could be the total size of the file (and not a float)
+ float size;
} PACK_STRUCT;
@@ -167,57 +174,57 @@ struct Header
*/
struct Header_MDL7
{
- //! magic number: "MDL7"
- char ident[4];
+ //! magic number: "MDL7"
+ char ident[4];
- //! Version number. Ignored
- int32_t version;
+ //! Version number. Ignored
+ int32_t version;
- //! Number of bones in file
- uint32_t bones_num;
+ //! Number of bones in file
+ uint32_t bones_num;
- //! Number of groups in file
- uint32_t groups_num;
+ //! Number of groups in file
+ uint32_t groups_num;
- //! Size of data in the file
- uint32_t data_size;
+ //! Size of data in the file
+ uint32_t data_size;
- //! Ignored. Used to store entity specific information
- int32_t entlump_size;
+ //! Ignored. Used to store entity specific information
+ int32_t entlump_size;
- //! Ignored. Used to store MED related data
- int32_t medlump_size;
+ //! Ignored. Used to store MED related data
+ int32_t medlump_size;
- //! Size of the Bone_MDL7 data structure used in the file
- uint16_t bone_stc_size;
+ //! Size of the Bone_MDL7 data structure used in the file
+ uint16_t bone_stc_size;
- //! Size of the Skin_MDL 7 data structure used in the file
- uint16_t skin_stc_size;
+ //! Size of the Skin_MDL 7 data structure used in the file
+ uint16_t skin_stc_size;
- //! Size of a single color (e.g. in a material)
- uint16_t colorvalue_stc_size;
+ //! Size of a single color (e.g. in a material)
+ uint16_t colorvalue_stc_size;
- //! Size of the Material_MDL7 data structure used in the file
- uint16_t material_stc_size;
+ //! Size of the Material_MDL7 data structure used in the file
+ uint16_t material_stc_size;
- //! Size of a texture coordinate set in the file
- uint16_t skinpoint_stc_size;
+ //! Size of a texture coordinate set in the file
+ uint16_t skinpoint_stc_size;
- //! Size of a triangle in the file
- uint16_t triangle_stc_size;
+ //! Size of a triangle in the file
+ uint16_t triangle_stc_size;
- //! Size of a normal vertex in the file
- uint16_t mainvertex_stc_size;
+ //! Size of a normal vertex in the file
+ uint16_t mainvertex_stc_size;
- //! Size of a per-frame animated vertex in the file
- //! (this is not supported)
- uint16_t framevertex_stc_size;
+ //! Size of a per-frame animated vertex in the file
+ //! (this is not supported)
+ uint16_t framevertex_stc_size;
- //! Size of a bone animation matrix
- uint16_t bonetrans_stc_size;
+ //! Size of a bone animation matrix
+ uint16_t bonetrans_stc_size;
- //! Size of the Frame_MDL7 data structure used in the file
- uint16_t frame_stc_size;
+ //! Size of the Frame_MDL7 data structure used in the file
+ uint16_t frame_stc_size;
} PACK_STRUCT;
@@ -227,33 +234,33 @@ struct Header_MDL7
*/
struct Bone_MDL7
{
- //! Index of the parent bone of *this* bone. 0xffff means:
- //! "hey, I have no parent, I'm an orphan"
- uint16_t parent_index;
- uint8_t _unused_[2];
+ //! Index of the parent bone of *this* bone. 0xffff means:
+ //! "hey, I have no parent, I'm an orphan"
+ uint16_t parent_index;
+ uint8_t _unused_[2];
- //! Relative position of the bone (relative to the
- //! parent bone)
- float x,y,z;
+ //! Relative position of the bone (relative to the
+ //! parent bone)
+ float x,y,z;
- //! Optional name of the bone
- char name[1 /* DUMMY SIZE */];
+ //! Optional name of the bone
+ char name[1 /* DUMMY SIZE */];
} PACK_STRUCT;
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
-# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
+# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS)
-# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS (16 + 32)
+# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS (16 + 32)
#endif
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE)
-# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE (16)
+# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE (16)
#endif
#if (!defined AI_MDL7_MAX_GROUPNAMESIZE)
-# define AI_MDL7_MAX_GROUPNAMESIZE 16
+# define AI_MDL7_MAX_GROUPNAMESIZE 16
#endif // ! AI_MDL7_MAX_GROUPNAMESIZE
// -------------------------------------------------------------------------------------
@@ -262,40 +269,40 @@ struct Bone_MDL7
*/
struct Group_MDL7
{
- //! = '1' -> triangle based Mesh
- unsigned char typ;
+ //! = '1' -> triangle based Mesh
+ unsigned char typ;
- int8_t deformers;
- int8_t max_weights;
- int8_t _unused_;
+ int8_t deformers;
+ int8_t max_weights;
+ int8_t _unused_;
- //! size of data for this group in bytes ( MD7_GROUP stc. included).
- int32_t groupdata_size;
- char name[AI_MDL7_MAX_GROUPNAMESIZE];
+ //! size of data for this group in bytes ( MD7_GROUP stc. included).
+ int32_t groupdata_size;
+ char name[AI_MDL7_MAX_GROUPNAMESIZE];
- //! Number of skins
- int32_t numskins;
+ //! Number of skins
+ int32_t numskins;
- //! Number of texture coordinates
- int32_t num_stpts;
+ //! Number of texture coordinates
+ int32_t num_stpts;
- //! Number of triangles
- int32_t numtris;
+ //! Number of triangles
+ int32_t numtris;
- //! Number of vertices
- int32_t numverts;
+ //! Number of vertices
+ int32_t numverts;
- //! Number of frames
- int32_t numframes;
+ //! Number of frames
+ int32_t numframes;
} PACK_STRUCT;
-#define AI_MDL7_SKINTYPE_MIPFLAG 0x08
-#define AI_MDL7_SKINTYPE_MATERIAL 0x10
-#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20
-#define AI_MDL7_SKINTYPE_RGBFLAG 0x80
+#define AI_MDL7_SKINTYPE_MIPFLAG 0x08
+#define AI_MDL7_SKINTYPE_MATERIAL 0x10
+#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20
+#define AI_MDL7_SKINTYPE_RGBFLAG 0x80
#if (!defined AI_MDL7_MAX_BONENAMESIZE)
-# define AI_MDL7_MAX_BONENAMESIZE 20
+# define AI_MDL7_MAX_BONENAMESIZE 20
#endif // !! AI_MDL7_MAX_BONENAMESIZE
// -------------------------------------------------------------------------------------
@@ -304,12 +311,12 @@ struct Group_MDL7
*/
struct Deformer_MDL7
{
- int8_t deformer_version; // 0
- int8_t deformer_typ; // 0 - bones
- int8_t _unused_[2];
- int32_t group_index;
- int32_t elements;
- int32_t deformerdata_size;
+ int8_t deformer_version; // 0
+ int8_t deformer_typ; // 0 - bones
+ int8_t _unused_[2];
+ int32_t group_index;
+ int32_t elements;
+ int32_t deformerdata_size;
} PACK_STRUCT;
@@ -319,10 +326,10 @@ struct Deformer_MDL7
*/
struct DeformerElement_MDL7
{
- //! bei deformer_typ==0 (==bones) element_index == bone index
- int32_t element_index;
- char element_name[AI_MDL7_MAX_BONENAMESIZE];
- int32_t weights;
+ //! bei deformer_typ==0 (==bones) element_index == bone index
+ int32_t element_index;
+ char element_name[AI_MDL7_MAX_BONENAMESIZE];
+ int32_t weights;
} PACK_STRUCT;
@@ -332,9 +339,9 @@ struct DeformerElement_MDL7
*/
struct DeformerWeight_MDL7
{
- //! for deformer_typ==0 (==bones) index == vertex index
- int32_t index;
- float weight;
+ //! for deformer_typ==0 (==bones) index == vertex index
+ int32_t index;
+ float weight;
} PACK_STRUCT;
@@ -347,7 +354,7 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
*/
struct ColorValue_MDL7
{
- float r,g,b,a;
+ float r,g,b,a;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -356,20 +363,20 @@ struct ColorValue_MDL7
*/
struct Material_MDL7
{
- //! Diffuse base color of the material
- ColorValue_MDL7 Diffuse;
+ //! Diffuse base color of the material
+ ColorValue_MDL7 Diffuse;
- //! Ambient base color of the material
- ColorValue_MDL7 Ambient;
+ //! Ambient base color of the material
+ ColorValue_MDL7 Ambient;
- //! Specular base color of the material
- ColorValue_MDL7 Specular;
+ //! Specular base color of the material
+ ColorValue_MDL7 Specular;
- //! Emissive base color of the material
- ColorValue_MDL7 Emissive;
+ //! Emissive base color of the material
+ ColorValue_MDL7 Emissive;
- //! Phong power
- float Power;
+ //! Phong power
+ float Power;
} PACK_STRUCT;
@@ -379,21 +386,21 @@ struct Material_MDL7
*/
struct Skin
{
- //! 0 = single (Skin), 1 = group (GroupSkin)
- //! For MDL3-5: Defines the type of the skin and there
- //! fore the size of the data to skip:
- //-------------------------------------------------------
- //! 2 for 565 RGB,
- //! 3 for 4444 ARGB,
- //! 10 for 565 mipmapped,
- //! 11 for 4444 mipmapped (bpp = 2),
- //! 12 for 888 RGB mipmapped (bpp = 3),
- //! 13 for 8888 ARGB mipmapped (bpp = 4)
- //-------------------------------------------------------
- int32_t group;
-
- //! Texture data
- uint8_t *data;
+ //! 0 = single (Skin), 1 = group (GroupSkin)
+ //! For MDL3-5: Defines the type of the skin and there
+ //! fore the size of the data to skip:
+ //-------------------------------------------------------
+ //! 2 for 565 RGB,
+ //! 3 for 4444 ARGB,
+ //! 10 for 565 mipmapped,
+ //! 11 for 4444 mipmapped (bpp = 2),
+ //! 12 for 888 RGB mipmapped (bpp = 3),
+ //! 13 for 8888 ARGB mipmapped (bpp = 4)
+ //-------------------------------------------------------
+ int32_t group;
+
+ //! Texture data
+ uint8_t *data;
} PACK_STRUCT;
@@ -404,13 +411,13 @@ struct Skin
*/
struct Skin_MDL5
{
- int32_t size, width, height;
- uint8_t *data;
+ int32_t size, width, height;
+ uint8_t *data;
} PACK_STRUCT;
// maximum length of texture file name
#if (!defined AI_MDL7_MAX_TEXNAMESIZE)
-# define AI_MDL7_MAX_TEXNAMESIZE 0x10
+# define AI_MDL7_MAX_TEXNAMESIZE 0x10
#endif
// ---------------------------------------------------------------------------
@@ -419,11 +426,11 @@ struct Skin_MDL5
*/
struct Skin_MDL7
{
- uint8_t typ;
- int8_t _unused_[3];
- int32_t width;
- int32_t height;
- char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
+ uint8_t typ;
+ int8_t _unused_[3];
+ int32_t width;
+ int32_t height;
+ char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -432,9 +439,9 @@ struct Skin_MDL7
*/
struct RGB565
{
- uint16_t r : 5;
- uint16_t g : 6;
- uint16_t b : 5;
+ uint16_t r : 5;
+ uint16_t g : 6;
+ uint16_t b : 5;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -443,10 +450,10 @@ struct RGB565
*/
struct ARGB4
{
- uint16_t a : 4;
- uint16_t r : 4;
- uint16_t g : 4;
- uint16_t b : 4;
+ uint16_t a : 4;
+ uint16_t r : 4;
+ uint16_t g : 4;
+ uint16_t b : 4;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -455,17 +462,17 @@ struct ARGB4
*/
struct GroupSkin
{
- //! 0 = single (Skin), 1 = group (GroupSkin)
- int32_t group;
+ //! 0 = single (Skin), 1 = group (GroupSkin)
+ int32_t group;
- //! Number of images
- int32_t nb;
+ //! Number of images
+ int32_t nb;
- //! Time for each image
- float *time;
+ //! Time for each image
+ float *time;
- //! Data of each image
- uint8_t **data;
+ //! Data of each image
+ uint8_t **data;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -474,14 +481,14 @@ struct GroupSkin
*/
struct TexCoord
{
- //! Is the vertex on the noundary between front and back piece?
- int32_t onseam;
+ //! Is the vertex on the noundary between front and back piece?
+ int32_t onseam;
- //! Texture coordinate in the tx direction
- int32_t s;
+ //! Texture coordinate in the tx direction
+ int32_t s;
- //! Texture coordinate in the ty direction
- int32_t t;
+ //! Texture coordinate in the ty direction
+ int32_t t;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -490,11 +497,11 @@ struct TexCoord
*/
struct TexCoord_MDL3
{
- //! position, horizontally in range 0..skinwidth-1
- int16_t u;
+ //! position, horizontally in range 0..skinwidth-1
+ int16_t u;
- //! position, vertically in range 0..skinheight-1
- int16_t v;
+ //! position, vertically in range 0..skinheight-1
+ int16_t v;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -503,11 +510,11 @@ struct TexCoord_MDL3
*/
struct TexCoord_MDL7
{
- //! position, horizontally in range 0..1
- float u;
+ //! position, horizontally in range 0..1
+ float u;
- //! position, vertically in range 0..1
- float v;
+ //! position, vertically in range 0..1
+ float v;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -519,11 +526,11 @@ struct TexCoord_MDL7
*/
struct SkinSet_MDL7
{
- //! Index into the UV coordinate list
- uint16_t st_index[3]; // size 6
+ //! Index into the UV coordinate list
+ uint16_t st_index[3]; // size 6
- //! Material index
- int32_t material; // size 4
+ //! Material index
+ int32_t material; // size 4
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -532,11 +539,11 @@ struct SkinSet_MDL7
*/
struct Triangle
{
- //! 0 = backface, 1 = frontface
- int32_t facesfront;
+ //! 0 = backface, 1 = frontface
+ int32_t facesfront;
- //! Vertex indices
- int32_t vertex[3];
+ //! Vertex indices
+ int32_t vertex[3];
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -545,11 +552,11 @@ struct Triangle
*/
struct Triangle_MDL3
{
- //! Index of 3 3D vertices in range 0..numverts
- uint16_t index_xyz[3];
+ //! Index of 3 3D vertices in range 0..numverts
+ uint16_t index_xyz[3];
- //! Index of 3 skin vertices in range 0..numskinverts
- uint16_t index_uv[3];
+ //! Index of 3 skin vertices in range 0..numskinverts
+ uint16_t index_uv[3];
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -558,29 +565,29 @@ struct Triangle_MDL3
*/
struct Triangle_MDL7
{
- //! Vertex indices
- uint16_t v_index[3]; // size 6
+ //! Vertex indices
+ uint16_t v_index[3]; // size 6
- //! Two skinsets. The second will be used for multi-texturing
- SkinSet_MDL7 skinsets[2];
-} PACK_STRUCT;
+ //! Two skinsets. The second will be used for multi-texturing
+ SkinSet_MDL7 skinsets[2];
+} PACK_STRUCT;
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
-# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
-#endif
+# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
+#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX)
-# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX (6+sizeof(SkinSet_MDL7))
-#endif
+# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX (6+sizeof(SkinSet_MDL7))
+#endif
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV)
-# define AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV (6+2*sizeof(SkinSet_MDL7))
-#endif
+# define AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV (6+2*sizeof(SkinSet_MDL7))
+#endif
// Helper constants for Triangle::facesfront
#if (!defined AI_MDL_BACKFACE)
-# define AI_MDL_BACKFACE 0x0
+# define AI_MDL_BACKFACE 0x0
#endif
#if (!defined AI_MDL_FRONTFACE)
-# define AI_MDL_FRONTFACE 0x1
+# define AI_MDL_FRONTFACE 0x1
#endif
// -------------------------------------------------------------------------------------
@@ -589,21 +596,21 @@ struct Triangle_MDL7
*/
struct Vertex
{
- uint8_t v[3];
- uint8_t normalIndex;
+ uint8_t v[3];
+ uint8_t normalIndex;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
struct Vertex_MDL4
{
- uint16_t v[3];
- uint8_t normalIndex;
- uint8_t unused;
+ uint16_t v[3];
+ uint8_t normalIndex;
+ uint8_t unused;
} PACK_STRUCT;
-#define AI_MDL7_FRAMEVERTEX120503_STCSIZE 16
-#define AI_MDL7_FRAMEVERTEX030305_STCSIZE 26
+#define AI_MDL7_FRAMEVERTEX120503_STCSIZE 16
+#define AI_MDL7_FRAMEVERTEX030305_STCSIZE 26
// -------------------------------------------------------------------------------------
/** \struct Vertex_MDL7
@@ -611,12 +618,12 @@ struct Vertex_MDL4
*/
struct Vertex_MDL7
{
- float x,y,z;
- uint16_t vertindex; // = bone index
- union {
- uint8_t norm162index;
- float norm[3];
- };
+ float x,y,z;
+ uint16_t vertindex; // = bone index
+ union {
+ uint8_t norm162index;
+ float norm[3];
+ };
} PACK_STRUCT;
@@ -626,19 +633,19 @@ struct Vertex_MDL7
*/
struct BoneTransform_MDL7
{
- //! 4*3
- float m [4*4];
+ //! 4*3
+ float m [4*4];
- //! the index of this vertex, 0.. header::bones_num - 1
- uint16_t bone_index;
+ //! the index of this vertex, 0.. header::bones_num - 1
+ uint16_t bone_index;
- //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
- //! THIS STUPID FILE FORMAT!
- int8_t _unused_[2];
+ //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
+ //! THIS STUPID FILE FORMAT!
+ int8_t _unused_[2];
} PACK_STRUCT;
-#define AI_MDL7_MAX_FRAMENAMESIZE 16
+#define AI_MDL7_MAX_FRAMENAMESIZE 16
// -------------------------------------------------------------------------------------
@@ -647,9 +654,9 @@ struct BoneTransform_MDL7
*/
struct Frame_MDL7
{
- char frame_name[AI_MDL7_MAX_FRAMENAMESIZE];
- uint32_t vertices_count;
- uint32_t transmatrix_count;
+ char frame_name[AI_MDL7_MAX_FRAMENAMESIZE];
+ uint32_t vertices_count;
+ uint32_t transmatrix_count;
};
@@ -659,17 +666,17 @@ struct Frame_MDL7
*/
struct SimpleFrame
{
- //! Minimum vertex of the bounding box
- Vertex bboxmin;
+ //! Minimum vertex of the bounding box
+ Vertex bboxmin;
- //! Maximum vertex of the bounding box
- Vertex bboxmax;
+ //! Maximum vertex of the bounding box
+ Vertex bboxmax;
- //! Name of the frame
- char name[16];
+ //! Name of the frame
+ char name[16];
- //! Vertex list of the frame
- Vertex *verts;
+ //! Vertex list of the frame
+ Vertex *verts;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -678,28 +685,28 @@ struct SimpleFrame
*/
struct Frame
{
- //! 0 = simple frame, !0 = group frame
- int32_t type;
+ //! 0 = simple frame, !0 = group frame
+ int32_t type;
- //! Frame data
- SimpleFrame frame;
+ //! Frame data
+ SimpleFrame frame;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
struct SimpleFrame_MDLn_SP
{
- //! Minimum vertex of the bounding box
- Vertex_MDL4 bboxmin;
+ //! Minimum vertex of the bounding box
+ Vertex_MDL4 bboxmin;
- //! Maximum vertex of the bounding box
- Vertex_MDL4 bboxmax;
+ //! Maximum vertex of the bounding box
+ Vertex_MDL4 bboxmax;
- //! Name of the frame
- char name[16];
+ //! Name of the frame
+ char name[16];
- //! Vertex list of the frame
- Vertex_MDL4 *verts;
+ //! Vertex list of the frame
+ Vertex_MDL4 *verts;
} PACK_STRUCT;
// -------------------------------------------------------------------------------------
@@ -708,20 +715,20 @@ struct SimpleFrame_MDLn_SP
*/
struct GroupFrame
{
- //! 0 = simple frame, !0 = group frame
- int32_t type;
+ //! 0 = simple frame, !0 = group frame
+ int32_t type;
- //! Minimum vertex for all single frames
- Vertex min;
+ //! Minimum vertex for all single frames
+ Vertex min;
- //! Maximum vertex for all single frames
- Vertex max;
+ //! Maximum vertex for all single frames
+ Vertex max;
- //! Time for all single frames
- float *time;
+ //! Time for all single frames
+ float *time;
- //! List of single frames
- SimpleFrame *frames;
+ //! List of single frames
+ SimpleFrame *frames;
} PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h"
@@ -732,20 +739,20 @@ struct GroupFrame
*/
struct IntFace_MDL7
{
- // provide a constructor for our own convenience
- IntFace_MDL7()
- {
- // set everything to zero
- mIndices[0] = mIndices[1] = mIndices[2] = 0;
- iMatIndex[0] = iMatIndex[1] = 0;
- }
+ // provide a constructor for our own convenience
+ IntFace_MDL7()
+ {
+ // set everything to zero
+ mIndices[0] = mIndices[1] = mIndices[2] = 0;
+ iMatIndex[0] = iMatIndex[1] = 0;
+ }
- //! Vertex indices
- uint32_t mIndices[3];
+ //! Vertex indices
+ uint32_t mIndices[3];
- //! Material index (maximally two channels, which are joined later)
- unsigned int iMatIndex[2];
-};
+ //! Material index (maximally two channels, which are joined later)
+ unsigned int iMatIndex[2];
+};
// -------------------------------------------------------------------------------------
/** \struct IntMaterial_MDL7
@@ -755,18 +762,18 @@ struct IntFace_MDL7
*/
struct IntMaterial_MDL7
{
- // provide a constructor for our own convenience
- IntMaterial_MDL7()
- {
- pcMat = NULL;
- iOldMatIndices[0] = iOldMatIndices[1] = 0;
- }
+ // provide a constructor for our own convenience
+ IntMaterial_MDL7()
+ {
+ pcMat = NULL;
+ iOldMatIndices[0] = iOldMatIndices[1] = 0;
+ }
- //! Material instance
- aiMaterial* pcMat;
+ //! Material instance
+ aiMaterial* pcMat;
- //! Old material indices
- unsigned int iOldMatIndices[2];
+ //! Old material indices
+ unsigned int iOldMatIndices[2];
};
// -------------------------------------------------------------------------------------
@@ -776,180 +783,185 @@ struct IntMaterial_MDL7
*/
struct IntBone_MDL7 : aiBone
{
- //! Default constructor
- IntBone_MDL7() : iParent (0xffff)
- {
- pkeyPositions.reserve(30);
- pkeyScalings.reserve(30);
- pkeyRotations.reserve(30);
- }
+ //! Default constructor
+ IntBone_MDL7() : iParent (0xffff)
+ {
+ pkeyPositions.reserve(30);
+ pkeyScalings.reserve(30);
+ pkeyRotations.reserve(30);
+ }
- //! Parent bone of the bone
- uint64_t iParent;
+ //! Parent bone of the bone
+ uint64_t iParent;
- //! Relative position of the bone
- aiVector3D vPosition;
+ //! Relative position of the bone
+ aiVector3D vPosition;
- //! Array of position keys
- std::vector<aiVectorKey> pkeyPositions;
+ //! Array of position keys
+ std::vector<aiVectorKey> pkeyPositions;
- //! Array of scaling keys
- std::vector<aiVectorKey> pkeyScalings;
+ //! Array of scaling keys
+ std::vector<aiVectorKey> pkeyScalings;
- //! Array of rotation keys
- std::vector<aiQuatKey> pkeyRotations;
+ //! Array of rotation keys
+ std::vector<aiQuatKey> pkeyRotations;
};
// -------------------------------------------------------------------------------------
//! Describes a MDL7 frame
struct IntFrameInfo_MDL7
{
- //! Construction from an existing frame header
- IntFrameInfo_MDL7(BE_NCONST MDL::Frame_MDL7* _pcFrame,unsigned int _iIndex)
- : iIndex(_iIndex)
- , pcFrame(_pcFrame)
- {}
+ //! Construction from an existing frame header
+ IntFrameInfo_MDL7(BE_NCONST MDL::Frame_MDL7* _pcFrame,unsigned int _iIndex)
+ : iIndex(_iIndex)
+ , pcFrame(_pcFrame)
+ {}
- //! Index of the frame
- unsigned int iIndex;
+ //! Index of the frame
+ unsigned int iIndex;
- //! Points to the header of the frame
- BE_NCONST MDL::Frame_MDL7* pcFrame;
+ //! Points to the header of the frame
+ BE_NCONST MDL::Frame_MDL7* pcFrame;
};
// -------------------------------------------------------------------------------------
//! Describes a MDL7 mesh group
struct IntGroupInfo_MDL7
{
- //! Default constructor
- IntGroupInfo_MDL7()
- : iIndex(0)
- , pcGroup(NULL)
- , pcGroupUVs(NULL)
- , pcGroupTris(NULL)
- , pcGroupVerts(NULL)
- {}
-
- //! Construction from an existing group header
- IntGroupInfo_MDL7(BE_NCONST MDL::Group_MDL7* _pcGroup, unsigned int _iIndex)
- : iIndex(_iIndex)
- , pcGroup(_pcGroup)
- {}
-
- //! Index of the group
- unsigned int iIndex;
-
- //! Points to the header of the group
- BE_NCONST MDL::Group_MDL7* pcGroup;
-
- //! Points to the beginning of the uv coordinate section
- BE_NCONST MDL::TexCoord_MDL7* pcGroupUVs;
-
- //! Points to the beginning of the triangle section
- MDL::Triangle_MDL7* pcGroupTris;
-
- //! Points to the beginning of the vertex section
- BE_NCONST MDL::Vertex_MDL7* pcGroupVerts;
+ //! Default constructor
+ IntGroupInfo_MDL7()
+ : iIndex(0)
+ , pcGroup(NULL)
+ , pcGroupUVs(NULL)
+ , pcGroupTris(NULL)
+ , pcGroupVerts(NULL)
+ {}
+
+ //! Construction from an existing group header
+ IntGroupInfo_MDL7(BE_NCONST MDL::Group_MDL7* _pcGroup, unsigned int _iIndex)
+ : iIndex(_iIndex)
+ , pcGroup(_pcGroup)
+ , pcGroupUVs()
+ , pcGroupTris()
+ , pcGroupVerts()
+ {}
+
+ //! Index of the group
+ unsigned int iIndex;
+
+ //! Points to the header of the group
+ BE_NCONST MDL::Group_MDL7* pcGroup;
+
+ //! Points to the beginning of the uv coordinate section
+ BE_NCONST MDL::TexCoord_MDL7* pcGroupUVs;
+
+ //! Points to the beginning of the triangle section
+ MDL::Triangle_MDL7* pcGroupTris;
+
+ //! Points to the beginning of the vertex section
+ BE_NCONST MDL::Vertex_MDL7* pcGroupVerts;
};
// -------------------------------------------------------------------------------------
//! Holds the data that belongs to a MDL7 mesh group
struct IntGroupData_MDL7
{
- IntGroupData_MDL7()
- : pcFaces(NULL), bNeed2UV(false)
- {}
+ IntGroupData_MDL7()
+ : pcFaces(NULL), bNeed2UV(false)
+ {}
- //! Array of faces that belong to the group
- MDL::IntFace_MDL7* pcFaces;
+ //! Array of faces that belong to the group
+ MDL::IntFace_MDL7* pcFaces;
- //! Array of vertex positions
- std::vector<aiVector3D> vPositions;
+ //! Array of vertex positions
+ std::vector<aiVector3D> vPositions;
- //! Array of vertex normals
- std::vector<aiVector3D> vNormals;
+ //! Array of vertex normals
+ std::vector<aiVector3D> vNormals;
- //! Array of bones indices
- std::vector<unsigned int> aiBones;
+ //! Array of bones indices
+ std::vector<unsigned int> aiBones;
- //! First UV coordinate set
- std::vector<aiVector3D> vTextureCoords1;
+ //! First UV coordinate set
+ std::vector<aiVector3D> vTextureCoords1;
- //! Optional second UV coordinate set
- std::vector<aiVector3D> vTextureCoords2;
+ //! Optional second UV coordinate set
+ std::vector<aiVector3D> vTextureCoords2;
- //! Specifies whether there are two texture
- //! coordinate sets required
- bool bNeed2UV;
+ //! Specifies whether there are two texture
+ //! coordinate sets required
+ bool bNeed2UV;
};
// -------------------------------------------------------------------------------------
//! Holds data from an MDL7 file that is shared by all mesh groups
struct IntSharedData_MDL7
{
- //! Default constructor
- IntSharedData_MDL7()
- {
- abNeedMaterials.reserve(10);
- }
-
- //! Destruction: properly delete all allocated resources
- ~IntSharedData_MDL7()
- {
- // kill all bones
- if (this->apcOutBones)
- {
- for (unsigned int m = 0; m < iNum;++m)
- delete this->apcOutBones[m];
- delete[] this->apcOutBones;
- }
- }
-
- //! Specifies which materials are used
- std::vector<bool> abNeedMaterials;
-
- //! List of all materials
- std::vector<aiMaterial*> pcMats;
-
- //! List of all bones
- IntBone_MDL7** apcOutBones;
-
- //! number of bones
- unsigned int iNum;
+ //! Default constructor
+ IntSharedData_MDL7()
+ : apcOutBones(),
+ iNum()
+ {
+ abNeedMaterials.reserve(10);
+ }
+
+ //! Destruction: properly delete all allocated resources
+ ~IntSharedData_MDL7()
+ {
+ // kill all bones
+ if (this->apcOutBones)
+ {
+ for (unsigned int m = 0; m < iNum;++m)
+ delete this->apcOutBones[m];
+ delete[] this->apcOutBones;
+ }
+ }
+
+ //! Specifies which materials are used
+ std::vector<bool> abNeedMaterials;
+
+ //! List of all materials
+ std::vector<aiMaterial*> pcMats;
+
+ //! List of all bones
+ IntBone_MDL7** apcOutBones;
+
+ //! number of bones
+ unsigned int iNum;
};
// -------------------------------------------------------------------------------------
//! Contains input data for GenerateOutputMeshes_3DGS_MDL7
struct IntSplitGroupData_MDL7
{
- //! Construction from a given shared data set
- IntSplitGroupData_MDL7(IntSharedData_MDL7& _shared,
- std::vector<aiMesh*>& _avOutList)
-
- : shared(_shared), avOutList(_avOutList)
- {
- }
-
- //! Destruction: properly delete all allocated resources
- ~IntSplitGroupData_MDL7()
- {
- // kill all face lists
- if(this->aiSplit)
- {
- for (unsigned int m = 0; m < shared.pcMats.size();++m)
- delete this->aiSplit[m];
- delete[] this->aiSplit;
- }
- }
-
- //! Contains a list of all faces per material
- std::vector<unsigned int>** aiSplit;
-
- //! Shared data for all groups of the model
- IntSharedData_MDL7& shared;
-
- //! List of meshes
- std::vector<aiMesh*>& avOutList;
+ //! Construction from a given shared data set
+ IntSplitGroupData_MDL7(IntSharedData_MDL7& _shared,
+ std::vector<aiMesh*>& _avOutList)
+
+ : aiSplit(), shared(_shared), avOutList(_avOutList)
+ {
+ }
+
+ //! Destruction: properly delete all allocated resources
+ ~IntSplitGroupData_MDL7()
+ {
+ // kill all face lists
+ if(this->aiSplit)
+ {
+ for (unsigned int m = 0; m < shared.pcMats.size();++m)
+ delete this->aiSplit[m];
+ delete[] this->aiSplit;
+ }
+ }
+
+ //! Contains a list of all faces per material
+ std::vector<unsigned int>** aiSplit;
+
+ //! Shared data for all groups of the model
+ IntSharedData_MDL7& shared;
+
+ //! List of meshes
+ std::vector<aiMesh*>& avOutList;
};
diff --git a/src/3rdparty/assimp/code/MDLLoader.cpp b/src/3rdparty/assimp/code/MDLLoader.cpp
index ebe6caf68..ba5c4c32c 100644
--- a/src/3rdparty/assimp/code/MDLLoader.cpp
+++ b/src/3rdparty/assimp/code/MDLLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -45,279 +45,295 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// internal headers
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
#include "MDLLoader.h"
+#include "Macros.h"
+#include "qnan.h"
#include "MDLDefaultColorMap.h"
-#include "MD2FileData.h"
+#include "MD2FileData.h"
+#include "StringUtils.h"
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
+#include <memory>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Quake Mesh / 3D GameStudio Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 7,
- 0,
- "mdl"
+ "Quake Mesh / 3D GameStudio Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 7,
+ 0,
+ "mdl"
};
// ------------------------------------------------------------------------------------------------
// Ugly stuff ... nevermind
-#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
- (*((const _type*)(((const char*)_data) + _index * _limit)))
+#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
+ (*((const _type*)(((const char*)_data) + _index * _limit)))
-#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \
- ((BE_NCONST _type*)(((const char*)_data) + _index * _limit))
+#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \
+ ((BE_NCONST _type*)(((const char*)_data) + _index * _limit))
-#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
- _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
+#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
+ _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MDLImporter::MDLImporter()
+ : configFrameID(),
+ mBuffer(),
+ iGSFileVersion(),
+ pIOHandler(),
+ pScene(),
+ iFileSize()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MDLImporter::~MDLImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- // if check for extension is not enough, check for the magic tokens
- if (extension == "mdl" || !extension.length() || checkSig) {
- uint32_t tokens[8];
- tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a;
- tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b;
- tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7;
- tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b;
- tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a;
- tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4;
- tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3;
- tokens[7] = AI_MDL_MAGIC_NUMBER_LE;
- return CheckMagicToken(pIOHandler,pFile,tokens,8,0);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ // if check for extension is not enough, check for the magic tokens
+ if (extension == "mdl" || !extension.length() || checkSig) {
+ uint32_t tokens[8];
+ tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a;
+ tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b;
+ tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7;
+ tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b;
+ tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a;
+ tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4;
+ tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3;
+ tokens[7] = AI_MDL_MAGIC_NUMBER_LE;
+ return CheckMagicToken(pIOHandler,pFile,tokens,8,0);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void MDLImporter::SetupProperties(const Importer* pImp)
{
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,-1);
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,-1);
- // The
- // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- if(static_cast<unsigned int>(-1) == configFrameID) {
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The
+ // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ if(static_cast<unsigned int>(-1) == configFrameID) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
- // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
- configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
+ // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
+ configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
}
// ------------------------------------------------------------------------------------------------
// Get a list of all supported extensions
const aiImporterDesc* MDLImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MDLImporter::InternReadFile( const std::string& pFile,
- aiScene* _pScene, IOSystem* _pIOHandler)
+// Imports the given file into the given scene structure.
+void MDLImporter::InternReadFile( const std::string& pFile,
+ aiScene* _pScene, IOSystem* _pIOHandler)
{
- pScene = _pScene;
- pIOHandler = _pIOHandler;
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open MDL file " + pFile + ".");
- }
-
- // This should work for all other types of MDL files, too ...
- // the quake header is one of the smallest, afaik
- iFileSize = (unsigned int)file->FileSize();
- if( iFileSize < sizeof(MDL::Header)) {
- throw DeadlyImportError( "MDL File is too small.");
- }
-
- // Allocate storage and copy the contents of the file to a memory buffer
- std::vector<unsigned char> buffer(iFileSize+1);
- mBuffer = &buffer[0];
- file->Read( (void*)mBuffer, 1, iFileSize);
-
- // Append a binary zero to the end of the buffer.
- // this is just for safety that string parsing routines
- // find the end of the buffer ...
- mBuffer[iFileSize] = '\0';
- const uint32_t iMagicWord = *((uint32_t*)mBuffer);
-
- // Determine the file subtype and call the appropriate member function
-
- // Original Quake1 format
- if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
- iGSFileVersion = 0;
- InternReadFile_Quake1();
- }
- // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
- else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
- iGSFileVersion = 2;
- InternReadFile_Quake1();
- }
- // GameStudio A4 MDL3 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
- iGSFileVersion = 3;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A5+ MDL4 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
- iGSFileVersion = 4;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A5+ MDL5 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
- iGSFileVersion = 5;
- InternReadFile_3DGS_MDL345();
- }
- // GameStudio A7 MDL7 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
- iGSFileVersion = 7;
- InternReadFile_3DGS_MDL7();
- }
- // IDST/IDSQ Format (CS:S/HL^2, etc ...)
- else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
- AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
- {
- DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
- iGSFileVersion = 0;
- InternReadFile_HL2();
- }
- else {
- // print the magic word to the log file
- throw DeadlyImportError( "Unknown MDL subformat " + pFile +
- ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known");
- }
-
- // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
- pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
- 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
-
- // delete the file buffer and cleanup
- AI_DEBUG_INVALIDATE_PTR(mBuffer);
- AI_DEBUG_INVALIDATE_PTR(pIOHandler);
- AI_DEBUG_INVALIDATE_PTR(pScene);
+ pScene = _pScene;
+ pIOHandler = _pIOHandler;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open MDL file " + pFile + ".");
+ }
+
+ // This should work for all other types of MDL files, too ...
+ // the quake header is one of the smallest, afaik
+ iFileSize = (unsigned int)file->FileSize();
+ if( iFileSize < sizeof(MDL::Header)) {
+ throw DeadlyImportError( "MDL File is too small.");
+ }
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ std::vector<unsigned char> buffer(iFileSize+1);
+ mBuffer = &buffer[0];
+ file->Read( (void*)mBuffer, 1, iFileSize);
+
+ // Append a binary zero to the end of the buffer.
+ // this is just for safety that string parsing routines
+ // find the end of the buffer ...
+ mBuffer[iFileSize] = '\0';
+ const uint32_t iMagicWord = *((uint32_t*)mBuffer);
+
+ // Determine the file subtype and call the appropriate member function
+
+ // Original Quake1 format
+ if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
+ iGSFileVersion = 0;
+ InternReadFile_Quake1();
+ }
+ // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
+ iGSFileVersion = 2;
+ InternReadFile_Quake1();
+ }
+ // GameStudio A4 MDL3 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
+ iGSFileVersion = 3;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A5+ MDL4 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
+ iGSFileVersion = 4;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A5+ MDL5 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
+ iGSFileVersion = 5;
+ InternReadFile_3DGS_MDL345();
+ }
+ // GameStudio A7 MDL7 format
+ else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) {
+ DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
+ iGSFileVersion = 7;
+ InternReadFile_3DGS_MDL7();
+ }
+ // IDST/IDSQ Format (CS:S/HL^2, etc ...)
+ else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
+ AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
+ {
+ DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
+ iGSFileVersion = 0;
+ InternReadFile_HL2();
+ }
+ else {
+ // print the magic word to the log file
+ throw DeadlyImportError( "Unknown MDL subformat " + pFile +
+ ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known");
+ }
+
+ // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+ pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+ 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+
+ // delete the file buffer and cleanup
+ AI_DEBUG_INVALIDATE_PTR(mBuffer);
+ AI_DEBUG_INVALIDATE_PTR(pIOHandler);
+ AI_DEBUG_INVALIDATE_PTR(pScene);
}
// ------------------------------------------------------------------------------------------------
// Check whether we're still inside the valid file range
void MDLImporter::SizeCheck(const void* szPos)
{
- if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize)
- {
- throw DeadlyImportError("Invalid MDL file. The file is too small "
- "or contains invalid data.");
- }
+ if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize)
+ {
+ throw DeadlyImportError("Invalid MDL file. The file is too small "
+ "or contains invalid data.");
+ }
}
// ------------------------------------------------------------------------------------------------
// Just for debgging purposes
void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine)
{
- ai_assert(NULL != szFile);
- if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize)
- {
- // remove a directory if there is one
- const char* szFilePtr = ::strrchr(szFile,'\\');
- if (!szFilePtr) {
- if(!(szFilePtr = ::strrchr(szFile,'/')))
- szFilePtr = szFile;
- }
- if (szFilePtr)++szFilePtr;
-
- char szBuffer[1024];
- ::sprintf(szBuffer,"Invalid MDL file. The file is too small "
- "or contains invalid data (File: %s Line: %i)",szFilePtr,iLine);
-
- throw DeadlyImportError(szBuffer);
- }
+ ai_assert(NULL != szFile);
+ if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize)
+ {
+ // remove a directory if there is one
+ const char* szFilePtr = ::strrchr(szFile,'\\');
+ if (!szFilePtr) {
+ if(!(szFilePtr = ::strrchr(szFile,'/')))
+ szFilePtr = szFile;
+ }
+ if (szFilePtr)++szFilePtr;
+
+ char szBuffer[1024];
+ ::sprintf(szBuffer,"Invalid MDL file. The file is too small "
+ "or contains invalid data (File: %s Line: %u)",szFilePtr,iLine);
+
+ throw DeadlyImportError(szBuffer);
+ }
}
// ------------------------------------------------------------------------------------------------
// Validate a quake file header
void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader)
{
- // some values may not be NULL
- if (!pcHeader->num_frames)
- throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file");
-
- if (!pcHeader->num_verts)
- throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file");
-
- if (!pcHeader->num_tris)
- throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file");
-
- // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
- if (!this->iGSFileVersion)
- {
- if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
-
- if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
-
- if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
- DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
-
- // (this does not apply for 3DGS MDLs)
- if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
- DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
- "the expected file format version");
- if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
- DefaultLogger::get()->warn("Skin width or height are 0");
- }
+ // some values may not be NULL
+ if (!pcHeader->num_frames)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file");
+
+ if (!pcHeader->num_verts)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file");
+
+ if (!pcHeader->num_tris)
+ throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file");
+
+ // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only
+ if (!this->iGSFileVersion)
+ {
+ if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
+
+ if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
+
+ if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
+ DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
+
+ // (this does not apply for 3DGS MDLs)
+ if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
+ DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
+ "the expected file format version");
+ if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
+ DefaultLogger::get()->warn("Skin width or height are 0");
+ }
}
#ifdef AI_BUILD_BIG_ENDIAN
// ------------------------------------------------------------------------------------------------
void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
{
- AI_SWAP4( pcHeader->ident);
- AI_SWAP4( pcHeader->version);
- AI_SWAP4( pcHeader->boundingradius);
- AI_SWAP4( pcHeader->flags);
- AI_SWAP4( pcHeader->num_frames);
- AI_SWAP4( pcHeader->num_skins);
- AI_SWAP4( pcHeader->num_tris);
- AI_SWAP4( pcHeader->num_verts);
- for (unsigned int i = 0; i < 3;++i)
- {
- AI_SWAP4( pcHeader->scale[i]);
- AI_SWAP4( pcHeader->translate[i]);
- }
- AI_SWAP4( pcHeader->size);
- AI_SWAP4( pcHeader->skinheight);
- AI_SWAP4( pcHeader->skinwidth);
- AI_SWAP4( pcHeader->synctype);
+ AI_SWAP4( pcHeader->ident);
+ AI_SWAP4( pcHeader->version);
+ AI_SWAP4( pcHeader->boundingradius);
+ AI_SWAP4( pcHeader->flags);
+ AI_SWAP4( pcHeader->num_frames);
+ AI_SWAP4( pcHeader->num_skins);
+ AI_SWAP4( pcHeader->num_tris);
+ AI_SWAP4( pcHeader->num_verts);
+ for (unsigned int i = 0; i < 3;++i)
+ {
+ AI_SWAP4( pcHeader->scale[i]);
+ AI_SWAP4( pcHeader->translate[i]);
+ }
+ AI_SWAP4( pcHeader->size);
+ AI_SWAP4( pcHeader->skinheight);
+ AI_SWAP4( pcHeader->skinwidth);
+ AI_SWAP4( pcHeader->synctype);
}
#endif
@@ -325,630 +341,637 @@ void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader)
// Read a Quake 1 file
void MDLImporter::InternReadFile_Quake1( )
{
- ai_assert(NULL != pScene);
- BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
+ ai_assert(NULL != pScene);
+ BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN
- FlipQuakeHeader(pcHeader);
+ FlipQuakeHeader(pcHeader);
#endif
- ValidateHeader_Quake1(pcHeader);
-
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
- {
- union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
- pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
-
- AI_SWAP4( pcSkin->group );
-
- // Quake 1 groupskins
- if (1 == pcSkin->group)
- {
- AI_SWAP4( pcGroupSkin->nb );
-
- // need to skip multiple images
- const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
- szCurrent += sizeof(uint32_t) * 2;
-
- if (0 != iNumImages)
- {
- if (!i) {
- // however, create only one output image (the first)
- this->CreateTextureARGB8_3DGS_MDL3(szCurrent + iNumImages * sizeof(float));
- }
- // go to the end of the skin section / the beginning of the next skin
- szCurrent += pcHeader->skinheight * pcHeader->skinwidth +
- sizeof(float) * iNumImages;
- }
- }
- // 3DGS has a few files that are using other 3DGS like texture formats here
- else
- {
- szCurrent += sizeof(uint32_t);
- unsigned int iSkip = i ? UINT_MAX : 0;
- CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip);
- szCurrent += iSkip;
- }
- }
- // get a pointer to the texture coordinates
- BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts;
-
- // get a pointer to the triangles
- BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent;
- szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris;
- VALIDATE_FILE_SIZE(szCurrent);
-
- // now get a pointer to the first frame in the file
- BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
- BE_NCONST MDL::SimpleFrame* pcFirstFrame;
-
- if (0 == pcFrames->type)
- {
- // get address of single frame
- pcFirstFrame = &pcFrames->frame;
- }
- else
- {
- // get the first frame in the group
- BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
- pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
- }
- BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
- VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
+ ValidateHeader_Quake1(pcHeader);
+
+ // current cursor position in the file
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+
+ // need to read all textures
+ for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i)
+ {
+ union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;};
+ if (szCurrent + sizeof(MDL::Skin) > this->mBuffer + this->iFileSize) {
+ throw DeadlyImportError("[Quake 1 MDL] Unexpected EOF");
+ }
+ pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
+
+ AI_SWAP4( pcSkin->group );
+
+ // Quake 1 groupskins
+ if (1 == pcSkin->group)
+ {
+ AI_SWAP4( pcGroupSkin->nb );
+
+ // need to skip multiple images
+ const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
+ szCurrent += sizeof(uint32_t) * 2;
+
+ if (0 != iNumImages)
+ {
+ if (!i) {
+ // however, create only one output image (the first)
+ this->CreateTextureARGB8_3DGS_MDL3(szCurrent + iNumImages * sizeof(float));
+ }
+ // go to the end of the skin section / the beginning of the next skin
+ szCurrent += pcHeader->skinheight * pcHeader->skinwidth +
+ sizeof(float) * iNumImages;
+ }
+ }
+ // 3DGS has a few files that are using other 3DGS like texture formats here
+ else
+ {
+ szCurrent += sizeof(uint32_t);
+ unsigned int iSkip = i ? UINT_MAX : 0;
+ CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip);
+ szCurrent += iSkip;
+ }
+ }
+ // get a pointer to the texture coordinates
+ BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent;
+ szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts;
+
+ // get a pointer to the triangles
+ BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent;
+ szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ // now get a pointer to the first frame in the file
+ BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
+ BE_NCONST MDL::SimpleFrame* pcFirstFrame;
+
+ if (0 == pcFrames->type)
+ {
+ // get address of single frame
+ pcFirstFrame = &pcFrames->frame;
+ }
+ else
+ {
+ // get the first frame in the group
+ BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
+ pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
+ }
+ BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
+ VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
#ifdef AI_BUILD_BIG_ENDIAN
- for (int i = 0; i<pcHeader->num_verts;++i)
- {
- AI_SWAP4( pcTexCoords[i].onseam );
- AI_SWAP4( pcTexCoords[i].s );
- AI_SWAP4( pcTexCoords[i].t );
- }
-
- for (int i = 0; i<pcHeader->num_tris;++i)
- {
- AI_SWAP4( pcTriangles[i].facesfront);
- AI_SWAP4( pcTriangles[i].vertex[0]);
- AI_SWAP4( pcTriangles[i].vertex[1]);
- AI_SWAP4( pcTriangles[i].vertex[2]);
- }
+ for (int i = 0; i<pcHeader->num_verts;++i)
+ {
+ AI_SWAP4( pcTexCoords[i].onseam );
+ AI_SWAP4( pcTexCoords[i].s );
+ AI_SWAP4( pcTexCoords[i].t );
+ }
+
+ for (int i = 0; i<pcHeader->num_tris;++i)
+ {
+ AI_SWAP4( pcTriangles[i].facesfront);
+ AI_SWAP4( pcTriangles[i].vertex[0]);
+ AI_SWAP4( pcTriangles[i].vertex[1]);
+ AI_SWAP4( pcTriangles[i].vertex[2]);
+ }
#endif
- // setup materials
- SetupMaterialProperties_3DGS_MDL5_Quake1();
-
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
-
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- pcMesh->mNumVertices = pcHeader->num_tris * 3;
- pcMesh->mNumFaces = pcHeader->num_tris;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
-
- // there won't be more than one mesh inside the file
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i)
- {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- pcMesh->mFaces[i].mIndices[c] = iCurrent;
-
- // read vertices
- unsigned int iIndex = pcTriangles->vertex[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts)
- {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- //vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- //pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- float s = (float)pcTexCoords[iIndex].s;
- float t = (float)pcTexCoords[iIndex].t;
-
- // translate texture coordinates
- if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) {
- s += pcHeader->skinwidth * 0.5f;
- }
-
- // Scale s and t to range from 0.0 to 1.0
- pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth;
- pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight;
-
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- return;
+ // setup materials
+ SetupMaterialProperties_3DGS_MDL5_Quake1();
+
+ // allocate enough storage to hold all vertices and triangles
+ aiMesh* pcMesh = new aiMesh();
+
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ pcMesh->mNumVertices = pcHeader->num_tris * 3;
+ pcMesh->mNumFaces = pcHeader->num_tris;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+
+ // there won't be more than one mesh inside the file
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ pScene->mMeshes[0] = pcMesh;
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i)
+ {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent)
+ {
+ pcMesh->mFaces[i].mIndices[c] = iCurrent;
+
+ // read vertices
+ unsigned int iIndex = pcTriangles->vertex[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts)
+ {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ //vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ //pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ float s = (float)pcTexCoords[iIndex].s;
+ float t = (float)pcTexCoords[iIndex].t;
+
+ // translate texture coordinates
+ if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) {
+ s += pcHeader->skinwidth * 0.5f;
+ }
+
+ // Scale s and t to range from 0.0 to 1.0
+ pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth;
+ pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight;
+
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Setup material properties for Quake and older GameStudio files
void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( )
{
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
-
- // allocate ONE material
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = new aiMaterial();
- pScene->mNumMaterials = 1;
-
- // setup the material's properties
- const int iMode = (int)aiShadingMode_Gouraud;
- aiMaterial* const pcHelper = (aiMaterial*)pScene->mMaterials[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor4D clr;
- if (0 != pcHeader->num_skins && pScene->mNumTextures) {
- // can we replace the texture with a single color?
- clr = this->ReplaceTextureWithColor(pScene->mTextures[0]);
- if (is_not_qnan(clr.r)) {
- delete pScene->mTextures[0];
- delete[] pScene->mTextures;
-
- pScene->mTextures = NULL;
- pScene->mNumTextures = 0;
- }
- else {
- clr.b = clr.a = clr.g = clr.r = 1.0f;
- aiString szString;
- ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
- szString.length = 2;
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- }
-
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.r *= 0.05f;clr.g *= 0.05f;
- clr.b *= 0.05f;clr.a = 1.0f;
- pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+
+ // allocate ONE material
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = new aiMaterial();
+ pScene->mNumMaterials = 1;
+
+ // setup the material's properties
+ const int iMode = (int)aiShadingMode_Gouraud;
+ aiMaterial* const pcHelper = (aiMaterial*)pScene->mMaterials[0];
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor4D clr;
+ if (0 != pcHeader->num_skins && pScene->mNumTextures) {
+ // can we replace the texture with a single color?
+ clr = this->ReplaceTextureWithColor(pScene->mTextures[0]);
+ if (is_not_qnan(clr.r)) {
+ delete pScene->mTextures[0];
+ delete[] pScene->mTextures;
+
+ pScene->mTextures = NULL;
+ pScene->mNumTextures = 0;
+ }
+ else {
+ clr.b = clr.a = clr.g = clr.r = 1.0f;
+ aiString szString;
+ ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
+ szString.length = 2;
+ pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
+
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.r *= 0.05f;clr.g *= 0.05f;
+ clr.b *= 0.05f;clr.a = 1.0f;
+ pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
}
// ------------------------------------------------------------------------------------------------
// Read a MDL 3,4,5 file
void MDLImporter::InternReadFile_3DGS_MDL345( )
{
- ai_assert(NULL != pScene);
+ ai_assert(NULL != pScene);
- // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
- BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
+ // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
+ BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer;
#ifdef AI_BUILD_BIG_ENDIAN
- FlipQuakeHeader(pcHeader);
+ FlipQuakeHeader(pcHeader);
#endif
- ValidateHeader_Quake1(pcHeader);
-
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) {
- BE_NCONST MDL::Skin* pcSkin;
- pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
- AI_SWAP4( pcSkin->group);
- // create one output image
- unsigned int iSkip = i ? UINT_MAX : 0;
- if (5 <= iGSFileVersion)
- {
- // MDL5 format could contain MIPmaps
- CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- else {
- CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- // need to skip one image
- szCurrent += iSkip + sizeof(uint32_t);
-
- }
- // get a pointer to the texture coordinates
- BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype;
-
- // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords
-
- // get a pointer to the triangles
- BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
+ ValidateHeader_Quake1(pcHeader);
+
+ // current cursor position in the file
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+ const unsigned char* szEnd = mBuffer + iFileSize;
+
+ // need to read all textures
+ for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) {
+ if (szCurrent >= szEnd) {
+ throw DeadlyImportError( "Texture data past end of file.");
+ }
+ BE_NCONST MDL::Skin* pcSkin;
+ pcSkin = (BE_NCONST MDL::Skin*)szCurrent;
+ AI_SWAP4( pcSkin->group);
+ // create one output image
+ unsigned int iSkip = i ? UINT_MAX : 0;
+ if (5 <= iGSFileVersion)
+ {
+ // MDL5 format could contain MIPmaps
+ CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t),
+ pcSkin->group,&iSkip);
+ }
+ else {
+ CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t),
+ pcSkin->group,&iSkip);
+ }
+ // need to skip one image
+ szCurrent += iSkip + sizeof(uint32_t);
+
+ }
+ // get a pointer to the texture coordinates
+ BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent;
+ szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype;
+
+ // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords
+
+ // get a pointer to the triangles
+ BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent;
+ szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris;
#ifdef AI_BUILD_BIG_ENDIAN
- for (int i = 0; i<pcHeader->synctype;++i) {
- AI_SWAP2( pcTexCoords[i].u );
- AI_SWAP2( pcTexCoords[i].v );
- }
+ for (int i = 0; i<pcHeader->synctype;++i) {
+ AI_SWAP2( pcTexCoords[i].u );
+ AI_SWAP2( pcTexCoords[i].v );
+ }
- for (int i = 0; i<pcHeader->num_tris;++i) {
- AI_SWAP2( pcTriangles[i].index_xyz[0]);
- AI_SWAP2( pcTriangles[i].index_xyz[1]);
- AI_SWAP2( pcTriangles[i].index_xyz[2]);
- AI_SWAP2( pcTriangles[i].index_uv[0]);
- AI_SWAP2( pcTriangles[i].index_uv[1]);
- AI_SWAP2( pcTriangles[i].index_uv[2]);
- }
+ for (int i = 0; i<pcHeader->num_tris;++i) {
+ AI_SWAP2( pcTriangles[i].index_xyz[0]);
+ AI_SWAP2( pcTriangles[i].index_xyz[1]);
+ AI_SWAP2( pcTriangles[i].index_xyz[2]);
+ AI_SWAP2( pcTriangles[i].index_uv[0]);
+ AI_SWAP2( pcTriangles[i].index_uv[1]);
+ AI_SWAP2( pcTriangles[i].index_uv[2]);
+ }
#endif
- VALIDATE_FILE_SIZE(szCurrent);
-
- // setup materials
- SetupMaterialProperties_3DGS_MDL5_Quake1();
-
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- pcMesh->mNumVertices = pcHeader->num_tris * 3;
- pcMesh->mNumFaces = pcHeader->num_tris;
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- // there won't be more than one mesh inside the file
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
-
- // allocate output storage
- pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
-
- if (pcHeader->synctype) {
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
- }
-
- // now get a pointer to the first frame in the file
- BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
- AI_SWAP4(pcFrames->type);
-
- // byte packed vertices
- // FIXME: these two snippets below are almost identical ... join them?
- /////////////////////////////////////////////////////////////////////////////////////
- if (0 == pcFrames->type || 3 >= this->iGSFileVersion) {
-
- const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
- const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
-
- VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts) {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- // vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- // pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- if (pcHeader->synctype) {
- ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
- pcTexCoords,pcTriangles->index_uv[c]);
- }
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
-
- }
- // short packed vertices
- /////////////////////////////////////////////////////////////////////////////////////
- else {
- // now get a pointer to the first frame in the file
- const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
-
- // get a pointer to the vertices
- const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
- sizeof(pcFirstFrame->name));
-
- VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
-
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
-
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent) {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)pcHeader->num_verts) {
- iIndex = pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
- }
-
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
- vec.x += pcHeader->translate[0];
-
- vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
- vec.y += pcHeader->translate[1];
- // vec.y *= -1.0f;
-
- vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
- vec.z += pcHeader->translate[2];
-
- // read the normal vector from the precalculated normal table
- MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
- // pcMesh->mNormals[iCurrent].y *= -1.0f;
-
- // read texture coordinates
- if (pcHeader->synctype) {
- ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
- pcTexCoords,pcTriangles->index_uv[c]);
- }
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- }
-
- // For MDL5 we will need to build valid texture coordinates
- // basing upon the file loaded (only support one file as skin)
- if (0x5 == iGSFileVersion)
- CalculateUVCoordinates_MDL5();
- return;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ // setup materials
+ SetupMaterialProperties_3DGS_MDL5_Quake1();
+
+ // allocate enough storage to hold all vertices and triangles
+ aiMesh* pcMesh = new aiMesh();
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ pcMesh->mNumVertices = pcHeader->num_tris * 3;
+ pcMesh->mNumFaces = pcHeader->num_tris;
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ // there won't be more than one mesh inside the file
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ pScene->mMeshes[0] = pcMesh;
+
+ // allocate output storage
+ pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ if (pcHeader->synctype) {
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+ }
+
+ // now get a pointer to the first frame in the file
+ BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
+ AI_SWAP4(pcFrames->type);
+
+ // byte packed vertices
+ // FIXME: these two snippets below are almost identical ... join them?
+ /////////////////////////////////////////////////////////////////////////////////////
+ if (0 == pcFrames->type || 3 >= this->iGSFileVersion) {
+
+ const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t));
+ const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
+
+ VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+ // read vertices
+ unsigned int iIndex = pcTriangles->index_xyz[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts) {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ // vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ // pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ if (pcHeader->synctype) {
+ ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
+ pcTexCoords,pcTriangles->index_uv[c]);
+ }
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+
+ }
+ // short packed vertices
+ /////////////////////////////////////////////////////////////////////////////////////
+ else {
+ // now get a pointer to the first frame in the file
+ const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t));
+
+ // get a pointer to the vertices
+ const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
+ sizeof(pcFirstFrame->name));
+
+ VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts);
+
+ // now iterate through all triangles
+ unsigned int iCurrent = 0;
+ for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) {
+ pcMesh->mFaces[i].mIndices = new unsigned int[3];
+ pcMesh->mFaces[i].mNumIndices = 3;
+
+ unsigned int iTemp = iCurrent;
+ for (unsigned int c = 0; c < 3;++c,++iCurrent) {
+ // read vertices
+ unsigned int iIndex = pcTriangles->index_xyz[c];
+ if (iIndex >= (unsigned int)pcHeader->num_verts) {
+ iIndex = pcHeader->num_verts-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+ }
+
+ aiVector3D& vec = pcMesh->mVertices[iCurrent];
+ vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0];
+ vec.x += pcHeader->translate[0];
+
+ vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1];
+ vec.y += pcHeader->translate[1];
+ // vec.y *= -1.0f;
+
+ vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2];
+ vec.z += pcHeader->translate[2];
+
+ // read the normal vector from the precalculated normal table
+ MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]);
+ // pcMesh->mNormals[iCurrent].y *= -1.0f;
+
+ // read texture coordinates
+ if (pcHeader->synctype) {
+ ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent],
+ pcTexCoords,pcTriangles->index_uv[c]);
+ }
+ }
+ pcMesh->mFaces[i].mIndices[0] = iTemp+2;
+ pcMesh->mFaces[i].mIndices[1] = iTemp+1;
+ pcMesh->mFaces[i].mIndices[2] = iTemp+0;
+ pcTriangles++;
+ }
+ }
+
+ // For MDL5 we will need to build valid texture coordinates
+ // basing upon the file loaded (only support one file as skin)
+ if (0x5 == iGSFileVersion)
+ CalculateUVCoordinates_MDL5();
+ return;
}
// ------------------------------------------------------------------------------------------------
// Get a single UV coordinate for Quake and older GameStudio files
-void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
- aiVector3D& vOut,
- const MDL::TexCoord_MDL3* pcSrc,
- unsigned int iIndex)
+void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
+ aiVector3D& vOut,
+ const MDL::TexCoord_MDL3* pcSrc,
+ unsigned int iIndex)
{
- ai_assert(NULL != pcSrc);
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
-
- // validate UV indices
- if (iIndex >= (unsigned int) pcHeader->synctype) {
- iIndex = pcHeader->synctype-1;
- DefaultLogger::get()->warn("Index overflow in MDLn UV coord list");
- }
-
- float s = (float)pcSrc[iIndex].u;
- float t = (float)pcSrc[iIndex].v;
-
- // Scale s and t to range from 0.0 to 1.0
- if (0x5 != iGSFileVersion) {
- s = (s + 0.5f) / pcHeader->skinwidth;
- t = 1.0f-(t + 0.5f) / pcHeader->skinheight;
- }
-
- vOut.x = s;
- vOut.y = t;
- vOut.z = 0.0f;
+ ai_assert(NULL != pcSrc);
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+
+ // validate UV indices
+ if (iIndex >= (unsigned int) pcHeader->synctype) {
+ iIndex = pcHeader->synctype-1;
+ DefaultLogger::get()->warn("Index overflow in MDLn UV coord list");
+ }
+
+ float s = (float)pcSrc[iIndex].u;
+ float t = (float)pcSrc[iIndex].v;
+
+ // Scale s and t to range from 0.0 to 1.0
+ if (0x5 != iGSFileVersion) {
+ s = (s + 0.5f) / pcHeader->skinwidth;
+ t = 1.0f-(t + 0.5f) / pcHeader->skinheight;
+ }
+
+ vOut.x = s;
+ vOut.y = t;
+ vOut.z = 0.0f;
}
// ------------------------------------------------------------------------------------------------
// Compute UV coordinates for a MDL5 file
void MDLImporter::CalculateUVCoordinates_MDL5()
{
- const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
- if (pcHeader->num_skins && this->pScene->mNumTextures) {
- const aiTexture* pcTex = this->pScene->mTextures[0];
-
- // if the file is loaded in DDS format: get the size of the
- // texture from the header of the DDS file
- // skip three DWORDs and read first height, then the width
- unsigned int iWidth, iHeight;
- if (!pcTex->mHeight) {
- const uint32_t* piPtr = (uint32_t*)pcTex->pcData;
-
- piPtr += 3;
- iHeight = (unsigned int)*piPtr++;
- iWidth = (unsigned int)*piPtr;
- if (!iHeight || !iWidth)
- {
- DefaultLogger::get()->warn("Either the width or the height of the "
- "embedded DDS texture is zero. Unable to compute final texture "
- "coordinates. The texture coordinates remain in their original "
- "0-x/0-y (x,y = texture size) range.");
- iWidth = 1;
- iHeight = 1;
- }
- }
- else {
- iWidth = pcTex->mWidth;
- iHeight = pcTex->mHeight;
- }
-
- if (1 != iWidth || 1 != iHeight) {
- const float fWidth = (float)iWidth;
- const float fHeight = (float)iHeight;
- aiMesh* pcMesh = this->pScene->mMeshes[0];
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- {
- pcMesh->mTextureCoords[0][i].x /= fWidth;
- pcMesh->mTextureCoords[0][i].y /= fHeight;
- pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL
- }
- }
- }
+ const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer;
+ if (pcHeader->num_skins && this->pScene->mNumTextures) {
+ const aiTexture* pcTex = this->pScene->mTextures[0];
+
+ // if the file is loaded in DDS format: get the size of the
+ // texture from the header of the DDS file
+ // skip three DWORDs and read first height, then the width
+ unsigned int iWidth, iHeight;
+ if (!pcTex->mHeight) {
+ const uint32_t* piPtr = (uint32_t*)pcTex->pcData;
+
+ piPtr += 3;
+ iHeight = (unsigned int)*piPtr++;
+ iWidth = (unsigned int)*piPtr;
+ if (!iHeight || !iWidth)
+ {
+ DefaultLogger::get()->warn("Either the width or the height of the "
+ "embedded DDS texture is zero. Unable to compute final texture "
+ "coordinates. The texture coordinates remain in their original "
+ "0-x/0-y (x,y = texture size) range.");
+ iWidth = 1;
+ iHeight = 1;
+ }
+ }
+ else {
+ iWidth = pcTex->mWidth;
+ iHeight = pcTex->mHeight;
+ }
+
+ if (1 != iWidth || 1 != iHeight) {
+ const float fWidth = (float)iWidth;
+ const float fHeight = (float)iHeight;
+ aiMesh* pcMesh = this->pScene->mMeshes[0];
+ for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
+ {
+ pcMesh->mTextureCoords[0][i].x /= fWidth;
+ pcMesh->mTextureCoords[0][i].y /= fHeight;
+ pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Validate the header of a MDL7 file
void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader)
{
- ai_assert(NULL != pcHeader);
-
- // There are some fixed sizes ...
- if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
- throw DeadlyImportError(
- "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
- }
- if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) {
- throw DeadlyImportError(
- "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
- }
- if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) {
- throw DeadlyImportError(
- "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
- }
-
- // if there are no groups ... how should we load such a file?
- if(!pcHeader->groups_num) {
- throw DeadlyImportError( "[3DGS MDL7] No frames found");
- }
+ ai_assert(NULL != pcHeader);
+
+ // There are some fixed sizes ...
+ if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
+ throw DeadlyImportError(
+ "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
+ }
+ if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) {
+ throw DeadlyImportError(
+ "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
+ }
+ if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) {
+ throw DeadlyImportError(
+ "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
+ }
+
+ // if there are no groups ... how should we load such a file?
+ if(!pcHeader->groups_num) {
+ throw DeadlyImportError( "[3DGS MDL7] No frames found");
+ }
}
// ------------------------------------------------------------------------------------------------
// resolve bone animation matrices
void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones)
{
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1);
- ai_assert(NULL != apcOutBones);
-
- // first find the bone that has NO parent, calculate the
- // animation matrix for it, then go on and search for the next parent
- // index (0) and so on until we can't find a new node.
- uint16_t iParent = 0xffff;
- uint32_t iIterations = 0;
- while (iIterations++ < pcHeader->bones_num) {
- for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) {
- BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone,
- pcHeader->bone_stc_size,MDL::Bone_MDL7);
-
- AI_SWAP2(pcBone->parent_index);
- AI_SWAP4(pcBone->x);
- AI_SWAP4(pcBone->y);
- AI_SWAP4(pcBone->z);
-
- if (iParent == pcBone->parent_index) {
- // MDL7 readme
- ////////////////////////////////////////////////////////////////
- /*
- The animation matrix is then calculated the following way:
-
- vector3 bPos = <absolute bone position>
- matrix44 laM; // local animation matrix
- sphrvector key_rotate = <bone rotation>
-
- matrix44 m1,m2;
- create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z);
- create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z);
-
- create_rotation_matrix(laM,key_rotate);
-
- laM = sm1 * laM;
- laM = laM * sm2;
- */
- /////////////////////////////////////////////////////////////////
-
- MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone];
-
- // store the parent index of the bone
- pcOutBone->iParent = pcBone->parent_index;
- if (0xffff != iParent) {
- const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent];
- pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x;
- pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y;
- pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z;
- }
- pcOutBone->vPosition.x = pcBone->x;
- pcOutBone->vPosition.y = pcBone->y;
- pcOutBone->vPosition.z = pcBone->z;
- pcOutBone->mOffsetMatrix.a4 -= pcBone->x;
- pcOutBone->mOffsetMatrix.b4 -= pcBone->y;
- pcOutBone->mOffsetMatrix.c4 -= pcBone->z;
-
- if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) {
- // no real name for our poor bone is specified :-(
- pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data,
- "UnnamedBone_%i",iBone);
- }
- else {
- // Make sure we won't run over the buffer's end if there is no
- // terminal 0 character (however the documentation says there
- // should be one)
- uint32_t iMaxLen = pcHeader->bone_stc_size-16;
- for (uint32_t qq = 0; qq < iMaxLen;++qq) {
- if (!pcBone->name[qq]) {
- iMaxLen = qq;
- break;
- }
- }
-
- // store the name of the bone
- pcOutBone->mName.length = (size_t)iMaxLen;
- ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length);
- pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
- }
- }
- }
- ++iParent;
- }
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1);
+ ai_assert(NULL != apcOutBones);
+
+ // first find the bone that has NO parent, calculate the
+ // animation matrix for it, then go on and search for the next parent
+ // index (0) and so on until we can't find a new node.
+ uint16_t iParent = 0xffff;
+ uint32_t iIterations = 0;
+ while (iIterations++ < pcHeader->bones_num) {
+ for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) {
+ BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone,
+ pcHeader->bone_stc_size,MDL::Bone_MDL7);
+
+ AI_SWAP2(pcBone->parent_index);
+ AI_SWAP4(pcBone->x);
+ AI_SWAP4(pcBone->y);
+ AI_SWAP4(pcBone->z);
+
+ if (iParent == pcBone->parent_index) {
+ // MDL7 readme
+ ////////////////////////////////////////////////////////////////
+ /*
+ The animation matrix is then calculated the following way:
+
+ vector3 bPos = <absolute bone position>
+ matrix44 laM; // local animation matrix
+ sphrvector key_rotate = <bone rotation>
+
+ matrix44 m1,m2;
+ create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z);
+ create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z);
+
+ create_rotation_matrix(laM,key_rotate);
+
+ laM = sm1 * laM;
+ laM = laM * sm2;
+ */
+ /////////////////////////////////////////////////////////////////
+
+ MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone];
+
+ // store the parent index of the bone
+ pcOutBone->iParent = pcBone->parent_index;
+ if (0xffff != iParent) {
+ const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent];
+ pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x;
+ pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y;
+ pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z;
+ }
+ pcOutBone->vPosition.x = pcBone->x;
+ pcOutBone->vPosition.y = pcBone->y;
+ pcOutBone->vPosition.z = pcBone->z;
+ pcOutBone->mOffsetMatrix.a4 -= pcBone->x;
+ pcOutBone->mOffsetMatrix.b4 -= pcBone->y;
+ pcOutBone->mOffsetMatrix.c4 -= pcBone->z;
+
+ if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) {
+ // no real name for our poor bone is specified :-(
+ pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN,
+ "UnnamedBone_%i",iBone);
+ }
+ else {
+ // Make sure we won't run over the buffer's end if there is no
+ // terminal 0 character (however the documentation says there
+ // should be one)
+ uint32_t iMaxLen = pcHeader->bone_stc_size-16;
+ for (uint32_t qq = 0; qq < iMaxLen;++qq) {
+ if (!pcBone->name[qq]) {
+ iMaxLen = qq;
+ break;
+ }
+ }
+
+ // store the name of the bone
+ pcOutBone->mName.length = (size_t)iMaxLen;
+ ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length);
+ pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
+ }
+ }
+ }
+ ++iParent;
+ }
}
// ------------------------------------------------------------------------------------------------
@@ -956,630 +979,634 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones)
MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7()
{
const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- if (pcHeader->bones_num) {
- // validate the size of the bone data structure in the file
- if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size &&
- AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
- AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size)
- {
- DefaultLogger::get()->warn("Unknown size of bone data structure");
- return NULL;
- }
-
- MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num];
- for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank)
- apcBonesOut[crank] = new MDL::IntBone_MDL7();
-
- // and calculate absolute bone offset matrices ...
- CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
- return apcBonesOut;
- }
- return NULL;
+ if (pcHeader->bones_num) {
+ // validate the size of the bone data structure in the file
+ if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size &&
+ AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
+ AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size)
+ {
+ DefaultLogger::get()->warn("Unknown size of bone data structure");
+ return NULL;
+ }
+
+ MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num];
+ for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank)
+ apcBonesOut[crank] = new MDL::IntBone_MDL7();
+
+ // and calculate absolute bone offset matrices ...
+ CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
+ return apcBonesOut;
+ }
+ return NULL;
}
// ------------------------------------------------------------------------------------------------
// read faces from a MDL7 file
void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData)
+ MDL::IntGroupData_MDL7& groupData)
{
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
-
- // iterate through all triangles and build valid display lists
- unsigned int iOutIndex = 0;
- for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
- AI_SWAP2(pcGroupTris->v_index[0]);
- AI_SWAP2(pcGroupTris->v_index[1]);
- AI_SWAP2(pcGroupTris->v_index[2]);
-
- // iterate through all indices of the current triangle
- for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
-
- // validate the vertex index
- unsigned int iIndex = pcGroupTris->v_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
- // (we might need to read this section a second time - to process frame vertices correctly)
- pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
- }
-
- // write the output face index
- groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
-
- aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
- vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x;
- vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
- vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
-
- // if we have bones, save the index
- if (!groupData.aiBones.empty()) {
- groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
- iIndex,pcHeader->mainvertex_stc_size).vertindex;
- }
-
- // now read the normal vector
- if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the full normal vector
- aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
- vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
- AI_SWAP4(vNormal.x);
- vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
- AI_SWAP4(vNormal.y);
- vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
- AI_SWAP4(vNormal.z);
- }
- else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the normal vector from Quake2's smart table
- aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
- MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
- pcHeader->mainvertex_stc_size) .norm162index,vNormal);
- }
- // validate and process the first uv coordinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) {
-
- if (groupInfo.pcGroup->num_stpts) {
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]);
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]);
- AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]);
-
- iIndex = pcGroupTris->skinsets[0].st_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
- iIndex = groupInfo.pcGroup->num_stpts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)");
- }
-
- float u = groupInfo.pcGroupUVs[iIndex].u;
- float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL
-
- groupData.vTextureCoords1[iOutIndex].x = u;
- groupData.vTextureCoords1[iOutIndex].y = v;
- }
- // assign the material index, but only if it is existing
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){
- AI_SWAP4(pcGroupTris->skinsets[0].material);
- groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
- }
- }
- // validate and process the second uv coordinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
-
- if (groupInfo.pcGroup->num_stpts) {
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]);
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]);
- AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]);
- AI_SWAP4(pcGroupTris->skinsets[1].material);
-
- iIndex = pcGroupTris->skinsets[1].st_index[c];
- if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
- iIndex = groupInfo.pcGroup->num_stpts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)");
- }
-
- float u = groupInfo.pcGroupUVs[ iIndex ].u;
- float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v;
-
- groupData.vTextureCoords2[ iOutIndex ].x = u;
- groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL
-
- // check whether we do really need the second texture
- // coordinate set ... wastes memory and loading time
- if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
- v != groupData.vTextureCoords1[ iOutIndex ].y ) )
- groupData.bNeed2UV = true;
-
- // if the material differs, we need a second skin, too
- if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
- groupData.bNeed2UV = true;
- }
- // assign the material index
- groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
- }
- }
- // get the next triangle in the list
- pcGroupTris = (MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
- }
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
+
+ // iterate through all triangles and build valid display lists
+ unsigned int iOutIndex = 0;
+ for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
+ AI_SWAP2(pcGroupTris->v_index[0]);
+ AI_SWAP2(pcGroupTris->v_index[1]);
+ AI_SWAP2(pcGroupTris->v_index[2]);
+
+ // iterate through all indices of the current triangle
+ for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
+
+ // validate the vertex index
+ unsigned int iIndex = pcGroupTris->v_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
+ // (we might need to read this section a second time - to process frame vertices correctly)
+ pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
+ }
+
+ // write the output face index
+ groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex;
+
+ aiVector3D& vPosition = groupData.vPositions[ iOutIndex ];
+ vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x;
+ vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
+ vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
+
+ // if we have bones, save the index
+ if (!groupData.aiBones.empty()) {
+ groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,
+ iIndex,pcHeader->mainvertex_stc_size).vertindex;
+ }
+
+ // now read the normal vector
+ if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the full normal vector
+ aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
+ vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
+ AI_SWAP4(vNormal.x);
+ vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
+ AI_SWAP4(vNormal.y);
+ vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
+ AI_SWAP4(vNormal.z);
+ }
+ else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the normal vector from Quake2's smart table
+ aiVector3D& vNormal = groupData.vNormals[ iOutIndex ];
+ MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,
+ pcHeader->mainvertex_stc_size) .norm162index,vNormal);
+ }
+ // validate and process the first uv coordinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) {
+
+ if (groupInfo.pcGroup->num_stpts) {
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]);
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]);
+ AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]);
+
+ iIndex = pcGroupTris->skinsets[0].st_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
+ iIndex = groupInfo.pcGroup->num_stpts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)");
+ }
+
+ float u = groupInfo.pcGroupUVs[iIndex].u;
+ float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL
+
+ groupData.vTextureCoords1[iOutIndex].x = u;
+ groupData.vTextureCoords1[iOutIndex].y = v;
+ }
+ // assign the material index, but only if it is existing
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){
+ AI_SWAP4(pcGroupTris->skinsets[0].material);
+ groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
+ }
+ }
+ // validate and process the second uv coordinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
+
+ if (groupInfo.pcGroup->num_stpts) {
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]);
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]);
+ AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]);
+ AI_SWAP4(pcGroupTris->skinsets[1].material);
+
+ iIndex = pcGroupTris->skinsets[1].st_index[c];
+ if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
+ iIndex = groupInfo.pcGroup->num_stpts-1;
+ DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)");
+ }
+
+ float u = groupInfo.pcGroupUVs[ iIndex ].u;
+ float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v;
+
+ groupData.vTextureCoords2[ iOutIndex ].x = u;
+ groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL
+
+ // check whether we do really need the second texture
+ // coordinate set ... wastes memory and loading time
+ if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x ||
+ v != groupData.vTextureCoords1[ iOutIndex ].y ) )
+ groupData.bNeed2UV = true;
+
+ // if the material differs, we need a second skin, too
+ if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material)
+ groupData.bNeed2UV = true;
+ }
+ // assign the material index
+ groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material;
+ }
+ }
+ // get the next triangle in the list
+ pcGroupTris = (MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
+ }
}
// ------------------------------------------------------------------------------------------------
// handle frames in a MDL7 file
bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSharedData_MDL7& shared,
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut)
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSharedData_MDL7& shared,
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut)
{
- ai_assert(NULL != szCurrent && NULL != szCurrentOut);
- const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
-
- // if we have no bones we can simply skip all frames,
- // otherwise we'll need to process them.
- // FIX: If we need another frame than the first we must apply frame vertex replacements ...
- for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) {
- MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame);
-
- AI_SWAP4(frame.pcFrame->vertices_count);
- AI_SWAP4(frame.pcFrame->transmatrix_count);
-
- const unsigned int iAdd = pcHeader->frame_stc_size +
- frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size +
- frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
-
- if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) {
- DefaultLogger::get()->warn("Index overflow in frame area. "
- "Ignoring all frames and all further mesh groups, too.");
-
- // don't parse more groups if we can't even read one
- // FIXME: sometimes this seems to occur even for valid files ...
- *szCurrentOut = szCurrent;
- return false;
- }
- // our output frame?
- if (configFrameID == iFrame) {
- BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
-
- for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) {
- // I assume this are simple replacements for normal vertices, the bone index serving
- // as the index of the vertex to be replaced.
- uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex;
- AI_SWAP2(iIndex);
- if (iIndex >= groupInfo.pcGroup->numverts) {
- DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
- continue;
- }
-
- aiVector3D vPosition,vNormal;
-
- vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
- AI_SWAP4(vPosition.x);
- vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
- AI_SWAP4(vPosition.y);
- vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
- AI_SWAP4(vPosition.z);
-
- // now read the normal vector
- if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the full normal vector
- vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
- AI_SWAP4(vNormal.x);
- vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
- AI_SWAP4(vNormal.y);
- vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
- AI_SWAP4(vNormal.z);
- }
- else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
- // read the normal vector from Quake2's smart table
- MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
- pcHeader->framevertex_stc_size) .norm162index,vNormal);
- }
-
- // FIXME: O(n^2) at the moment ...
- BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
- unsigned int iOutIndex = 0;
- for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
- // iterate through all indices of the current triangle
- for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
- // replace the vertex with the new data
- const unsigned int iCurIndex = pcGroupTris->v_index[c];
- if (iCurIndex == iIndex) {
- groupData.vPositions[iOutIndex] = vPosition;
- groupData.vNormals[iOutIndex] = vNormal;
- }
- }
- // get the next triangle in the list
- pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*)
- pcGroupTris + pcHeader->triangle_stc_size);
- }
- }
- }
- // parse bone trafo matrix keys (only if there are bones ...)
- if (shared.apcOutBones) {
- ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
- }
- szCurrent += iAdd;
- }
- *szCurrentOut = szCurrent;
- return true;
+ ai_assert(NULL != szCurrent && NULL != szCurrentOut);
+ const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
+
+ // if we have no bones we can simply skip all frames,
+ // otherwise we'll need to process them.
+ // FIX: If we need another frame than the first we must apply frame vertex replacements ...
+ for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) {
+ MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame);
+
+ AI_SWAP4(frame.pcFrame->vertices_count);
+ AI_SWAP4(frame.pcFrame->transmatrix_count);
+
+ const unsigned int iAdd = pcHeader->frame_stc_size +
+ frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size +
+ frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
+
+ if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) {
+ DefaultLogger::get()->warn("Index overflow in frame area. "
+ "Ignoring all frames and all further mesh groups, too.");
+
+ // don't parse more groups if we can't even read one
+ // FIXME: sometimes this seems to occur even for valid files ...
+ *szCurrentOut = szCurrent;
+ return false;
+ }
+ // our output frame?
+ if (configFrameID == iFrame) {
+ BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size);
+
+ for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) {
+ // I assume this are simple replacements for normal vertices, the bone index serving
+ // as the index of the vertex to be replaced.
+ uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex;
+ AI_SWAP2(iIndex);
+ if (iIndex >= groupInfo.pcGroup->numverts) {
+ DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
+ continue;
+ }
+
+ aiVector3D vPosition,vNormal;
+
+ vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x;
+ AI_SWAP4(vPosition.x);
+ vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y;
+ AI_SWAP4(vPosition.y);
+ vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z;
+ AI_SWAP4(vPosition.z);
+
+ // now read the normal vector
+ if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the full normal vector
+ vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0];
+ AI_SWAP4(vNormal.x);
+ vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1];
+ AI_SWAP4(vNormal.y);
+ vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2];
+ AI_SWAP4(vNormal.z);
+ }
+ else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) {
+ // read the normal vector from Quake2's smart table
+ MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,
+ pcHeader->framevertex_stc_size) .norm162index,vNormal);
+ }
+
+ // FIXME: O(n^2) at the moment ...
+ BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris;
+ unsigned int iOutIndex = 0;
+ for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) {
+ // iterate through all indices of the current triangle
+ for (unsigned int c = 0; c < 3;++c,++iOutIndex) {
+ // replace the vertex with the new data
+ const unsigned int iCurIndex = pcGroupTris->v_index[c];
+ if (iCurIndex == iIndex) {
+ groupData.vPositions[iOutIndex] = vPosition;
+ groupData.vNormals[iOutIndex] = vNormal;
+ }
+ }
+ // get the next triangle in the list
+ pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*)
+ pcGroupTris + pcHeader->triangle_stc_size);
+ }
+ }
+ }
+ // parse bone trafo matrix keys (only if there are bones ...)
+ if (shared.apcOutBones) {
+ ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared);
+ }
+ szCurrent += iAdd;
+ }
+ *szCurrentOut = szCurrent;
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Sort faces by material, handle multiple UVs correctly
void MDLImporter::SortByMaterials_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData)
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData)
{
- const unsigned int iNumMaterials = (unsigned int)splitGroupData.shared.pcMats.size();
- if (!groupData.bNeed2UV) {
- // if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
- groupData.vTextureCoords2.clear();
-
- // allocate the array
- splitGroupData.aiSplit = new std::vector<unsigned int>*[iNumMaterials];
-
- for (unsigned int m = 0; m < iNumMaterials;++m)
- splitGroupData.aiSplit[m] = new std::vector<unsigned int>();
-
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
- // check range
- if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) {
- // use the last material instead
- splitGroupData.aiSplit[iNumMaterials-1]->push_back(iFace);
-
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0])
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
- }
- else splitGroupData.aiSplit[groupData.pcFaces[iFace].
- iMatIndex[0]]->push_back(iFace);
- }
- }
- else
- {
- // we need to build combined materials for each combination of
- std::vector<MDL::IntMaterial_MDL7> avMats;
- avMats.reserve(iNumMaterials*2);
-
- // fixme: why on the heap?
- std::vector<std::vector<unsigned int>* > aiTempSplit(iNumMaterials*2);
- for (unsigned int m = 0; m < iNumMaterials;++m)
- aiTempSplit[m] = new std::vector<unsigned int>();
-
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
- // check range
- unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0];
- if (iMatIndex >= iNumMaterials) {
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(UINT_MAX != iMatIndex)
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
- iMatIndex = iNumMaterials-1;
- }
- unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1];
-
- unsigned int iNum = iMatIndex;
- if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) {
- if (iMatIndex2 >= iNumMaterials) {
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
- iMatIndex2 = iNumMaterials-1;
- }
-
- // do a slow seach in the list ...
- iNum = 0;
- bool bFound = false;
- for (std::vector<MDL::IntMaterial_MDL7>::iterator i = avMats.begin();i != avMats.end();++i,++iNum){
- if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) {
- // reuse this material
- bFound = true;
- break;
- }
- }
- if (!bFound) {
- // build a new material ...
- MDL::IntMaterial_MDL7 sHelper;
- sHelper.pcMat = new aiMaterial();
- sHelper.iOldMatIndices[0] = iMatIndex;
- sHelper.iOldMatIndices[1] = iMatIndex2;
- JoinSkins_3DGS_MDL7(splitGroupData.shared.pcMats[iMatIndex],
- splitGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat);
-
- // and add it to the list
- avMats.push_back(sHelper);
- iNum = (unsigned int)avMats.size()-1;
- }
- // adjust the size of the file array
- if (iNum == aiTempSplit.size()) {
- aiTempSplit.push_back(new std::vector<unsigned int>());
- }
- }
- aiTempSplit[iNum]->push_back(iFace);
- }
-
- // now add the newly created materials to the old list
- if (0 == groupInfo.iIndex) {
- splitGroupData.shared.pcMats.resize(avMats.size());
- for (unsigned int o = 0; o < avMats.size();++o)
- splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
- }
- else {
- // This might result in redundant materials ...
- splitGroupData.shared.pcMats.resize(iNumMaterials + avMats.size());
- for (unsigned int o = iNumMaterials; o < avMats.size();++o)
- splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
- }
-
- // and build the final face-to-material array
- splitGroupData.aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
- for (unsigned int m = 0; m < iNumMaterials;++m)
- splitGroupData.aiSplit[m] = aiTempSplit[m];
- }
+ const unsigned int iNumMaterials = (unsigned int)splitGroupData.shared.pcMats.size();
+ if (!groupData.bNeed2UV) {
+ // if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
+ groupData.vTextureCoords2.clear();
+
+ // allocate the array
+ splitGroupData.aiSplit = new std::vector<unsigned int>*[iNumMaterials];
+
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ splitGroupData.aiSplit[m] = new std::vector<unsigned int>();
+
+ // iterate through all faces and sort by material
+ for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
+ // check range
+ if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) {
+ // use the last material instead
+ splitGroupData.aiSplit[iNumMaterials-1]->push_back(iFace);
+
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0])
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
+ }
+ else splitGroupData.aiSplit[groupData.pcFaces[iFace].
+ iMatIndex[0]]->push_back(iFace);
+ }
+ }
+ else
+ {
+ // we need to build combined materials for each combination of
+ std::vector<MDL::IntMaterial_MDL7> avMats;
+ avMats.reserve(iNumMaterials*2);
+
+ // fixme: why on the heap?
+ std::vector<std::vector<unsigned int>* > aiTempSplit(iNumMaterials*2);
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ aiTempSplit[m] = new std::vector<unsigned int>();
+
+ // iterate through all faces and sort by material
+ for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) {
+ // check range
+ unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0];
+ if (iMatIndex >= iNumMaterials) {
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ if(UINT_MAX != iMatIndex)
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
+ iMatIndex = iNumMaterials-1;
+ }
+ unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1];
+
+ unsigned int iNum = iMatIndex;
+ if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) {
+ if (iMatIndex2 >= iNumMaterials) {
+ // sometimes MED writes -1, but normally only if there is only
+ // one skin assigned. No warning in this case
+ DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
+ iMatIndex2 = iNumMaterials-1;
+ }
+
+ // do a slow search in the list ...
+ iNum = 0;
+ bool bFound = false;
+ for (std::vector<MDL::IntMaterial_MDL7>::iterator i = avMats.begin();i != avMats.end();++i,++iNum){
+ if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) {
+ // reuse this material
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound) {
+ // build a new material ...
+ MDL::IntMaterial_MDL7 sHelper;
+ sHelper.pcMat = new aiMaterial();
+ sHelper.iOldMatIndices[0] = iMatIndex;
+ sHelper.iOldMatIndices[1] = iMatIndex2;
+ JoinSkins_3DGS_MDL7(splitGroupData.shared.pcMats[iMatIndex],
+ splitGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat);
+
+ // and add it to the list
+ avMats.push_back(sHelper);
+ iNum = (unsigned int)avMats.size()-1;
+ }
+ // adjust the size of the file array
+ if (iNum == aiTempSplit.size()) {
+ aiTempSplit.push_back(new std::vector<unsigned int>());
+ }
+ }
+ aiTempSplit[iNum]->push_back(iFace);
+ }
+
+ // now add the newly created materials to the old list
+ if (0 == groupInfo.iIndex) {
+ splitGroupData.shared.pcMats.resize(avMats.size());
+ for (unsigned int o = 0; o < avMats.size();++o)
+ splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
+ }
+ else {
+ // This might result in redundant materials ...
+ splitGroupData.shared.pcMats.resize(iNumMaterials + avMats.size());
+ for (unsigned int o = iNumMaterials; o < avMats.size();++o)
+ splitGroupData.shared.pcMats[o] = avMats[o].pcMat;
+ }
+
+ // and build the final face-to-material array
+ splitGroupData.aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
+ for (unsigned int m = 0; m < iNumMaterials;++m)
+ splitGroupData.aiSplit[m] = aiTempSplit[m];
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a MDL7 file
void MDLImporter::InternReadFile_3DGS_MDL7( )
{
- ai_assert(NULL != pScene);
-
- MDL::IntSharedData_MDL7 sharedData;
-
- // current cursor position in the file
- BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer;
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
-
- AI_SWAP4(pcHeader->version);
- AI_SWAP4(pcHeader->bones_num);
- AI_SWAP4(pcHeader->groups_num);
- AI_SWAP4(pcHeader->data_size);
- AI_SWAP4(pcHeader->entlump_size);
- AI_SWAP4(pcHeader->medlump_size);
- AI_SWAP2(pcHeader->bone_stc_size);
- AI_SWAP2(pcHeader->skin_stc_size);
- AI_SWAP2(pcHeader->colorvalue_stc_size);
- AI_SWAP2(pcHeader->material_stc_size);
- AI_SWAP2(pcHeader->skinpoint_stc_size);
- AI_SWAP2(pcHeader->triangle_stc_size);
- AI_SWAP2(pcHeader->mainvertex_stc_size);
- AI_SWAP2(pcHeader->framevertex_stc_size);
- AI_SWAP2(pcHeader->bonetrans_stc_size);
- AI_SWAP2(pcHeader->frame_stc_size);
-
- // validate the header of the file. There are some structure
- // sizes that are expected by the loader to be constant
- this->ValidateHeader_3DGS_MDL7(pcHeader);
-
- // load all bones (they are shared by all groups, so
- // we'll need to add them to all groups/meshes later)
- // apcBonesOut is a list of all bones or NULL if they could not been loaded
- szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
- sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
-
- // vector to held all created meshes
- std::vector<aiMesh*>* avOutList;
-
- // 3 meshes per group - that should be OK for most models
- avOutList = new std::vector<aiMesh*>[pcHeader->groups_num];
- for (uint32_t i = 0; i < pcHeader->groups_num;++i)
- avOutList[i].reserve(3);
-
- // buffer to held the names of all groups in the file
- char* aszGroupNameBuffer = new char[AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num];
-
- // read all groups
- for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) {
- MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup);
- szCurrent = (const unsigned char*)(groupInfo.pcGroup+1);
-
- VALIDATE_FILE_SIZE(szCurrent);
-
- AI_SWAP4(groupInfo.pcGroup->groupdata_size);
- AI_SWAP4(groupInfo.pcGroup->numskins);
- AI_SWAP4(groupInfo.pcGroup->num_stpts);
- AI_SWAP4(groupInfo.pcGroup->numtris);
- AI_SWAP4(groupInfo.pcGroup->numverts);
- AI_SWAP4(groupInfo.pcGroup->numframes);
-
- if (1 != groupInfo.pcGroup->typ) {
- // Not a triangle-based mesh
- DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
- }
-
- // store the name of the group
- const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE;
- ::memcpy(&aszGroupNameBuffer[ofs],
- groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE);
-
- // make sure '\0' is at the end
- aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0';
-
- // read all skins
- sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins);
- sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() +
- groupInfo.pcGroup->numskins,false);
-
- for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) {
- ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats);
- }
- // if we have absolutely no skin loaded we need to generate a default material
- if (sharedData.pcMats.empty()) {
- const int iMode = (int)aiShadingMode_Gouraud;
- sharedData.pcMats.push_back(new aiMaterial());
- aiMaterial* pcHelper = (aiMaterial*)sharedData.pcMats[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- aiString szName;
- szName.Set(AI_DEFAULT_MATERIAL_NAME);
- pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
-
- sharedData.abNeedMaterials.resize(1,false);
- }
-
- // now get a pointer to all texture coords in the group
- groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent;
- for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){
- AI_SWAP4(groupInfo.pcGroupUVs[i].u);
- AI_SWAP4(groupInfo.pcGroupUVs[i].v);
- }
- szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts;
-
- // now get a pointer to all triangle in the group
- groupInfo.pcGroupTris = (Triangle_MDL7*)szCurrent;
- szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris;
-
- // now get a pointer to all vertices in the group
- groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent;
- for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){
- AI_SWAP4(groupInfo.pcGroupVerts[i].x);
- AI_SWAP4(groupInfo.pcGroupVerts[i].y);
- AI_SWAP4(groupInfo.pcGroupVerts[i].z);
-
- AI_SWAP2(groupInfo.pcGroupVerts[i].vertindex);
- //We can not swap the normal information now as we don't know which of the two kinds it is
- }
- szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts;
- VALIDATE_FILE_SIZE(szCurrent);
-
- MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData,avOutList[iGroup]);
- MDL::IntGroupData_MDL7 groupData;
- if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts)
- {
- // build output vectors
- const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3;
- groupData.vPositions.resize(iNumVertices);
- groupData.vNormals.resize(iNumVertices);
-
- if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,UINT_MAX);
-
- // it is also possible that there are 0 UV coordinate sets
- if (groupInfo.pcGroup->num_stpts){
- groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
-
- // check whether the triangle data structure is large enough
- // to contain a second UV coodinate set
- if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
- groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
- groupData.bNeed2UV = true;
- }
- }
- groupData.pcFaces = new MDL::IntFace_MDL7[groupInfo.pcGroup->numtris];
-
- // read all faces into the preallocated arrays
- ReadFaces_3DGS_MDL7(groupInfo, groupData);
-
- // sort by materials
- SortByMaterials_3DGS_MDL7(groupInfo, groupData,
- splitGroupData);
-
- for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) {
- if (!splitGroupData.aiSplit[qq]->empty())
- sharedData.abNeedMaterials[qq] = true;
+ ai_assert(NULL != pScene);
+
+ MDL::IntSharedData_MDL7 sharedData;
+
+ // current cursor position in the file
+ BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer;
+ const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
+
+ AI_SWAP4(pcHeader->version);
+ AI_SWAP4(pcHeader->bones_num);
+ AI_SWAP4(pcHeader->groups_num);
+ AI_SWAP4(pcHeader->data_size);
+ AI_SWAP4(pcHeader->entlump_size);
+ AI_SWAP4(pcHeader->medlump_size);
+ AI_SWAP2(pcHeader->bone_stc_size);
+ AI_SWAP2(pcHeader->skin_stc_size);
+ AI_SWAP2(pcHeader->colorvalue_stc_size);
+ AI_SWAP2(pcHeader->material_stc_size);
+ AI_SWAP2(pcHeader->skinpoint_stc_size);
+ AI_SWAP2(pcHeader->triangle_stc_size);
+ AI_SWAP2(pcHeader->mainvertex_stc_size);
+ AI_SWAP2(pcHeader->framevertex_stc_size);
+ AI_SWAP2(pcHeader->bonetrans_stc_size);
+ AI_SWAP2(pcHeader->frame_stc_size);
+
+ // validate the header of the file. There are some structure
+ // sizes that are expected by the loader to be constant
+ this->ValidateHeader_3DGS_MDL7(pcHeader);
+
+ // load all bones (they are shared by all groups, so
+ // we'll need to add them to all groups/meshes later)
+ // apcBonesOut is a list of all bones or NULL if they could not been loaded
+ szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
+ sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
+
+ // vector to held all created meshes
+ std::vector<aiMesh*>* avOutList;
+
+ // 3 meshes per group - that should be OK for most models
+ avOutList = new std::vector<aiMesh*>[pcHeader->groups_num];
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i)
+ avOutList[i].reserve(3);
+
+ // buffer to held the names of all groups in the file
+ const size_t buffersize( AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num );
+ char* aszGroupNameBuffer = new char[ buffersize ];
+
+ // read all groups
+ for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) {
+ MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup);
+ szCurrent = (const unsigned char*)(groupInfo.pcGroup+1);
+
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ AI_SWAP4(groupInfo.pcGroup->groupdata_size);
+ AI_SWAP4(groupInfo.pcGroup->numskins);
+ AI_SWAP4(groupInfo.pcGroup->num_stpts);
+ AI_SWAP4(groupInfo.pcGroup->numtris);
+ AI_SWAP4(groupInfo.pcGroup->numverts);
+ AI_SWAP4(groupInfo.pcGroup->numframes);
+
+ if (1 != groupInfo.pcGroup->typ) {
+ // Not a triangle-based mesh
+ DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
+ }
+
+ // store the name of the group
+ const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE;
+ ::memcpy(&aszGroupNameBuffer[ofs],
+ groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE);
+
+ // make sure '\0' is at the end
+ aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0';
+
+ // read all skins
+ sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins);
+ sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() +
+ groupInfo.pcGroup->numskins,false);
+
+ for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) {
+ ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats);
+ }
+ // if we have absolutely no skin loaded we need to generate a default material
+ if (sharedData.pcMats.empty()) {
+ const int iMode = (int)aiShadingMode_Gouraud;
+ sharedData.pcMats.push_back(new aiMaterial());
+ aiMaterial* pcHelper = (aiMaterial*)sharedData.pcMats[0];
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.6f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString szName;
+ szName.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+
+ sharedData.abNeedMaterials.resize(1,false);
+ }
+
+ // now get a pointer to all texture coords in the group
+ groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent;
+ for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){
+ AI_SWAP4(groupInfo.pcGroupUVs[i].u);
+ AI_SWAP4(groupInfo.pcGroupUVs[i].v);
+ }
+ szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts;
+
+ // now get a pointer to all triangle in the group
+ groupInfo.pcGroupTris = (Triangle_MDL7*)szCurrent;
+ szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris;
+
+ // now get a pointer to all vertices in the group
+ groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent;
+ for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){
+ AI_SWAP4(groupInfo.pcGroupVerts[i].x);
+ AI_SWAP4(groupInfo.pcGroupVerts[i].y);
+ AI_SWAP4(groupInfo.pcGroupVerts[i].z);
+
+ AI_SWAP2(groupInfo.pcGroupVerts[i].vertindex);
+ //We can not swap the normal information now as we don't know which of the two kinds it is
+ }
+ szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts;
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData,avOutList[iGroup]);
+ MDL::IntGroupData_MDL7 groupData;
+ if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts)
+ {
+ // build output vectors
+ const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3;
+ groupData.vPositions.resize(iNumVertices);
+ groupData.vNormals.resize(iNumVertices);
+
+ if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,UINT_MAX);
+
+ // it is also possible that there are 0 UV coordinate sets
+ if (groupInfo.pcGroup->num_stpts){
+ groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
+
+ // check whether the triangle data structure is large enough
+ // to contain a second UV coodinate set
+ if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) {
+ groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
+ groupData.bNeed2UV = true;
+ }
+ }
+ groupData.pcFaces = new MDL::IntFace_MDL7[groupInfo.pcGroup->numtris];
+
+ // read all faces into the preallocated arrays
+ ReadFaces_3DGS_MDL7(groupInfo, groupData);
+
+ // sort by materials
+ SortByMaterials_3DGS_MDL7(groupInfo, groupData,
+ splitGroupData);
+
+ for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) {
+ if (!splitGroupData.aiSplit[qq]->empty())
+ sharedData.abNeedMaterials[qq] = true;
+ }
+ }
+ else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
+ "vertices or faces. It will be skipped.");
+
+ // process all frames and generate output meshes
+ ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
+ GenerateOutputMeshes_3DGS_MDL7(groupData,splitGroupData);
+ }
+
+ // generate a nodegraph and subnodes for each group
+ pScene->mRootNode = new aiNode();
+
+ // now we need to build a final mesh list
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i)
+ pScene->mNumMeshes += (unsigned int)avOutList[i].size();
+
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; {
+ unsigned int p = 0,q = 0;
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
+ for (unsigned int a = 0; a < avOutList[i].size();++a) {
+ pScene->mMeshes[p++] = avOutList[i][a];
+ }
+ if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren;
+ }
+ // we will later need an extra node to serve as parent for all bones
+ if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren;
+ this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+ p = 0;
+ for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
+ if (avOutList[i].empty())continue;
+
+ aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode();
+ pcNode->mNumMeshes = (unsigned int)avOutList[i].size();
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+ pcNode->mParent = this->pScene->mRootNode;
+ for (unsigned int a = 0; a < pcNode->mNumMeshes;++a)
+ pcNode->mMeshes[a] = q + a;
+ q += (unsigned int)avOutList[i].size();
+
+ // setup the name of the node
+ char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
+ if ('\0' == *szBuffer) {
+ const size_t maxSize(buffersize - (i*AI_MDL7_MAX_GROUPNAMESIZE));
+ pcNode->mName.length = ai_snprintf(szBuffer, maxSize, "Group_%u", p);
+ } else {
+ pcNode->mName.length = ::strlen(szBuffer);
}
- }
- else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
- "vertices or faces. It will be skipped.");
-
- // process all frames and generate output meshes
- ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent);
- GenerateOutputMeshes_3DGS_MDL7(groupData,splitGroupData);
- }
-
- // generate a nodegraph and subnodes for each group
- pScene->mRootNode = new aiNode();
-
- // now we need to build a final mesh list
- for (uint32_t i = 0; i < pcHeader->groups_num;++i)
- pScene->mNumMeshes += (unsigned int)avOutList[i].size();
-
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; {
- unsigned int p = 0,q = 0;
- for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
- for (unsigned int a = 0; a < avOutList[i].size();++a) {
- pScene->mMeshes[p++] = avOutList[i][a];
- }
- if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren;
- }
- // we will later need an extra node to serve as parent for all bones
- if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren;
- this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
- p = 0;
- for (uint32_t i = 0; i < pcHeader->groups_num;++i) {
- if (avOutList[i].empty())continue;
-
- aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode();
- pcNode->mNumMeshes = (unsigned int)avOutList[i].size();
- pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
- pcNode->mParent = this->pScene->mRootNode;
- for (unsigned int a = 0; a < pcNode->mNumMeshes;++a)
- pcNode->mMeshes[a] = q + a;
- q += (unsigned int)avOutList[i].size();
-
- // setup the name of the node
- char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE];
- if ('\0' == *szBuffer)
- pcNode->mName.length = ::sprintf(szBuffer,"Group_%i",p);
- else pcNode->mName.length = ::strlen(szBuffer);
- ::strcpy(pcNode->mName.data,szBuffer);
- ++p;
- }
- }
-
- // if there is only one root node with a single child we can optimize it a bit ...
- if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
- aiNode* pcOldRoot = this->pScene->mRootNode;
- pScene->mRootNode = pcOldRoot->mChildren[0];
- pcOldRoot->mChildren[0] = NULL;
- delete pcOldRoot;
- pScene->mRootNode->mParent = NULL;
- }
- else pScene->mRootNode->mName.Set("<mesh_root>");
-
- delete[] avOutList;
- delete[] aszGroupNameBuffer;
- AI_DEBUG_INVALIDATE_PTR(avOutList);
- AI_DEBUG_INVALIDATE_PTR(aszGroupNameBuffer);
-
- // build a final material list.
- CopyMaterials_3DGS_MDL7(sharedData);
- HandleMaterialReferences_3DGS_MDL7();
-
- // generate output bone animations and add all bones to the scenegraph
- if (sharedData.apcOutBones) {
- // this step adds empty dummy bones to the nodegraph
- // insert another dummy node to avoid name conflicts
- aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode();
-
- pc->mName.Set("<skeleton_root>");
-
- // add bones to the nodegraph
- AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
- sharedData.apcOutBones,pc,0xffff);
-
- // this steps build a valid output animation
- BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
- sharedData.apcOutBones);
- }
+ ::strcpy(pcNode->mName.data,szBuffer);
+ ++p;
+ }
+ }
+
+ // if there is only one root node with a single child we can optimize it a bit ...
+ if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
+ aiNode* pcOldRoot = this->pScene->mRootNode;
+ pScene->mRootNode = pcOldRoot->mChildren[0];
+ pcOldRoot->mChildren[0] = NULL;
+ delete pcOldRoot;
+ pScene->mRootNode->mParent = NULL;
+ }
+ else pScene->mRootNode->mName.Set("<mesh_root>");
+
+ delete[] avOutList;
+ delete[] aszGroupNameBuffer;
+ AI_DEBUG_INVALIDATE_PTR(avOutList);
+ AI_DEBUG_INVALIDATE_PTR(aszGroupNameBuffer);
+
+ // build a final material list.
+ CopyMaterials_3DGS_MDL7(sharedData);
+ HandleMaterialReferences_3DGS_MDL7();
+
+ // generate output bone animations and add all bones to the scenegraph
+ if (sharedData.apcOutBones) {
+ // this step adds empty dummy bones to the nodegraph
+ // insert another dummy node to avoid name conflicts
+ aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode();
+
+ pc->mName.Set("<skeleton_root>");
+
+ // add bones to the nodegraph
+ AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
+ sharedData.apcOutBones,pc,0xffff);
+
+ // this steps build a valid output animation
+ BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **)
+ sharedData.apcOutBones);
+ }
}
// ------------------------------------------------------------------------------------------------
// Copy materials
void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
{
- pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- pScene->mMaterials[i] = shared.pcMats[i];
+ pScene->mNumMaterials = (unsigned int)shared.pcMats.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ pScene->mMaterials[i] = shared.pcMats[i];
}
@@ -1587,356 +1614,356 @@ void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared)
// Process material references
void MDLImporter::HandleMaterialReferences_3DGS_MDL7()
{
- // search for referrer materials
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
- int iIndex = 0;
- if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) {
- for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
- aiMesh* const pcMesh = pScene->mMeshes[a];
- if (i == pcMesh->mMaterialIndex) {
- pcMesh->mMaterialIndex = iIndex;
- }
- }
- // collapse the rest of the array
- delete pScene->mMaterials[i];
- for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) {
-
- pScene->mMaterials[pp] = pScene->mMaterials[pp+1];
- for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
- aiMesh* const pcMesh = pScene->mMeshes[a];
- if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex;
- }
- }
- --pScene->mNumMaterials;
- }
- }
+ // search for referrer materials
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ int iIndex = 0;
+ if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) {
+ for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
+ aiMesh* const pcMesh = pScene->mMeshes[a];
+ if (i == pcMesh->mMaterialIndex) {
+ pcMesh->mMaterialIndex = iIndex;
+ }
+ }
+ // collapse the rest of the array
+ delete pScene->mMaterials[i];
+ for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) {
+
+ pScene->mMaterials[pp] = pScene->mMaterials[pp+1];
+ for (unsigned int a = 0; a < pScene->mNumMeshes;++a) {
+ aiMesh* const pcMesh = pScene->mMeshes[a];
+ if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex;
+ }
+ }
+ --pScene->mNumMaterials;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Read bone transformation keys
void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- IntFrameInfo_MDL7& frame,
- MDL::IntSharedData_MDL7& shared)
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ IntFrameInfo_MDL7& frame,
+ MDL::IntSharedData_MDL7& shared)
{
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
-
- // only the first group contains bone animation keys
- if (frame.pcFrame->transmatrix_count) {
- if (!groupInfo.iIndex) {
- // skip all frames vertices. We can't support them
- const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*)
- (((const char*)frame.pcFrame) + pcHeader->frame_stc_size +
- frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size);
-
- // read all transformation matrices
- for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) {
- if(pcBoneTransforms->bone_index >= pcHeader->bones_num) {
- DefaultLogger::get()->warn("Index overflow in frame area. "
- "Unable to parse this bone transformation");
- }
- else {
- AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex,
- pcBoneTransforms,shared.apcOutBones);
- }
- pcBoneTransforms = (const MDL::BoneTransform_MDL7*)(
- (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size);
- }
- }
- else {
- DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0");
- }
- }
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+
+ // only the first group contains bone animation keys
+ if (frame.pcFrame->transmatrix_count) {
+ if (!groupInfo.iIndex) {
+ // skip all frames vertices. We can't support them
+ const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*)
+ (((const char*)frame.pcFrame) + pcHeader->frame_stc_size +
+ frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size);
+
+ // read all transformation matrices
+ for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) {
+ if(pcBoneTransforms->bone_index >= pcHeader->bones_num) {
+ DefaultLogger::get()->warn("Index overflow in frame area. "
+ "Unable to parse this bone transformation");
+ }
+ else {
+ AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex,
+ pcBoneTransforms,shared.apcOutBones);
+ }
+ pcBoneTransforms = (const MDL::BoneTransform_MDL7*)(
+ (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size);
+ }
+ }
+ else {
+ DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0");
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Attach bones to the output nodegraph
void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBones,
- aiNode* pcParent,uint16_t iParentIndex)
+ aiNode* pcParent,uint16_t iParentIndex)
{
- ai_assert(NULL != apcBones && NULL != pcParent);
+ ai_assert(NULL != apcBones && NULL != pcParent);
- // get a pointer to the header ...
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ // get a pointer to the header ...
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const MDL::IntBone_MDL7** apcBones2 = apcBones;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ const MDL::IntBone_MDL7** apcBones2 = apcBones;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- const MDL::IntBone_MDL7* const pcBone = *apcBones2++;
- if (pcBone->iParent == iParentIndex) {
- ++pcParent->mNumChildren;
- }
- }
- pcParent->mChildren = new aiNode*[pcParent->mNumChildren];
- unsigned int qq = 0;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ const MDL::IntBone_MDL7* const pcBone = *apcBones2++;
+ if (pcBone->iParent == iParentIndex) {
+ ++pcParent->mNumChildren;
+ }
+ }
+ pcParent->mChildren = new aiNode*[pcParent->mNumChildren];
+ unsigned int qq = 0;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- const MDL::IntBone_MDL7* const pcBone = *apcBones++;
- if (pcBone->iParent != iParentIndex)continue;
+ const MDL::IntBone_MDL7* const pcBone = *apcBones++;
+ if (pcBone->iParent != iParentIndex)continue;
- aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode();
- pcNode->mName = aiString( pcBone->mName );
+ aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode();
+ pcNode->mName = aiString( pcBone->mName );
- AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i);
- }
+ AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i);
+ }
}
// ------------------------------------------------------------------------------------------------
// Build output animations
void MDLImporter::BuildOutputAnims_3DGS_MDL7(
- const MDL::IntBone_MDL7** apcBonesOut)
+ const MDL::IntBone_MDL7** apcBonesOut)
{
- ai_assert(NULL != apcBonesOut);
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer;
-
- // one animation ...
- aiAnimation* pcAnim = new aiAnimation();
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- if (!apcBonesOut[i]->pkeyPositions.empty()) {
-
- // get the last frame ... (needn't be equal to pcHeader->frames_num)
- for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) {
- pcAnim->mDuration = std::max(pcAnim->mDuration, (double)
- apcBonesOut[i]->pkeyPositions[qq].mTime);
- }
- ++pcAnim->mNumChannels;
- }
- }
- if (pcAnim->mDuration) {
- pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels];
-
- unsigned int iCnt = 0;
- for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
- if (!apcBonesOut[i]->pkeyPositions.empty()) {
- const MDL::IntBone_MDL7* const intBone = apcBonesOut[i];
-
- aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim();
- pcNodeAnim->mNodeName = aiString( intBone->mName );
-
- // allocate enough storage for all keys
- pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
- pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size();
- pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();
-
- pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
- pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
- pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys];
-
- // copy all keys
- for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) {
- pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq];
- pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq];
- pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq];
- }
- }
- }
-
- // store the output animation
- pScene->mNumAnimations = 1;
- pScene->mAnimations = new aiAnimation*[1];
- pScene->mAnimations[0] = pcAnim;
- }
- else delete pcAnim;
+ ai_assert(NULL != apcBonesOut);
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer;
+
+ // one animation ...
+ aiAnimation* pcAnim = new aiAnimation();
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ if (!apcBonesOut[i]->pkeyPositions.empty()) {
+
+ // get the last frame ... (needn't be equal to pcHeader->frames_num)
+ for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) {
+ pcAnim->mDuration = std::max(pcAnim->mDuration, (double)
+ apcBonesOut[i]->pkeyPositions[qq].mTime);
+ }
+ ++pcAnim->mNumChannels;
+ }
+ }
+ if (pcAnim->mDuration) {
+ pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels];
+
+ unsigned int iCnt = 0;
+ for (uint32_t i = 0; i < pcHeader->bones_num;++i) {
+ if (!apcBonesOut[i]->pkeyPositions.empty()) {
+ const MDL::IntBone_MDL7* const intBone = apcBonesOut[i];
+
+ aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim();
+ pcNodeAnim->mNodeName = aiString( intBone->mName );
+
+ // allocate enough storage for all keys
+ pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size();
+ pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size();
+ pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size();
+
+ pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
+ pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys];
+ pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys];
+
+ // copy all keys
+ for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) {
+ pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq];
+ pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq];
+ pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq];
+ }
+ }
+ }
+
+ // store the output animation
+ pScene->mNumAnimations = 1;
+ pScene->mAnimations = new aiAnimation*[1];
+ pScene->mAnimations[0] = pcAnim;
+ }
+ else delete pcAnim;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
- const MDL::BoneTransform_MDL7* pcBoneTransforms,
- MDL::IntBone_MDL7** apcBonesOut)
+ const MDL::BoneTransform_MDL7* pcBoneTransforms,
+ MDL::IntBone_MDL7** apcBonesOut)
{
- ai_assert(NULL != pcBoneTransforms);
- ai_assert(NULL != apcBonesOut);
-
- // first .. get the transformation matrix
- aiMatrix4x4 mTransform;
- mTransform.a1 = pcBoneTransforms->m[0];
- mTransform.b1 = pcBoneTransforms->m[1];
- mTransform.c1 = pcBoneTransforms->m[2];
- mTransform.d1 = pcBoneTransforms->m[3];
-
- mTransform.a2 = pcBoneTransforms->m[4];
- mTransform.b2 = pcBoneTransforms->m[5];
- mTransform.c2 = pcBoneTransforms->m[6];
- mTransform.d2 = pcBoneTransforms->m[7];
-
- mTransform.a3 = pcBoneTransforms->m[8];
- mTransform.b3 = pcBoneTransforms->m[9];
- mTransform.c3 = pcBoneTransforms->m[10];
- mTransform.d3 = pcBoneTransforms->m[11];
-
- // now decompose the transformation matrix into separate
- // scaling, rotation and translation
- aiVectorKey vScaling,vPosition;
- aiQuatKey qRotation;
-
- // FIXME: Decompose will assert in debug builds if the matrix is invalid ...
- mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue);
-
- // now generate keys
- vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo;
-
- // add the keys to the bone
- MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index];
- pcBoneOut->pkeyPositions.push_back ( vPosition );
- pcBoneOut->pkeyScalings.push_back ( vScaling );
- pcBoneOut->pkeyRotations.push_back ( qRotation );
+ ai_assert(NULL != pcBoneTransforms);
+ ai_assert(NULL != apcBonesOut);
+
+ // first .. get the transformation matrix
+ aiMatrix4x4 mTransform;
+ mTransform.a1 = pcBoneTransforms->m[0];
+ mTransform.b1 = pcBoneTransforms->m[1];
+ mTransform.c1 = pcBoneTransforms->m[2];
+ mTransform.d1 = pcBoneTransforms->m[3];
+
+ mTransform.a2 = pcBoneTransforms->m[4];
+ mTransform.b2 = pcBoneTransforms->m[5];
+ mTransform.c2 = pcBoneTransforms->m[6];
+ mTransform.d2 = pcBoneTransforms->m[7];
+
+ mTransform.a3 = pcBoneTransforms->m[8];
+ mTransform.b3 = pcBoneTransforms->m[9];
+ mTransform.c3 = pcBoneTransforms->m[10];
+ mTransform.d3 = pcBoneTransforms->m[11];
+
+ // now decompose the transformation matrix into separate
+ // scaling, rotation and translation
+ aiVectorKey vScaling,vPosition;
+ aiQuatKey qRotation;
+
+ // FIXME: Decompose will assert in debug builds if the matrix is invalid ...
+ mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue);
+
+ // now generate keys
+ vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo;
+
+ // add the keys to the bone
+ MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index];
+ pcBoneOut->pkeyPositions.push_back ( vPosition );
+ pcBoneOut->pkeyScalings.push_back ( vScaling );
+ pcBoneOut->pkeyRotations.push_back ( qRotation );
}
// ------------------------------------------------------------------------------------------------
// Construct output meshes
void MDLImporter::GenerateOutputMeshes_3DGS_MDL7(
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData)
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData)
{
- const MDL::IntSharedData_MDL7& shared = splitGroupData.shared;
-
- // get a pointer to the header ...
- const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
- const unsigned int iNumOutBones = pcHeader->bones_num;
-
- for (std::vector<aiMaterial*>::size_type i = 0; i < shared.pcMats.size();++i) {
- if (!splitGroupData.aiSplit[i]->empty()) {
-
- // allocate the output mesh
- aiMesh* pcMesh = new aiMesh();
-
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- pcMesh->mMaterialIndex = (unsigned int)i;
-
- // allocate output storage
- pcMesh->mNumFaces = (unsigned int)splitGroupData.aiSplit[i]->size();
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- pcMesh->mNumVertices = pcMesh->mNumFaces*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
-
- if (!groupData.vTextureCoords1.empty()) {
- pcMesh->mNumUVComponents[0] = 2;
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- if (!groupData.vTextureCoords2.empty()) {
- pcMesh->mNumUVComponents[1] = 2;
- pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
- }
- }
-
- // iterate through all faces and build an unique set of vertices
- unsigned int iCurrent = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
- pcMesh->mFaces[iFace].mNumIndices = 3;
- pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
-
- unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
- const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
-
- // iterate through all face indices
- for (unsigned int c = 0; c < 3;++c) {
- const uint32_t iIndex = oldFace.mIndices[c];
- pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex];
- pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex];
-
- if (!groupData.vTextureCoords1.empty()) {
-
- pcMesh->mTextureCoords[0][iCurrent] = groupData.vTextureCoords1[iIndex];
- if (!groupData.vTextureCoords2.empty()) {
- pcMesh->mTextureCoords[1][iCurrent] = groupData.vTextureCoords2[iIndex];
- }
- }
- pcMesh->mFaces[iFace].mIndices[c] = iCurrent++;
- }
- }
-
- // if we have bones in the mesh we'll need to generate
- // proper vertex weights for them
- if (!groupData.aiBones.empty()) {
- std::vector<std::vector<unsigned int> > aaiVWeightList;
- aaiVWeightList.resize(iNumOutBones);
-
- int iCurrent = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
- unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
- const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
-
- // iterate through all face indices
- for (unsigned int c = 0; c < 3;++c) {
- unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ];
- if (UINT_MAX != iBone) {
- if (iBone >= iNumOutBones) {
- DefaultLogger::get()->error("Bone index overflow. "
- "The bone index of a vertex exceeds the allowed range. ");
- iBone = iNumOutBones-1;
- }
- aaiVWeightList[ iBone ].push_back ( iCurrent );
- }
- ++iCurrent;
- }
- }
- // now check which bones are required ...
- for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) {
- if (!(*k).empty()) {
- ++pcMesh->mNumBones;
- }
- }
- pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
- iCurrent = 0;
- for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent)
- {
- if ((*k).empty())
- continue;
-
- // seems we'll need this node
- aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone();
- pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName);
- pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix;
-
- // setup vertex weights
- pcBone->mNumWeights = (unsigned int)(*k).size();
- pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights];
-
- for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) {
- pcBone->mWeights[weight].mVertexId = (*k)[weight];
- pcBone->mWeights[weight].mWeight = 1.0f;
- }
- }
- }
- // add the mesh to the list of output meshes
- splitGroupData.avOutList.push_back(pcMesh);
- }
- }
+ const MDL::IntSharedData_MDL7& shared = splitGroupData.shared;
+
+ // get a pointer to the header ...
+ const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer;
+ const unsigned int iNumOutBones = pcHeader->bones_num;
+
+ for (std::vector<aiMaterial*>::size_type i = 0; i < shared.pcMats.size();++i) {
+ if (!splitGroupData.aiSplit[i]->empty()) {
+
+ // allocate the output mesh
+ aiMesh* pcMesh = new aiMesh();
+
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ pcMesh->mMaterialIndex = (unsigned int)i;
+
+ // allocate output storage
+ pcMesh->mNumFaces = (unsigned int)splitGroupData.aiSplit[i]->size();
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ pcMesh->mNumVertices = pcMesh->mNumFaces*3;
+ pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+
+ if (!groupData.vTextureCoords1.empty()) {
+ pcMesh->mNumUVComponents[0] = 2;
+ pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ if (!groupData.vTextureCoords2.empty()) {
+ pcMesh->mNumUVComponents[1] = 2;
+ pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
+ }
+ }
+
+ // iterate through all faces and build an unique set of vertices
+ unsigned int iCurrent = 0;
+ for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
+ pcMesh->mFaces[iFace].mNumIndices = 3;
+ pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
+
+ unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
+ const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
+
+ // iterate through all face indices
+ for (unsigned int c = 0; c < 3;++c) {
+ const uint32_t iIndex = oldFace.mIndices[c];
+ pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex];
+ pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex];
+
+ if (!groupData.vTextureCoords1.empty()) {
+
+ pcMesh->mTextureCoords[0][iCurrent] = groupData.vTextureCoords1[iIndex];
+ if (!groupData.vTextureCoords2.empty()) {
+ pcMesh->mTextureCoords[1][iCurrent] = groupData.vTextureCoords2[iIndex];
+ }
+ }
+ pcMesh->mFaces[iFace].mIndices[c] = iCurrent++;
+ }
+ }
+
+ // if we have bones in the mesh we'll need to generate
+ // proper vertex weights for them
+ if (!groupData.aiBones.empty()) {
+ std::vector<std::vector<unsigned int> > aaiVWeightList;
+ aaiVWeightList.resize(iNumOutBones);
+
+ int iCurrent = 0;
+ for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) {
+ unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace);
+ const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace];
+
+ // iterate through all face indices
+ for (unsigned int c = 0; c < 3;++c) {
+ unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ];
+ if (UINT_MAX != iBone) {
+ if (iBone >= iNumOutBones) {
+ DefaultLogger::get()->error("Bone index overflow. "
+ "The bone index of a vertex exceeds the allowed range. ");
+ iBone = iNumOutBones-1;
+ }
+ aaiVWeightList[ iBone ].push_back ( iCurrent );
+ }
+ ++iCurrent;
+ }
+ }
+ // now check which bones are required ...
+ for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) {
+ if (!(*k).empty()) {
+ ++pcMesh->mNumBones;
+ }
+ }
+ pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
+ iCurrent = 0;
+ for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent)
+ {
+ if ((*k).empty())
+ continue;
+
+ // seems we'll need this node
+ aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone();
+ pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName);
+ pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix;
+
+ // setup vertex weights
+ pcBone->mNumWeights = (unsigned int)(*k).size();
+ pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights];
+
+ for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) {
+ pcBone->mWeights[weight].mVertexId = (*k)[weight];
+ pcBone->mWeights[weight].mWeight = 1.0f;
+ }
+ }
+ }
+ // add the mesh to the list of output meshes
+ splitGroupData.avOutList.push_back(pcMesh);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Join to materials
void MDLImporter::JoinSkins_3DGS_MDL7(
- aiMaterial* pcMat1,
- aiMaterial* pcMat2,
- aiMaterial* pcMatOut)
+ aiMaterial* pcMat1,
+ aiMaterial* pcMat2,
+ aiMaterial* pcMatOut)
{
- ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut);
-
- // first create a full copy of the first skin property set
- // and assign it to the output material
- aiMaterial::CopyPropertyList(pcMatOut,pcMat1);
-
- int iVal = 0;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
-
- // then extract the diffuse texture from the second skin,
- // setup 1 as UV source and we have it
- aiString sString;
- if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) {
- iVal = 1;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
- pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
- }
+ ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut);
+
+ // first create a full copy of the first skin property set
+ // and assign it to the output material
+ aiMaterial::CopyPropertyList(pcMatOut,pcMat1);
+
+ int iVal = 0;
+ pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
+
+ // then extract the diffuse texture from the second skin,
+ // setup 1 as UV source and we have it
+ aiString sString;
+ if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) {
+ iVal = 1;
+ pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
+ pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a half-life 2 MDL
void MDLImporter::InternReadFile_HL2( )
{
- //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer;
- throw DeadlyImportError("HL2 MDLs are not implemented");
+ //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer;
+ throw DeadlyImportError("HL2 MDLs are not implemented");
}
#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER
diff --git a/src/3rdparty/assimp/code/MDLLoader.h b/src/3rdparty/assimp/code/MDLLoader.h
index 7003ea803..62e451cbe 100644
--- a/src/3rdparty/assimp/code/MDLLoader.h
+++ b/src/3rdparty/assimp/code/MDLLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MDLLOADER_H_INCLUDED
#include "BaseImporter.h"
-
-struct aiNode;
#include "MDLFileData.h"
#include "HalfLifeFileData.h"
-namespace Assimp {
+struct aiNode;
+struct aiTexture;
+
+namespace Assimp {
using namespace MDL;
@@ -60,9 +61,9 @@ using namespace MDL;
// --------------------------------------------------------------------------------------
// Include file/line information in debug builds
#ifdef ASSIMP_BUILD_DEBUG
-# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg,__FILE__,__LINE__)
+# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg,__FILE__,__LINE__)
#else
-# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg)
+# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg)
#endif
// --------------------------------------------------------------------------------------
@@ -83,372 +84,372 @@ using namespace MDL;
class MDLImporter : public BaseImporter
{
public:
- MDLImporter();
- ~MDLImporter();
+ MDLImporter();
+ ~MDLImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Import a quake 1 MDL file (IDPO)
- */
- void InternReadFile_Quake1( );
-
- // -------------------------------------------------------------------
- /** Import a GameStudio A4/A5 file (MDL 3,4,5)
- */
- void InternReadFile_3DGS_MDL345( );
-
- // -------------------------------------------------------------------
- /** Import a GameStudio A7 file (MDL 7)
- */
- void InternReadFile_3DGS_MDL7( );
-
- // -------------------------------------------------------------------
- /** Import a CS:S/HL2 MDL file (not fully implemented)
- */
- void InternReadFile_HL2( );
-
- // -------------------------------------------------------------------
- /** Check whether a given position is inside the valid range
- * Throw a DeadlyImportError if it is not
- * \param szPos Cursor position
- * \param szFile Name of the source file from which the function was called
- * \param iLine Source code line from which the function was called
- */
- void SizeCheck(const void* szPos);
- void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
-
-
- // -------------------------------------------------------------------
- /** Validate the header data structure of a game studio MDL7 file
- * \param pcHeader Input header to be validated
- */
- void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader);
-
- // -------------------------------------------------------------------
- /** Validate the header data structure of a Quake 1 model
- * \param pcHeader Input header to be validated
- */
- void ValidateHeader_Quake1(const MDL::Header* pcHeader);
-
-
- // -------------------------------------------------------------------
- /** Try to load a palette from the current directory (colormap.lmp)
- * If it is not found the default palette of Quake1 is returned
- */
- void SearchPalette(const unsigned char** pszColorMap);
-
- // -------------------------------------------------------------------
- /** Free a palette created with a previous call to SearchPalette()
- */
- void FreePalette(const unsigned char* pszColorMap);
-
-
- // -------------------------------------------------------------------
- /** Load a paletized texture from the file and convert it to 32bpp
- */
- void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
-
- // -------------------------------------------------------------------
- /** Used to load textures from MDL3/4
- * \param szData Input data
- * \param iType Color data type
- * \param piSkip Receive: Size to skip, in bytes
- */
- void CreateTexture_3DGS_MDL4(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip);
-
-
- // -------------------------------------------------------------------
- /** Used to load textures from MDL5
- * \param szData Input data
- * \param iType Color data type
- * \param piSkip Receive: Size to skip, in bytes
- */
- void CreateTexture_3DGS_MDL5(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip);
-
-
- // -------------------------------------------------------------------
- /** Checks whether a texture can be replaced with a single color
- * This is useful for all file formats before MDL7 (all those
- * that are not containing material colors separate from textures).
- * MED seems to write dummy 8x8 monochrome images instead.
- * \param pcTexture Input texture
- * \return aiColor.r is set to qnan if the function fails and no
- * color can be found.
- */
- aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
-
-
- // -------------------------------------------------------------------
- /** Converts the absolute texture coordinates in MDL5 files to
- * relative in a range between 0 and 1
- */
- void CalculateUVCoordinates_MDL5();
-
-
- // -------------------------------------------------------------------
- /** Read an UV coordinate from the file. If the file format is not
- * MDL5, the function calculates relative texture coordinates
- * \param vOut Receives the output UV coord
- * \param pcSrc UV coordinate buffer
- * \param UV coordinate index
- */
- void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut,
- const MDL::TexCoord_MDL3* pcSrc,
- unsigned int iIndex);
-
- // -------------------------------------------------------------------
- /** Setup the material properties for Quake and MDL<7 models.
- * These formats don't support more than one material per mesh,
- * therefore the method processes only ONE skin and removes
- * all others.
- */
- void SetupMaterialProperties_3DGS_MDL5_Quake1( );
-
-
- // -------------------------------------------------------------------
- /** Parse a skin lump in a MDL7/HMP7 file with all of its features
- * variant 1: Current cursor position is the beginning of the skin header
- * \param szCurrent Current data pointer
- * \param szCurrentOut Output data pointer
- * \param pcMats Material list for this group. To be filled ...
- */
- void ParseSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- std::vector<aiMaterial*>& pcMats);
-
- // -------------------------------------------------------------------
- /** Parse a skin lump in a MDL7/HMP7 file with all of its features
- * variant 2: Current cursor position is the beginning of the skin data
- * \param szCurrent Current data pointer
- * \param szCurrentOut Output data pointer
- * \param pcMatOut Output material
- * \param iType header.typ
- * \param iWidth header.width
- * \param iHeight header.height
- */
- void ParseSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- aiMaterial* pcMatOut,
- unsigned int iType,
- unsigned int iWidth,
- unsigned int iHeight);
-
- // -------------------------------------------------------------------
- /** Skip a skin lump in a MDL7/HMP7 file
- * \param szCurrent Current data pointer
- * \param szCurrentOut Output data pointer. Points to the byte just
- * behind the last byte of the skin.
- * \param iType header.typ
- * \param iWidth header.width
- * \param iHeight header.height
- */
- void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- unsigned int iType,
- unsigned int iWidth,
- unsigned int iHeight);
-
- // -------------------------------------------------------------------
- /** Parse texture color data for MDL5, MDL6 and MDL7 formats
- * \param szData Current data pointer
- * \param iType type of the texture data. No DDS or external
- * \param piSkip Receive the number of bytes to skip
- * \param pcNew Must point to fully initialized data. Width and
- * height must be set. If pcNew->pcData is set to UINT_MAX,
- * piSkip will receive the size of the texture, in bytes, but no
- * color data will be read.
- */
- void ParseTextureColorData(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip,
- aiTexture* pcNew);
-
- // -------------------------------------------------------------------
- /** Join two materials / skins. Setup UV source ... etc
- * \param pcMat1 First input material
- * \param pcMat2 Second input material
- * \param pcMatOut Output material instance to be filled. Must be empty
- */
- void JoinSkins_3DGS_MDL7(aiMaterial* pcMat1,
- aiMaterial* pcMat2,
- aiMaterial* pcMatOut);
-
- // -------------------------------------------------------------------
- /** Add a bone transformation key to an animation
- * \param iTrafo Index of the transformation (always==frame index?)
- * No need to validate this index, it is always valid.
- * \param pcBoneTransforms Bone transformation for this index
- * \param apcOutBones Output bones array
- */
- void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
- const MDL::BoneTransform_MDL7* pcBoneTransforms,
- MDL::IntBone_MDL7** apcBonesOut);
-
- // -------------------------------------------------------------------
- /** Load the bone list of a MDL7 file
- * \return If the bones could be loaded successfully, a valid
- * array containing pointers to a temporary bone
- * representation. NULL if the bones could not be loaded.
- */
- MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
-
- // -------------------------------------------------------------------
- /** Load bone transformation keyframes from a file chunk
- * \param groupInfo -> doc of data structure
- * \param frame -> doc of data structure
- * \param shared -> doc of data structure
- */
- void ParseBoneTrafoKeys_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- IntFrameInfo_MDL7& frame,
- MDL::IntSharedData_MDL7& shared);
-
- // -------------------------------------------------------------------
- /** Calculate absolute bone animation matrices for each bone
- * \param apcOutBones Output bones array
- */
- void CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones);
-
- // -------------------------------------------------------------------
- /** Add all bones to the nodegraph (as children of the root node)
- * \param apcBonesOut List of bones
- * \param pcParent Parent node. New nodes will be added to this node
- * \param iParentIndex Index of the parent bone
- */
- void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut,
- aiNode* pcParent,uint16_t iParentIndex);
-
- // -------------------------------------------------------------------
- /** Build output animations
- * \param apcBonesOut List of bones
- */
- void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut);
-
- // -------------------------------------------------------------------
- /** Handles materials that are just referencing another material
- * There is no test file for this feature, but Conitec's doc
- * say it is used.
- */
- void HandleMaterialReferences_3DGS_MDL7();
-
- // -------------------------------------------------------------------
- /** Copies only the material that are referenced by at least one
- * mesh to the final output material list. All other materials
- * will be discarded.
- * \param shared -> doc of data structure
- */
- void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared);
-
- // -------------------------------------------------------------------
- /** Process the frame section at the end of a group
- * \param groupInfo -> doc of data structure
- * \param shared -> doc of data structure
- * \param szCurrent Pointer to the start of the frame section
- * \param szCurrentOut Receives a pointer to the first byte of the
- * next data section.
- * \return false to read no further groups (a small workaround for
- * some tiny and unsolved problems ... )
- */
- bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSharedData_MDL7& shared,
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Sort all faces by their materials. If the mesh is using
- * multiple materials per face (that are blended together) the function
- * might create new materials.
- * \param groupInfo -> doc of data structure
- * \param groupData -> doc of data structure
- * \param splitGroupData -> doc of data structure
- */
- void SortByMaterials_3DGS_MDL7(
- const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData);
-
- // -------------------------------------------------------------------
- /** Read all faces and vertices from a MDL7 group. The function fills
- * preallocated memory buffers.
- * \param groupInfo -> doc of data structure
- * \param groupData -> doc of data structure
- */
- void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
- MDL::IntGroupData_MDL7& groupData);
-
- // -------------------------------------------------------------------
- /** Generate the final output meshes for a7 models
- * \param groupData -> doc of data structure
- * \param splitGroupData -> doc of data structure
- */
- void GenerateOutputMeshes_3DGS_MDL7(
- MDL::IntGroupData_MDL7& groupData,
- MDL::IntSplitGroupData_MDL7& splitGroupData);
+ // -------------------------------------------------------------------
+ /** Import a quake 1 MDL file (IDPO)
+ */
+ void InternReadFile_Quake1( );
+
+ // -------------------------------------------------------------------
+ /** Import a GameStudio A4/A5 file (MDL 3,4,5)
+ */
+ void InternReadFile_3DGS_MDL345( );
+
+ // -------------------------------------------------------------------
+ /** Import a GameStudio A7 file (MDL 7)
+ */
+ void InternReadFile_3DGS_MDL7( );
+
+ // -------------------------------------------------------------------
+ /** Import a CS:S/HL2 MDL file (not fully implemented)
+ */
+ void InternReadFile_HL2( );
+
+ // -------------------------------------------------------------------
+ /** Check whether a given position is inside the valid range
+ * Throw a DeadlyImportError if it is not
+ * \param szPos Cursor position
+ * \param szFile Name of the source file from which the function was called
+ * \param iLine Source code line from which the function was called
+ */
+ void SizeCheck(const void* szPos);
+ void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
+
+
+ // -------------------------------------------------------------------
+ /** Validate the header data structure of a game studio MDL7 file
+ * \param pcHeader Input header to be validated
+ */
+ void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader);
+
+ // -------------------------------------------------------------------
+ /** Validate the header data structure of a Quake 1 model
+ * \param pcHeader Input header to be validated
+ */
+ void ValidateHeader_Quake1(const MDL::Header* pcHeader);
+
+
+ // -------------------------------------------------------------------
+ /** Try to load a palette from the current directory (colormap.lmp)
+ * If it is not found the default palette of Quake1 is returned
+ */
+ void SearchPalette(const unsigned char** pszColorMap);
+
+ // -------------------------------------------------------------------
+ /** Free a palette created with a previous call to SearchPalette()
+ */
+ void FreePalette(const unsigned char* pszColorMap);
+
+
+ // -------------------------------------------------------------------
+ /** Load a paletized texture from the file and convert it to 32bpp
+ */
+ void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
+
+ // -------------------------------------------------------------------
+ /** Used to load textures from MDL3/4
+ * \param szData Input data
+ * \param iType Color data type
+ * \param piSkip Receive: Size to skip, in bytes
+ */
+ void CreateTexture_3DGS_MDL4(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip);
+
+
+ // -------------------------------------------------------------------
+ /** Used to load textures from MDL5
+ * \param szData Input data
+ * \param iType Color data type
+ * \param piSkip Receive: Size to skip, in bytes
+ */
+ void CreateTexture_3DGS_MDL5(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip);
+
+
+ // -------------------------------------------------------------------
+ /** Checks whether a texture can be replaced with a single color
+ * This is useful for all file formats before MDL7 (all those
+ * that are not containing material colors separate from textures).
+ * MED seems to write dummy 8x8 monochrome images instead.
+ * \param pcTexture Input texture
+ * \return aiColor.r is set to qnan if the function fails and no
+ * color can be found.
+ */
+ aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
+
+
+ // -------------------------------------------------------------------
+ /** Converts the absolute texture coordinates in MDL5 files to
+ * relative in a range between 0 and 1
+ */
+ void CalculateUVCoordinates_MDL5();
+
+
+ // -------------------------------------------------------------------
+ /** Read an UV coordinate from the file. If the file format is not
+ * MDL5, the function calculates relative texture coordinates
+ * \param vOut Receives the output UV coord
+ * \param pcSrc UV coordinate buffer
+ * \param UV coordinate index
+ */
+ void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut,
+ const MDL::TexCoord_MDL3* pcSrc,
+ unsigned int iIndex);
+
+ // -------------------------------------------------------------------
+ /** Setup the material properties for Quake and MDL<7 models.
+ * These formats don't support more than one material per mesh,
+ * therefore the method processes only ONE skin and removes
+ * all others.
+ */
+ void SetupMaterialProperties_3DGS_MDL5_Quake1( );
+
+
+ // -------------------------------------------------------------------
+ /** Parse a skin lump in a MDL7/HMP7 file with all of its features
+ * variant 1: Current cursor position is the beginning of the skin header
+ * \param szCurrent Current data pointer
+ * \param szCurrentOut Output data pointer
+ * \param pcMats Material list for this group. To be filled ...
+ */
+ void ParseSkinLump_3DGS_MDL7(
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ std::vector<aiMaterial*>& pcMats);
+
+ // -------------------------------------------------------------------
+ /** Parse a skin lump in a MDL7/HMP7 file with all of its features
+ * variant 2: Current cursor position is the beginning of the skin data
+ * \param szCurrent Current data pointer
+ * \param szCurrentOut Output data pointer
+ * \param pcMatOut Output material
+ * \param iType header.typ
+ * \param iWidth header.width
+ * \param iHeight header.height
+ */
+ void ParseSkinLump_3DGS_MDL7(
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ aiMaterial* pcMatOut,
+ unsigned int iType,
+ unsigned int iWidth,
+ unsigned int iHeight);
+
+ // -------------------------------------------------------------------
+ /** Skip a skin lump in a MDL7/HMP7 file
+ * \param szCurrent Current data pointer
+ * \param szCurrentOut Output data pointer. Points to the byte just
+ * behind the last byte of the skin.
+ * \param iType header.typ
+ * \param iWidth header.width
+ * \param iHeight header.height
+ */
+ void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ unsigned int iType,
+ unsigned int iWidth,
+ unsigned int iHeight);
+
+ // -------------------------------------------------------------------
+ /** Parse texture color data for MDL5, MDL6 and MDL7 formats
+ * \param szData Current data pointer
+ * \param iType type of the texture data. No DDS or external
+ * \param piSkip Receive the number of bytes to skip
+ * \param pcNew Must point to fully initialized data. Width and
+ * height must be set. If pcNew->pcData is set to UINT_MAX,
+ * piSkip will receive the size of the texture, in bytes, but no
+ * color data will be read.
+ */
+ void ParseTextureColorData(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip,
+ aiTexture* pcNew);
+
+ // -------------------------------------------------------------------
+ /** Join two materials / skins. Setup UV source ... etc
+ * \param pcMat1 First input material
+ * \param pcMat2 Second input material
+ * \param pcMatOut Output material instance to be filled. Must be empty
+ */
+ void JoinSkins_3DGS_MDL7(aiMaterial* pcMat1,
+ aiMaterial* pcMat2,
+ aiMaterial* pcMatOut);
+
+ // -------------------------------------------------------------------
+ /** Add a bone transformation key to an animation
+ * \param iTrafo Index of the transformation (always==frame index?)
+ * No need to validate this index, it is always valid.
+ * \param pcBoneTransforms Bone transformation for this index
+ * \param apcOutBones Output bones array
+ */
+ void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
+ const MDL::BoneTransform_MDL7* pcBoneTransforms,
+ MDL::IntBone_MDL7** apcBonesOut);
+
+ // -------------------------------------------------------------------
+ /** Load the bone list of a MDL7 file
+ * \return If the bones could be loaded successfully, a valid
+ * array containing pointers to a temporary bone
+ * representation. NULL if the bones could not be loaded.
+ */
+ MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
+
+ // -------------------------------------------------------------------
+ /** Load bone transformation keyframes from a file chunk
+ * \param groupInfo -> doc of data structure
+ * \param frame -> doc of data structure
+ * \param shared -> doc of data structure
+ */
+ void ParseBoneTrafoKeys_3DGS_MDL7(
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ IntFrameInfo_MDL7& frame,
+ MDL::IntSharedData_MDL7& shared);
+
+ // -------------------------------------------------------------------
+ /** Calculate absolute bone animation matrices for each bone
+ * \param apcOutBones Output bones array
+ */
+ void CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones);
+
+ // -------------------------------------------------------------------
+ /** Add all bones to the nodegraph (as children of the root node)
+ * \param apcBonesOut List of bones
+ * \param pcParent Parent node. New nodes will be added to this node
+ * \param iParentIndex Index of the parent bone
+ */
+ void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut,
+ aiNode* pcParent,uint16_t iParentIndex);
+
+ // -------------------------------------------------------------------
+ /** Build output animations
+ * \param apcBonesOut List of bones
+ */
+ void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut);
+
+ // -------------------------------------------------------------------
+ /** Handles materials that are just referencing another material
+ * There is no test file for this feature, but Conitec's doc
+ * say it is used.
+ */
+ void HandleMaterialReferences_3DGS_MDL7();
+
+ // -------------------------------------------------------------------
+ /** Copies only the material that are referenced by at least one
+ * mesh to the final output material list. All other materials
+ * will be discarded.
+ * \param shared -> doc of data structure
+ */
+ void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared);
+
+ // -------------------------------------------------------------------
+ /** Process the frame section at the end of a group
+ * \param groupInfo -> doc of data structure
+ * \param shared -> doc of data structure
+ * \param szCurrent Pointer to the start of the frame section
+ * \param szCurrentOut Receives a pointer to the first byte of the
+ * next data section.
+ * \return false to read no further groups (a small workaround for
+ * some tiny and unsolved problems ... )
+ */
+ bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSharedData_MDL7& shared,
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Sort all faces by their materials. If the mesh is using
+ * multiple materials per face (that are blended together) the function
+ * might create new materials.
+ * \param groupInfo -> doc of data structure
+ * \param groupData -> doc of data structure
+ * \param splitGroupData -> doc of data structure
+ */
+ void SortByMaterials_3DGS_MDL7(
+ const MDL::IntGroupInfo_MDL7& groupInfo,
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData);
+
+ // -------------------------------------------------------------------
+ /** Read all faces and vertices from a MDL7 group. The function fills
+ * preallocated memory buffers.
+ * \param groupInfo -> doc of data structure
+ * \param groupData -> doc of data structure
+ */
+ void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
+ MDL::IntGroupData_MDL7& groupData);
+
+ // -------------------------------------------------------------------
+ /** Generate the final output meshes for a7 models
+ * \param groupData -> doc of data structure
+ * \param splitGroupData -> doc of data structure
+ */
+ void GenerateOutputMeshes_3DGS_MDL7(
+ MDL::IntGroupData_MDL7& groupData,
+ MDL::IntSplitGroupData_MDL7& splitGroupData);
protected:
- /** Configuration option: frame to be loaded */
- unsigned int configFrameID;
+ /** Configuration option: frame to be loaded */
+ unsigned int configFrameID;
+
+ /** Configuration option: palette to be used to decode palletized images*/
+ std::string configPalette;
- /** Configuration option: palette to be used to decode palletized images*/
- std::string configPalette;
+ /** Buffer to hold the loaded file */
+ unsigned char* mBuffer;
- /** Buffer to hold the loaded file */
- unsigned char* mBuffer;
-
- /** For GameStudio MDL files: The number in the magic word, either 3,4 or 5
- * (MDL7 doesn't need this, the format has a separate loader) */
- unsigned int iGSFileVersion;
+ /** For GameStudio MDL files: The number in the magic word, either 3,4 or 5
+ * (MDL7 doesn't need this, the format has a separate loader) */
+ unsigned int iGSFileVersion;
- /** Output I/O handler. used to load external lmp files */
- IOSystem* pIOHandler;
+ /** Output I/O handler. used to load external lmp files */
+ IOSystem* pIOHandler;
- /** Output scene to be filled */
- aiScene* pScene;
+ /** Output scene to be filled */
+ aiScene* pScene;
- /** Size of the input file in bytes */
- unsigned int iFileSize;
+ /** Size of the input file in bytes */
+ unsigned int iFileSize;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/MDLMaterialLoader.cpp b/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
index 3d32420e1..d1502d6fb 100644
--- a/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
+++ b/src/3rdparty/assimp/code/MDLMaterialLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,803 +25,811 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the material part of the MDL importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
// internal headers
#include "MDLLoader.h"
#include "MDLDefaultColorMap.h"
+#include "StringUtils.h"
+#include <assimp/texture.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include "qnan.h"
+#include "Defines.h"
+
using namespace Assimp;
static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
// ------------------------------------------------------------------------------------------------
-// Find a suitable pallette file or take teh default one
+// Find a suitable pallette file or take the default one
void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
{
- // now try to find the color map in the current directory
- IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
-
- const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
- if(pcStream)
- {
- if (pcStream->FileSize() >= 768)
- {
- unsigned char* colorMap = new unsigned char[256*3];
- szColorMap = colorMap;
- pcStream->Read(colorMap,256*3,1);
- DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
- "It will be used to decode embedded textures in palletized formats.");
- }
- delete pcStream;
- pcStream = NULL;
- }
- *pszColorMap = szColorMap;
+ // now try to find the color map in the current directory
+ IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
+
+ const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
+ if(pcStream)
+ {
+ if (pcStream->FileSize() >= 768)
+ {
+ unsigned char* colorMap = new unsigned char[256*3];
+ szColorMap = colorMap;
+ pcStream->Read(colorMap,256*3,1);
+ DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
+ "It will be used to decode embedded textures in palletized formats.");
+ }
+ delete pcStream;
+ pcStream = NULL;
+ }
+ *pszColorMap = szColorMap;
}
// ------------------------------------------------------------------------------------------------
// Free the palette again
void MDLImporter::FreePalette(const unsigned char* szColorMap)
{
- if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
- delete[] szColorMap;
+ if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
+ delete[] szColorMap;
}
// ------------------------------------------------------------------------------------------------
// Check whether we can replace a texture with a single color
aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
{
- ai_assert(NULL != pcTexture);
-
- aiColor4D clrOut;
- clrOut.r = get_qnan();
- if (!pcTexture->mHeight || !pcTexture->mWidth)
- return clrOut;
-
- const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
- const aiTexel* pcTexel = pcTexture->pcData+1;
- const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
-
- while (pcTexel != pcTexelEnd)
- {
- if (*pcTexel != *(pcTexel-1))
- {
- pcTexel = NULL;
- break;
- }
- ++pcTexel;
- }
- if (pcTexel)
- {
- clrOut.r = pcTexture->pcData->r / 255.0f;
- clrOut.g = pcTexture->pcData->g / 255.0f;
- clrOut.b = pcTexture->pcData->b / 255.0f;
- clrOut.a = pcTexture->pcData->a / 255.0f;
- }
- return clrOut;
+ ai_assert(NULL != pcTexture);
+
+ aiColor4D clrOut;
+ clrOut.r = get_qnan();
+ if (!pcTexture->mHeight || !pcTexture->mWidth)
+ return clrOut;
+
+ const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
+ const aiTexel* pcTexel = pcTexture->pcData+1;
+ const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
+
+ while (pcTexel != pcTexelEnd)
+ {
+ if (*pcTexel != *(pcTexel-1))
+ {
+ pcTexel = NULL;
+ break;
+ }
+ ++pcTexel;
+ }
+ if (pcTexel)
+ {
+ clrOut.r = pcTexture->pcData->r / 255.0f;
+ clrOut.g = pcTexture->pcData->g / 255.0f;
+ clrOut.b = pcTexture->pcData->b / 255.0f;
+ clrOut.a = pcTexture->pcData->a / 255.0f;
+ }
+ return clrOut;
}
// ------------------------------------------------------------------------------------------------
// Read a texture from a MDL3 file
void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
{
- const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function
+ const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
- VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
- pcHeader->skinheight);
+ VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
+ pcHeader->skinheight);
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
- pcNew->mWidth = pcHeader->skinwidth;
- pcNew->mHeight = pcHeader->skinheight;
+ // allocate a new texture object
+ aiTexture* pcNew = new aiTexture();
+ pcNew->mWidth = pcHeader->skinwidth;
+ pcNew->mHeight = pcHeader->skinheight;
- pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
+ pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- const unsigned char* szColorMap;
- this->SearchPalette(&szColorMap);
+ const unsigned char* szColorMap;
+ this->SearchPalette(&szColorMap);
- // copy texture data
- for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
+ // copy texture data
+ for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ const unsigned char val = szData[i];
+ const unsigned char* sz = &szColorMap[val*3];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = *sz++;
- pcNew->pcData[i].g = *sz++;
- pcNew->pcData[i].b = *sz;
- }
+ pcNew->pcData[i].a = 0xFF;
+ pcNew->pcData[i].r = *sz++;
+ pcNew->pcData[i].g = *sz++;
+ pcNew->pcData[i].b = *sz;
+ }
- FreePalette(szColorMap);
+ FreePalette(szColorMap);
- // store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i <pScene->mNumTextures;++i)
- pScene->mTextures[i] = pc[i];
+ // store the texture
+ aiTexture** pc = this->pScene->mTextures;
+ this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
+ for (unsigned int i = 0; i <pScene->mNumTextures;++i)
+ pScene->mTextures[i] = pc[i];
- pScene->mTextures[this->pScene->mNumTextures] = pcNew;
- pScene->mNumTextures++;
- delete[] pc;
- return;
+ pScene->mTextures[this->pScene->mNumTextures] = pcNew;
+ pScene->mNumTextures++;
+ delete[] pc;
+ return;
}
// ------------------------------------------------------------------------------------------------
// Read a texture from a MDL4 file
-void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip)
+void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip)
{
- ai_assert(NULL != piSkip);
-
- const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function
-
- if (iType == 1 || iType > 3)
- {
- DefaultLogger::get()->error("Unsupported texture file format");
- return;
- }
-
- const bool bNoRead = *piSkip == UINT_MAX;
-
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
- pcNew->mWidth = pcHeader->skinwidth;
- pcNew->mHeight = pcHeader->skinheight;
-
- if (bNoRead)pcNew->pcData = bad_texel;
- ParseTextureColorData(szData,iType,piSkip,pcNew);
-
- // store the texture
- if (!bNoRead)
- {
- if (!this->pScene->mNumTextures)
- {
- pScene->mNumTextures = 1;
- pScene->mTextures = new aiTexture*[1];
- pScene->mTextures[0] = pcNew;
- }
- else
- {
- aiTexture** pc = pScene->mTextures;
- pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
- pScene->mTextures[i] = pc[i];
- pScene->mTextures[pScene->mNumTextures] = pcNew;
- pScene->mNumTextures++;
- delete[] pc;
- }
- }
- else {
- pcNew->pcData = NULL;
- delete pcNew;
- }
- return;
+ ai_assert(NULL != piSkip);
+
+ const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function
+
+ if (iType == 1 || iType > 3)
+ {
+ DefaultLogger::get()->error("Unsupported texture file format");
+ return;
+ }
+
+ const bool bNoRead = *piSkip == UINT_MAX;
+
+ // allocate a new texture object
+ aiTexture* pcNew = new aiTexture();
+ pcNew->mWidth = pcHeader->skinwidth;
+ pcNew->mHeight = pcHeader->skinheight;
+
+ if (bNoRead)pcNew->pcData = bad_texel;
+ ParseTextureColorData(szData,iType,piSkip,pcNew);
+
+ // store the texture
+ if (!bNoRead)
+ {
+ if (!this->pScene->mNumTextures)
+ {
+ pScene->mNumTextures = 1;
+ pScene->mTextures = new aiTexture*[1];
+ pScene->mTextures[0] = pcNew;
+ }
+ else
+ {
+ aiTexture** pc = pScene->mTextures;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
+ for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
+ pScene->mTextures[i] = pc[i];
+ pScene->mTextures[pScene->mNumTextures] = pcNew;
+ pScene->mNumTextures++;
+ delete[] pc;
+ }
+ }
+ else {
+ pcNew->pcData = NULL;
+ delete pcNew;
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Load color data of a texture and convert it to our output format
-void MDLImporter::ParseTextureColorData(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip,
- aiTexture* pcNew)
+void MDLImporter::ParseTextureColorData(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip,
+ aiTexture* pcNew)
{
- const bool do_read = bad_texel != pcNew->pcData;
-
- // allocate storage for the texture image
- if (do_read) {
- pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- }
-
- // R5G6B5 format (with or without MIPs)
- // ****************************************************************
- if (2 == iType || 10 == iType)
- {
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
-
- // copy texture data
- unsigned int i;
- if (do_read)
- {
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
- AI_SWAP2(val);
-
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = (unsigned char)val.b << 3;
- pcNew->pcData[i].g = (unsigned char)val.g << 2;
- pcNew->pcData[i].b = (unsigned char)val.r << 3;
- }
- }
- else i = pcNew->mWidth*pcNew->mHeight;
- *piSkip = i * 2;
-
- // apply MIP maps
- if (10 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
- VALIDATE_FILE_SIZE(szData + *piSkip);
- }
- }
- // ARGB4 format (with or without MIPs)
- // ****************************************************************
- else if (3 == iType || 11 == iType)
- {
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
-
- // copy texture data
- unsigned int i;
- if (do_read)
- {
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
- AI_SWAP2(val);
-
- pcNew->pcData[i].a = (unsigned char)val.a << 4;
- pcNew->pcData[i].r = (unsigned char)val.r << 4;
- pcNew->pcData[i].g = (unsigned char)val.g << 4;
- pcNew->pcData[i].b = (unsigned char)val.b << 4;
- }
- }
- else i = pcNew->mWidth*pcNew->mHeight;
- *piSkip = i * 2;
-
- // apply MIP maps
- if (11 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
- VALIDATE_FILE_SIZE(szData + *piSkip);
- }
- }
- // RGB8 format (with or without MIPs)
- // ****************************************************************
- else if (4 == iType || 12 == iType)
- {
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
-
- // copy texture data
- unsigned int i;
- if (do_read)
- {
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char* _szData = &szData[i*3];
-
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].b = *_szData++;
- pcNew->pcData[i].g = *_szData++;
- pcNew->pcData[i].r = *_szData;
- }
- }
- else i = pcNew->mWidth*pcNew->mHeight;
-
-
- // apply MIP maps
- *piSkip = i * 3;
- if (12 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
- VALIDATE_FILE_SIZE(szData + *piSkip);
- }
- }
- // ARGB8 format (with ir without MIPs)
- // ****************************************************************
- else if (5 == iType || 13 == iType)
- {
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
-
- // copy texture data
- unsigned int i;
- if (do_read)
- {
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char* _szData = &szData[i*4];
-
- pcNew->pcData[i].b = *_szData++;
- pcNew->pcData[i].g = *_szData++;
- pcNew->pcData[i].r = *_szData++;
- pcNew->pcData[i].a = *_szData;
- }
- }
- else i = pcNew->mWidth*pcNew->mHeight;
-
- // apply MIP maps
- *piSkip = i << 2;
- if (13 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
- }
- }
- // palletized 8 bit texture. As for Quake 1
- // ****************************************************************
- else if (0 == iType)
- {
- VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
-
- // copy texture data
- unsigned int i;
- if (do_read)
- {
-
- const unsigned char* szColorMap;
- SearchPalette(&szColorMap);
-
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
-
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = *sz++;
- pcNew->pcData[i].g = *sz++;
- pcNew->pcData[i].b = *sz;
- }
- this->FreePalette(szColorMap);
-
- }
- else i = pcNew->mWidth*pcNew->mHeight;
- *piSkip = i;
-
- // FIXME: Also support for MIP maps?
- }
+ const bool do_read = bad_texel != pcNew->pcData;
+
+ // allocate storage for the texture image
+ if (do_read) {
+ pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
+ }
+
+ // R5G6B5 format (with or without MIPs)
+ // ****************************************************************
+ if (2 == iType || 10 == iType)
+ {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
+
+ // copy texture data
+ unsigned int i;
+ if (do_read)
+ {
+ for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
+ AI_SWAP2(val);
+
+ pcNew->pcData[i].a = 0xFF;
+ pcNew->pcData[i].r = (unsigned char)val.b << 3;
+ pcNew->pcData[i].g = (unsigned char)val.g << 2;
+ pcNew->pcData[i].b = (unsigned char)val.r << 3;
+ }
+ }
+ else i = pcNew->mWidth*pcNew->mHeight;
+ *piSkip = i * 2;
+
+ // apply MIP maps
+ if (10 == iType)
+ {
+ *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
+ VALIDATE_FILE_SIZE(szData + *piSkip);
+ }
+ }
+ // ARGB4 format (with or without MIPs)
+ // ****************************************************************
+ else if (3 == iType || 11 == iType)
+ {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
+
+ // copy texture data
+ unsigned int i;
+ if (do_read)
+ {
+ for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
+ AI_SWAP2(val);
+
+ pcNew->pcData[i].a = (unsigned char)val.a << 4;
+ pcNew->pcData[i].r = (unsigned char)val.r << 4;
+ pcNew->pcData[i].g = (unsigned char)val.g << 4;
+ pcNew->pcData[i].b = (unsigned char)val.b << 4;
+ }
+ }
+ else i = pcNew->mWidth*pcNew->mHeight;
+ *piSkip = i * 2;
+
+ // apply MIP maps
+ if (11 == iType)
+ {
+ *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
+ VALIDATE_FILE_SIZE(szData + *piSkip);
+ }
+ }
+ // RGB8 format (with or without MIPs)
+ // ****************************************************************
+ else if (4 == iType || 12 == iType)
+ {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
+
+ // copy texture data
+ unsigned int i;
+ if (do_read)
+ {
+ for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ const unsigned char* _szData = &szData[i*3];
+
+ pcNew->pcData[i].a = 0xFF;
+ pcNew->pcData[i].b = *_szData++;
+ pcNew->pcData[i].g = *_szData++;
+ pcNew->pcData[i].r = *_szData;
+ }
+ }
+ else i = pcNew->mWidth*pcNew->mHeight;
+
+
+ // apply MIP maps
+ *piSkip = i * 3;
+ if (12 == iType)
+ {
+ *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
+ VALIDATE_FILE_SIZE(szData + *piSkip);
+ }
+ }
+ // ARGB8 format (with ir without MIPs)
+ // ****************************************************************
+ else if (5 == iType || 13 == iType)
+ {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
+
+ // copy texture data
+ unsigned int i;
+ if (do_read)
+ {
+ for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ const unsigned char* _szData = &szData[i*4];
+
+ pcNew->pcData[i].b = *_szData++;
+ pcNew->pcData[i].g = *_szData++;
+ pcNew->pcData[i].r = *_szData++;
+ pcNew->pcData[i].a = *_szData;
+ }
+ }
+ else i = pcNew->mWidth*pcNew->mHeight;
+
+ // apply MIP maps
+ *piSkip = i << 2;
+ if (13 == iType)
+ {
+ *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
+ }
+ }
+ // palletized 8 bit texture. As for Quake 1
+ // ****************************************************************
+ else if (0 == iType)
+ {
+ VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
+
+ // copy texture data
+ unsigned int i;
+ if (do_read)
+ {
+
+ const unsigned char* szColorMap;
+ SearchPalette(&szColorMap);
+
+ for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
+ {
+ const unsigned char val = szData[i];
+ const unsigned char* sz = &szColorMap[val*3];
+
+ pcNew->pcData[i].a = 0xFF;
+ pcNew->pcData[i].r = *sz++;
+ pcNew->pcData[i].g = *sz++;
+ pcNew->pcData[i].b = *sz;
+ }
+ this->FreePalette(szColorMap);
+
+ }
+ else i = pcNew->mWidth*pcNew->mHeight;
+ *piSkip = i;
+
+ // FIXME: Also support for MIP maps?
+ }
}
// ------------------------------------------------------------------------------------------------
// Get a texture from a MDL5 file
-void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip)
+void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
+ unsigned int iType,
+ unsigned int* piSkip)
{
- ai_assert(NULL != piSkip);
- bool bNoRead = *piSkip == UINT_MAX;
-
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
-
- VALIDATE_FILE_SIZE(szData+8);
-
- // first read the size of the texture
- pcNew->mWidth = *((uint32_t*)szData);
- AI_SWAP4(pcNew->mWidth);
- szData += sizeof(uint32_t);
-
- pcNew->mHeight = *((uint32_t*)szData);
- AI_SWAP4(pcNew->mHeight);
- szData += sizeof(uint32_t);
-
- if (bNoRead) {
- pcNew->pcData = bad_texel;
- }
-
- // this should not occur - at least the docs say it shouldn't.
- // however, one can easily try out what MED does if you have
- // a model with a DDS texture and export it to MDL5 ...
- // yeah, it embedds the DDS file.
- if (6 == iType)
- {
- // this is a compressed texture in DDS format
- *piSkip = pcNew->mWidth;
- VALIDATE_FILE_SIZE(szData + *piSkip);
-
- if (!bNoRead)
- {
- // place a hint and let the application know that this is a DDS file
- pcNew->mHeight = 0;
- pcNew->achFormatHint[0] = 'd';
- pcNew->achFormatHint[1] = 'd';
- pcNew->achFormatHint[2] = 's';
- pcNew->achFormatHint[3] = '\0';
-
- pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
- ::memcpy(pcNew->pcData,szData,pcNew->mWidth);
- }
- }
- else
- {
- // parse the color data of the texture
- ParseTextureColorData(szData,iType,piSkip,pcNew);
- }
- *piSkip += sizeof(uint32_t) * 2;
-
- if (!bNoRead)
- {
- // store the texture
- if (!this->pScene->mNumTextures)
- {
- pScene->mNumTextures = 1;
- pScene->mTextures = new aiTexture*[1];
- pScene->mTextures[0] = pcNew;
- }
- else
- {
- aiTexture** pc = pScene->mTextures;
- pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i < pScene->mNumTextures;++i)
- this->pScene->mTextures[i] = pc[i];
-
- pScene->mTextures[pScene->mNumTextures] = pcNew;
- pScene->mNumTextures++;
- delete[] pc;
- }
- }
- else {
- pcNew->pcData = NULL;
- delete pcNew;
- }
- return;
+ ai_assert(NULL != piSkip);
+ bool bNoRead = *piSkip == UINT_MAX;
+
+ // allocate a new texture object
+ aiTexture* pcNew = new aiTexture();
+
+ VALIDATE_FILE_SIZE(szData+8);
+
+ // first read the size of the texture
+ pcNew->mWidth = *((uint32_t*)szData);
+ AI_SWAP4(pcNew->mWidth);
+ szData += sizeof(uint32_t);
+
+ pcNew->mHeight = *((uint32_t*)szData);
+ AI_SWAP4(pcNew->mHeight);
+ szData += sizeof(uint32_t);
+
+ if (bNoRead) {
+ pcNew->pcData = bad_texel;
+ }
+
+ // this should not occur - at least the docs say it shouldn't.
+ // however, one can easily try out what MED does if you have
+ // a model with a DDS texture and export it to MDL5 ...
+ // yeah, it embedds the DDS file.
+ if (6 == iType)
+ {
+ // this is a compressed texture in DDS format
+ *piSkip = pcNew->mWidth;
+ VALIDATE_FILE_SIZE(szData + *piSkip);
+
+ if (!bNoRead)
+ {
+ // place a hint and let the application know that this is a DDS file
+ pcNew->mHeight = 0;
+ pcNew->achFormatHint[0] = 'd';
+ pcNew->achFormatHint[1] = 'd';
+ pcNew->achFormatHint[2] = 's';
+ pcNew->achFormatHint[3] = '\0';
+
+ pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
+ ::memcpy(pcNew->pcData,szData,pcNew->mWidth);
+ }
+ }
+ else
+ {
+ // parse the color data of the texture
+ ParseTextureColorData(szData,iType,piSkip,pcNew);
+ }
+ *piSkip += sizeof(uint32_t) * 2;
+
+ if (!bNoRead)
+ {
+ // store the texture
+ if (!this->pScene->mNumTextures)
+ {
+ pScene->mNumTextures = 1;
+ pScene->mTextures = new aiTexture*[1];
+ pScene->mTextures[0] = pcNew;
+ }
+ else
+ {
+ aiTexture** pc = pScene->mTextures;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
+ for (unsigned int i = 0; i < pScene->mNumTextures;++i)
+ this->pScene->mTextures[i] = pc[i];
+
+ pScene->mTextures[pScene->mNumTextures] = pcNew;
+ pScene->mNumTextures++;
+ delete[] pc;
+ }
+ }
+ else {
+ pcNew->pcData = NULL;
+ delete pcNew;
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Get a skin from a MDL7 file - more complex than all other subformats
void MDLImporter::ParseSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- aiMaterial* pcMatOut,
- unsigned int iType,
- unsigned int iWidth,
- unsigned int iHeight)
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ aiMaterial* pcMatOut,
+ unsigned int iType,
+ unsigned int iWidth,
+ unsigned int iHeight)
{
- aiTexture* pcNew = NULL;
-
- // get the type of the skin
- unsigned int iMasked = (unsigned int)(iType & 0xF);
-
- if (0x1 == iMasked)
- {
- // ***** REFERENCE TO ANOTHER SKIN INDEX *****
- int referrer = (int)iWidth;
- pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
- }
- else if (0x6 == iMasked)
- {
- // ***** EMBEDDED DDS FILE *****
- if (1 != iHeight)
- {
- DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
- "but texture height is not equal to 1, which is not supported by MED");
- }
-
- pcNew = new aiTexture();
- pcNew->mHeight = 0;
- pcNew->mWidth = iWidth;
-
- // place a proper format hint
- pcNew->achFormatHint[0] = 'd';
- pcNew->achFormatHint[1] = 'd';
- pcNew->achFormatHint[2] = 's';
- pcNew->achFormatHint[3] = '\0';
-
- pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
- memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
- szCurrent += iWidth;
- }
- if (0x7 == iMasked)
- {
- // ***** REFERENCE TO EXTERNAL FILE *****
- if (1 != iHeight)
- {
- DefaultLogger::get()->warn("Found a reference to an external texture, "
- "but texture height is not equal to 1, which is not supported by MED");
- }
-
- aiString szFile;
- const size_t iLen = strlen((const char*)szCurrent);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(szFile.data,(const char*)szCurrent,iLen2);
- szFile.length = iLen;
-
- szCurrent += iLen2;
-
- // place this as diffuse texture
- pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- else if (iMasked || !iType || (iType && iWidth && iHeight))
- {
- // ***** STANDARD COLOR TEXTURE *****
- pcNew = new aiTexture();
- if (!iHeight || !iWidth)
- {
- DefaultLogger::get()->warn("Found embedded texture, but its width "
- "an height are both 0. Is this a joke?");
-
- // generate an empty chess pattern
- pcNew->mWidth = pcNew->mHeight = 8;
- pcNew->pcData = new aiTexel[64];
- for (unsigned int x = 0; x < 8;++x)
- {
- for (unsigned int y = 0; y < 8;++y)
- {
- const bool bSet = ((0 == x % 2 && 0 != y % 2) ||
- (0 != x % 2 && 0 == y % 2));
-
- aiTexel* pc = &pcNew->pcData[y * 8 + x];
- pc->r = pc->b = pc->g = (bSet?0xFF:0);
- pc->a = 0xFF;
- }
- }
- }
- else
- {
- // it is a standard color texture. Fill in width and height
- // and call the same function we used for loading MDL5 files
-
- pcNew->mWidth = iWidth;
- pcNew->mHeight = iHeight;
-
- unsigned int iSkip = 0;
- ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
-
- // skip length of texture data
- szCurrent += iSkip;
- }
- }
-
- // sometimes there are MDL7 files which have a monochrome
- // texture instead of material colors ... posssible they have
- // been converted to MDL7 from other formats, such as MDL5
- aiColor4D clrTexture;
- if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew);
- else clrTexture.r = get_qnan();
-
- // check whether a material definition is contained in the skin
- if (iType & AI_MDL7_SKINTYPE_MATERIAL)
- {
- BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
- szCurrent = (unsigned char*)(pcMatIn+1);
- VALIDATE_FILE_SIZE(szCurrent);
-
- aiColor3D clrTemp;
+ aiTexture* pcNew = NULL;
+
+ // get the type of the skin
+ unsigned int iMasked = (unsigned int)(iType & 0xF);
+
+ if (0x1 == iMasked)
+ {
+ // ***** REFERENCE TO ANOTHER SKIN INDEX *****
+ int referrer = (int)iWidth;
+ pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
+ }
+ else if (0x6 == iMasked)
+ {
+ // ***** EMBEDDED DDS FILE *****
+ if (1 != iHeight)
+ {
+ DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
+ "but texture height is not equal to 1, which is not supported by MED");
+ }
+
+ pcNew = new aiTexture();
+ pcNew->mHeight = 0;
+ pcNew->mWidth = iWidth;
+
+ // place a proper format hint
+ pcNew->achFormatHint[0] = 'd';
+ pcNew->achFormatHint[1] = 'd';
+ pcNew->achFormatHint[2] = 's';
+ pcNew->achFormatHint[3] = '\0';
+
+ pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
+ memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
+ szCurrent += iWidth;
+ }
+ if (0x7 == iMasked)
+ {
+ // ***** REFERENCE TO EXTERNAL FILE *****
+ if (1 != iHeight)
+ {
+ DefaultLogger::get()->warn("Found a reference to an external texture, "
+ "but texture height is not equal to 1, which is not supported by MED");
+ }
+
+ aiString szFile;
+ const size_t iLen = strlen((const char*)szCurrent);
+ size_t iLen2 = iLen+1;
+ iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
+ memcpy(szFile.data,(const char*)szCurrent,iLen2);
+ szFile.length = iLen;
+
+ szCurrent += iLen2;
+
+ // place this as diffuse texture
+ pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ else if (iMasked || !iType || (iType && iWidth && iHeight))
+ {
+ // ***** STANDARD COLOR TEXTURE *****
+ pcNew = new aiTexture();
+ if (!iHeight || !iWidth)
+ {
+ DefaultLogger::get()->warn("Found embedded texture, but its width "
+ "an height are both 0. Is this a joke?");
+
+ // generate an empty chess pattern
+ pcNew->mWidth = pcNew->mHeight = 8;
+ pcNew->pcData = new aiTexel[64];
+ for (unsigned int x = 0; x < 8;++x)
+ {
+ for (unsigned int y = 0; y < 8;++y)
+ {
+ const bool bSet = ((0 == x % 2 && 0 != y % 2) ||
+ (0 != x % 2 && 0 == y % 2));
+
+ aiTexel* pc = &pcNew->pcData[y * 8 + x];
+ pc->r = pc->b = pc->g = (bSet?0xFF:0);
+ pc->a = 0xFF;
+ }
+ }
+ }
+ else
+ {
+ // it is a standard color texture. Fill in width and height
+ // and call the same function we used for loading MDL5 files
+
+ pcNew->mWidth = iWidth;
+ pcNew->mHeight = iHeight;
+
+ unsigned int iSkip = 0;
+ ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
+
+ // skip length of texture data
+ szCurrent += iSkip;
+ }
+ }
+
+ // sometimes there are MDL7 files which have a monochrome
+ // texture instead of material colors ... posssible they have
+ // been converted to MDL7 from other formats, such as MDL5
+ aiColor4D clrTexture;
+ if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew);
+ else clrTexture.r = get_qnan();
+
+ // check whether a material definition is contained in the skin
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL)
+ {
+ BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
+ szCurrent = (unsigned char*)(pcMatIn+1);
+ VALIDATE_FILE_SIZE(szCurrent);
+
+ aiColor3D clrTemp;
#define COLOR_MULTIPLY_RGB() \
- if (is_not_qnan(clrTexture.r)) \
- { \
- clrTemp.r *= clrTexture.r; \
- clrTemp.g *= clrTexture.g; \
- clrTemp.b *= clrTexture.b; \
- }
-
- // read diffuse color
- clrTemp.r = pcMatIn->Diffuse.r;
- AI_SWAP4(clrTemp.r);
- clrTemp.g = pcMatIn->Diffuse.g;
- AI_SWAP4(clrTemp.g);
- clrTemp.b = pcMatIn->Diffuse.b;
- AI_SWAP4(clrTemp.b);
- COLOR_MULTIPLY_RGB();
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
-
- // read specular color
- clrTemp.r = pcMatIn->Specular.r;
- AI_SWAP4(clrTemp.r);
- clrTemp.g = pcMatIn->Specular.g;
- AI_SWAP4(clrTemp.g);
- clrTemp.b = pcMatIn->Specular.b;
- AI_SWAP4(clrTemp.b);
- COLOR_MULTIPLY_RGB();
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
-
- // read ambient color
- clrTemp.r = pcMatIn->Ambient.r;
- AI_SWAP4(clrTemp.r);
- clrTemp.g = pcMatIn->Ambient.g;
- AI_SWAP4(clrTemp.g);
- clrTemp.b = pcMatIn->Ambient.b;
- AI_SWAP4(clrTemp.b);
- COLOR_MULTIPLY_RGB();
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
-
- // read emissive color
- clrTemp.r = pcMatIn->Emissive.r;
- AI_SWAP4(clrTemp.r);
- clrTemp.g = pcMatIn->Emissive.g;
- AI_SWAP4(clrTemp.g);
- clrTemp.b = pcMatIn->Emissive.b;
- AI_SWAP4(clrTemp.b);
- pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
+ if (is_not_qnan(clrTexture.r)) \
+ { \
+ clrTemp.r *= clrTexture.r; \
+ clrTemp.g *= clrTexture.g; \
+ clrTemp.b *= clrTexture.b; \
+ }
+
+ // read diffuse color
+ clrTemp.r = pcMatIn->Diffuse.r;
+ AI_SWAP4(clrTemp.r);
+ clrTemp.g = pcMatIn->Diffuse.g;
+ AI_SWAP4(clrTemp.g);
+ clrTemp.b = pcMatIn->Diffuse.b;
+ AI_SWAP4(clrTemp.b);
+ COLOR_MULTIPLY_RGB();
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ // read specular color
+ clrTemp.r = pcMatIn->Specular.r;
+ AI_SWAP4(clrTemp.r);
+ clrTemp.g = pcMatIn->Specular.g;
+ AI_SWAP4(clrTemp.g);
+ clrTemp.b = pcMatIn->Specular.b;
+ AI_SWAP4(clrTemp.b);
+ COLOR_MULTIPLY_RGB();
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
+
+ // read ambient color
+ clrTemp.r = pcMatIn->Ambient.r;
+ AI_SWAP4(clrTemp.r);
+ clrTemp.g = pcMatIn->Ambient.g;
+ AI_SWAP4(clrTemp.g);
+ clrTemp.b = pcMatIn->Ambient.b;
+ AI_SWAP4(clrTemp.b);
+ COLOR_MULTIPLY_RGB();
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
+
+ // read emissive color
+ clrTemp.r = pcMatIn->Emissive.r;
+ AI_SWAP4(clrTemp.r);
+ clrTemp.g = pcMatIn->Emissive.g;
+ AI_SWAP4(clrTemp.g);
+ clrTemp.b = pcMatIn->Emissive.b;
+ AI_SWAP4(clrTemp.b);
+ pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
#undef COLOR_MULITPLY_RGB
- // FIX: Take the opacity from the ambient color.
- // The doc say something else, but it is fact that MED exports the
- // opacity like this .... oh well.
- clrTemp.r = pcMatIn->Ambient.a;
- AI_SWAP4(clrTemp.r);
- if (is_not_qnan(clrTexture.r)) {
- clrTemp.r *= clrTexture.a;
- }
- pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
-
- // read phong power
- int iShadingMode = (int)aiShadingMode_Gouraud;
- AI_SWAP4(pcMatIn->Power);
- if (0.0f != pcMatIn->Power)
- {
- iShadingMode = (int)aiShadingMode_Phong;
- pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
- }
- pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
- }
- else if (is_not_qnan(clrTexture.r))
- {
- pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
- pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
- }
- // if the texture could be replaced by a single material color
- // we don't need the texture anymore
- if (is_not_qnan(clrTexture.r))
- {
- delete pcNew;
- pcNew = NULL;
- }
-
- // If an ASCII effect description (HLSL?) is contained in the file,
- // we can simply ignore it ...
- if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
- {
- VALIDATE_FILE_SIZE(szCurrent);
- int32_t iMe = *((int32_t*)szCurrent);
- AI_SWAP4(iMe);
- szCurrent += sizeof(char) * iMe + sizeof(int32_t);
- VALIDATE_FILE_SIZE(szCurrent);
- }
-
- // If an embedded texture has been loaded setup the corresponding
- // data structures in the aiScene instance
- if (pcNew && pScene->mNumTextures <= 999)
- {
-
- // place this as diffuse texture
- char szCurrent[5];
- ::sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
-
- aiString szFile;
- const size_t iLen = strlen((const char*)szCurrent);
- ::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
- szFile.length = iLen;
-
- pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
- // store the texture
- if (!pScene->mNumTextures)
- {
- pScene->mNumTextures = 1;
- pScene->mTextures = new aiTexture*[1];
- pScene->mTextures[0] = pcNew;
- }
- else
- {
- aiTexture** pc = pScene->mTextures;
- pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
- for (unsigned int i = 0; i < pScene->mNumTextures;++i) {
- pScene->mTextures[i] = pc[i];
- }
-
- pScene->mTextures[pScene->mNumTextures] = pcNew;
- pScene->mNumTextures++;
- delete[] pc;
- }
- }
- VALIDATE_FILE_SIZE(szCurrent);
- *szCurrentOut = szCurrent;
+ // FIX: Take the opacity from the ambient color.
+ // The doc say something else, but it is fact that MED exports the
+ // opacity like this .... oh well.
+ clrTemp.r = pcMatIn->Ambient.a;
+ AI_SWAP4(clrTemp.r);
+ if (is_not_qnan(clrTexture.r)) {
+ clrTemp.r *= clrTexture.a;
+ }
+ pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
+
+ // read phong power
+ int iShadingMode = (int)aiShadingMode_Gouraud;
+ AI_SWAP4(pcMatIn->Power);
+ if (0.0f != pcMatIn->Power)
+ {
+ iShadingMode = (int)aiShadingMode_Phong;
+ pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
+ }
+ pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
+ }
+ else if (is_not_qnan(clrTexture.r))
+ {
+ pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
+ pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
+ }
+ // if the texture could be replaced by a single material color
+ // we don't need the texture anymore
+ if (is_not_qnan(clrTexture.r))
+ {
+ delete pcNew;
+ pcNew = NULL;
+ }
+
+ // If an ASCII effect description (HLSL?) is contained in the file,
+ // we can simply ignore it ...
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
+ {
+ VALIDATE_FILE_SIZE(szCurrent);
+ int32_t iMe = *((int32_t*)szCurrent);
+ AI_SWAP4(iMe);
+ szCurrent += sizeof(char) * iMe + sizeof(int32_t);
+ VALIDATE_FILE_SIZE(szCurrent);
+ }
+
+ // If an embedded texture has been loaded setup the corresponding
+ // data structures in the aiScene instance
+ if (pcNew && pScene->mNumTextures <= 999)
+ {
+
+ // place this as diffuse texture
+ char szCurrent[5];
+ ai_snprintf(szCurrent,5,"*%i",this->pScene->mNumTextures);
+
+ aiString szFile;
+ const size_t iLen = strlen((const char*)szCurrent);
+ ::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
+ szFile.length = iLen;
+
+ pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+ // store the texture
+ if (!pScene->mNumTextures)
+ {
+ pScene->mNumTextures = 1;
+ pScene->mTextures = new aiTexture*[1];
+ pScene->mTextures[0] = pcNew;
+ }
+ else
+ {
+ aiTexture** pc = pScene->mTextures;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
+ for (unsigned int i = 0; i < pScene->mNumTextures;++i) {
+ pScene->mTextures[i] = pc[i];
+ }
+
+ pScene->mTextures[pScene->mNumTextures] = pcNew;
+ pScene->mNumTextures++;
+ delete[] pc;
+ }
+ }
+ VALIDATE_FILE_SIZE(szCurrent);
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
// Skip a skin lump
void MDLImporter::SkipSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- unsigned int iType,
- unsigned int iWidth,
- unsigned int iHeight)
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ unsigned int iType,
+ unsigned int iWidth,
+ unsigned int iHeight)
{
- // get the type of the skin
- const unsigned int iMasked = (unsigned int)(iType & 0xF);
-
- if (0x6 == iMasked)
- {
- szCurrent += iWidth;
- }
- if (0x7 == iMasked)
- {
- const size_t iLen = ::strlen((const char*)szCurrent);
- szCurrent += iLen+1;
- }
- else if (iMasked || !iType)
- {
- if (iMasked || !iType || (iType && iWidth && iHeight))
- {
- // ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply
- // return the size of the color data in bytes in iSkip
- unsigned int iSkip = 0;
-
- aiTexture tex;
- tex.pcData = bad_texel;
- tex.mHeight = iHeight;
- tex.mWidth = iWidth;
- ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
-
- // FIX: Important, otherwise the destructor will crash
- tex.pcData = NULL;
-
- // skip length of texture data
- szCurrent += iSkip;
- }
- }
-
- // check whether a material definition is contained in the skin
- if (iType & AI_MDL7_SKINTYPE_MATERIAL)
- {
- BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
- szCurrent = (unsigned char*)(pcMatIn+1);
- }
-
- // if an ASCII effect description (HLSL?) is contained in the file,
- // we can simply ignore it ...
- if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
- {
- int32_t iMe = *((int32_t*)szCurrent);
- AI_SWAP4(iMe);
- szCurrent += sizeof(char) * iMe + sizeof(int32_t);
- }
- *szCurrentOut = szCurrent;
+ // get the type of the skin
+ const unsigned int iMasked = (unsigned int)(iType & 0xF);
+
+ if (0x6 == iMasked)
+ {
+ szCurrent += iWidth;
+ }
+ if (0x7 == iMasked)
+ {
+ const size_t iLen = ::strlen((const char*)szCurrent);
+ szCurrent += iLen+1;
+ }
+ else if (iMasked || !iType)
+ {
+ if (iMasked || !iType || (iType && iWidth && iHeight))
+ {
+ // ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply
+ // return the size of the color data in bytes in iSkip
+ unsigned int iSkip = 0;
+
+ aiTexture tex;
+ tex.pcData = bad_texel;
+ tex.mHeight = iHeight;
+ tex.mWidth = iWidth;
+ ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
+
+ // FIX: Important, otherwise the destructor will crash
+ tex.pcData = NULL;
+
+ // skip length of texture data
+ szCurrent += iSkip;
+ }
+ }
+
+ // check whether a material definition is contained in the skin
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL)
+ {
+ BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
+ szCurrent = (unsigned char*)(pcMatIn+1);
+ }
+
+ // if an ASCII effect description (HLSL?) is contained in the file,
+ // we can simply ignore it ...
+ if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
+ {
+ int32_t iMe = *((int32_t*)szCurrent);
+ AI_SWAP4(iMe);
+ szCurrent += sizeof(char) * iMe + sizeof(int32_t);
+ }
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
void MDLImporter::ParseSkinLump_3DGS_MDL7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- std::vector<aiMaterial*>& pcMats)
+ const unsigned char* szCurrent,
+ const unsigned char** szCurrentOut,
+ std::vector<aiMaterial*>& pcMats)
{
- ai_assert(NULL != szCurrent);
- ai_assert(NULL != szCurrentOut);
-
- *szCurrentOut = szCurrent;
- BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent;
- AI_SWAP4(pcSkin->width);
- AI_SWAP4(pcSkin->height);
- szCurrent += 12;
-
- // allocate an output material
- aiMaterial* pcMatOut = new aiMaterial();
- pcMats.push_back(pcMatOut);
-
- // skip length of file name
- szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
-
- ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
- pcSkin->typ,pcSkin->width,pcSkin->height);
-
- // place the name of the skin in the material
- if (pcSkin->texture_name[0])
- {
- // the 0 termination could be there or not - we can't know
- aiString szFile;
- ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
- szFile.data[sizeof(pcSkin->texture_name)] = '\0';
- szFile.length = ::strlen(szFile.data);
-
- pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
- }
+ ai_assert(NULL != szCurrent);
+ ai_assert(NULL != szCurrentOut);
+
+ *szCurrentOut = szCurrent;
+ BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent;
+ AI_SWAP4(pcSkin->width);
+ AI_SWAP4(pcSkin->height);
+ szCurrent += 12;
+
+ // allocate an output material
+ aiMaterial* pcMatOut = new aiMaterial();
+ pcMats.push_back(pcMatOut);
+
+ // skip length of file name
+ szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
+
+ ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
+ pcSkin->typ,pcSkin->width,pcSkin->height);
+
+ // place the name of the skin in the material
+ if (pcSkin->texture_name[0])
+ {
+ // the 0 termination could be there or not - we can't know
+ aiString szFile;
+ ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
+ szFile.data[sizeof(pcSkin->texture_name)] = '\0';
+ szFile.length = ::strlen(szFile.data);
+
+ pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
+ }
}
#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER
diff --git a/src/3rdparty/assimp/code/MS3DLoader.cpp b/src/3rdparty/assimp/code/MS3DLoader.cpp
index c1a4a8dbf..ef16a756a 100644
--- a/src/3rdparty/assimp/code/MS3DLoader.cpp
+++ b/src/3rdparty/assimp/code/MS3DLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -44,25 +44,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Written against http://chumbalum.swissquake.ch/ms3d/ms3dspec.txt
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER
// internal headers
#include "MS3DLoader.h"
#include "StreamReader.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Milkshape 3D Importer",
- "",
- "",
- "http://chumbalum.swissquake.ch/",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "ms3d"
+ "Milkshape 3D Importer",
+ "",
+ "",
+ "http://chumbalum.swissquake.ch/",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ms3d"
};
// ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH
@@ -73,591 +78,592 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
MS3DImporter::MS3DImporter()
+ : mScene()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
MS3DImporter::~MS3DImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- // first call - simple extension check
- const std::string extension = GetExtension(pFile);
- if (extension == "ms3d") {
- return true;
- }
-
- // second call - check for magic identifiers
- else if (!extension.length() || checkSig) {
- if (!pIOHandler) {
- return true;
- }
- const char* tokens[] = {"MS3D000000"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // first call - simple extension check
+ const std::string extension = GetExtension(pFile);
+ if (extension == "ms3d") {
+ return true;
+ }
+
+ // second call - check for magic identifiers
+ else if (!extension.length() || checkSig) {
+ if (!pIOHandler) {
+ return true;
+ }
+ const char* tokens[] = {"MS3D000000"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* MS3DImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
void ReadColor(StreamReaderLE& stream, aiColor4D& ambient)
{
- // aiColor4D is packed on gcc, implicit binding to float& fails therefore.
- stream >> (float&)ambient.r >> (float&)ambient.g >> (float&)ambient.b >> (float&)ambient.a;
+ // aiColor4D is packed on gcc, implicit binding to float& fails therefore.
+ stream >> (float&)ambient.r >> (float&)ambient.g >> (float&)ambient.b >> (float&)ambient.a;
}
// ------------------------------------------------------------------------------------------------
void ReadVector(StreamReaderLE& stream, aiVector3D& pos)
{
- // See note in ReadColor()
- stream >> (float&)pos.x >> (float&)pos.y >> (float&)pos.z;
+ // See note in ReadColor()
+ stream >> (float&)pos.x >> (float&)pos.y >> (float&)pos.z;
}
// ------------------------------------------------------------------------------------------------
-template<typename T>
+template<typename T>
void MS3DImporter :: ReadComments(StreamReaderLE& stream, std::vector<T>& outp)
{
- uint16_t cnt;
- stream >> cnt;
-
- for(unsigned int i = 0; i < cnt; ++i) {
- uint32_t index, clength;
- stream >> index >> clength;
-
- if(index >= outp.size()) {
- DefaultLogger::get()->warn("MS3D: Invalid index in comment section");
- }
- else if (clength > stream.GetRemainingSize()) {
- throw DeadlyImportError("MS3D: Failure reading comment, length field is out of range");
- }
- else {
- outp[index].comment = std::string(reinterpret_cast<char*>(stream.GetPtr()),clength);
- }
- stream.IncPtr(clength);
- }
+ uint16_t cnt;
+ stream >> cnt;
+
+ for(unsigned int i = 0; i < cnt; ++i) {
+ uint32_t index, clength;
+ stream >> index >> clength;
+
+ if(index >= outp.size()) {
+ DefaultLogger::get()->warn("MS3D: Invalid index in comment section");
+ }
+ else if (clength > stream.GetRemainingSize()) {
+ throw DeadlyImportError("MS3D: Failure reading comment, length field is out of range");
+ }
+ else {
+ outp[index].comment = std::string(reinterpret_cast<char*>(stream.GetPtr()),clength);
+ }
+ stream.IncPtr(clength);
+ }
}
// ------------------------------------------------------------------------------------------------
template <typename T, typename T2, typename T3> bool inrange(const T& in, const T2& lower, const T3& higher)
{
- return in > lower && in <= higher;
+ return in > lower && in <= higher;
}
// ------------------------------------------------------------------------------------------------
void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints,
- std::vector<bool>& hadit,
- aiNode* nd,
- const aiMatrix4x4& absTrafo)
+ std::vector<bool>& hadit,
+ aiNode* nd,
+ const aiMatrix4x4& absTrafo)
{
- unsigned int cnt = 0;
- for(size_t i = 0; i < joints.size(); ++i) {
- if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) {
- ++cnt;
- }
- }
-
- nd->mChildren = new aiNode*[nd->mNumChildren = cnt];
- cnt = 0;
- for(size_t i = 0; i < joints.size(); ++i) {
- if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) {
- aiNode* ch = nd->mChildren[cnt++] = new aiNode(joints[i].name);
- ch->mParent = nd;
-
- ch->mTransformation = aiMatrix4x4::Translation(joints[i].position,aiMatrix4x4()=aiMatrix4x4())*
- // XXX actually, I don't *know* why we need the inverse here. Probably column vs. row order?
- aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation).Transpose();
-
- const aiMatrix4x4 abs = absTrafo*ch->mTransformation;
- for(unsigned int a = 0; a < mScene->mNumMeshes; ++a) {
- aiMesh* const msh = mScene->mMeshes[a];
- for(unsigned int n = 0; n < msh->mNumBones; ++n) {
- aiBone* const bone = msh->mBones[n];
-
- if(bone->mName == ch->mName) {
- bone->mOffsetMatrix = aiMatrix4x4(abs).Inverse();
- }
- }
- }
-
- hadit[i] = true;
- CollectChildJoints(joints,hadit,ch,abs);
- }
- }
+ unsigned int cnt = 0;
+ for(size_t i = 0; i < joints.size(); ++i) {
+ if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) {
+ ++cnt;
+ }
+ }
+
+ nd->mChildren = new aiNode*[nd->mNumChildren = cnt];
+ cnt = 0;
+ for(size_t i = 0; i < joints.size(); ++i) {
+ if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) {
+ aiNode* ch = nd->mChildren[cnt++] = new aiNode(joints[i].name);
+ ch->mParent = nd;
+
+ ch->mTransformation = aiMatrix4x4::Translation(joints[i].position,aiMatrix4x4()=aiMatrix4x4())*
+ // XXX actually, I don't *know* why we need the inverse here. Probably column vs. row order?
+ aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation).Transpose();
+
+ const aiMatrix4x4 abs = absTrafo*ch->mTransformation;
+ for(unsigned int a = 0; a < mScene->mNumMeshes; ++a) {
+ aiMesh* const msh = mScene->mMeshes[a];
+ for(unsigned int n = 0; n < msh->mNumBones; ++n) {
+ aiBone* const bone = msh->mBones[n];
+
+ if(bone->mName == ch->mName) {
+ bone->mOffsetMatrix = aiMatrix4x4(abs).Inverse();
+ }
+ }
+ }
+
+ hadit[i] = true;
+ CollectChildJoints(joints,hadit,ch,abs);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, aiNode* nd)
{
- std::vector<bool> hadit(joints.size(),false);
- aiMatrix4x4 trafo;
+ std::vector<bool> hadit(joints.size(),false);
+ aiMatrix4x4 trafo;
- CollectChildJoints(joints,hadit,nd,trafo);
+ CollectChildJoints(joints,hadit,nd,trafo);
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void MS3DImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void MS3DImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+ StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+
+ // CanRead() should have done this already
+ char head[10];
+ int32_t version;
- // CanRead() should have done this already
- char head[10];
- int32_t version;
+ mScene = pScene;
- mScene = pScene;
+ // 1 ------------ read into temporary data structures mirroring the original file
- // 1 ------------ read into temporary data structures mirroring the original file
+ stream.CopyAndAdvance(head,10);
+ stream >> version;
+ if (strncmp(head,"MS3D000000",10)) {
+ throw DeadlyImportError("Not a MS3D file, magic string MS3D000000 not found: "+pFile);
+ }
- stream.CopyAndAdvance(head,10);
- stream >> version;
- if (strncmp(head,"MS3D000000",10)) {
- throw DeadlyImportError("Not a MS3D file, magic string MS3D000000 not found: "+pFile);
- }
+ if (version != 4) {
+ throw DeadlyImportError("MS3D: Unsupported file format version, 4 was expected");
+ }
- if (version != 4) {
- throw DeadlyImportError("MS3D: Unsupported file format version, 4 was expected");
- }
+ uint16_t verts;
+ stream >> verts;
- uint16_t verts;
- stream >> verts;
+ std::vector<TempVertex> vertices(verts);
+ for (unsigned int i = 0; i < verts; ++i) {
+ TempVertex& v = vertices[i];
- std::vector<TempVertex> vertices(verts);
- for (unsigned int i = 0; i < verts; ++i) {
- TempVertex& v = vertices[i];
+ stream.IncPtr(1);
+ ReadVector(stream,v.pos);
+ v.bone_id[0] = stream.GetI1();
+ v.ref_cnt = stream.GetI1();
- stream.IncPtr(1);
- ReadVector(stream,v.pos);
- v.bone_id[0] = stream.GetI1();
- v.ref_cnt = stream.GetI1();
+ v.bone_id[1] = v.bone_id[2] = v.bone_id[3] = UINT_MAX;
+ v.weights[1] = v.weights[2] = v.weights[3] = 0.f;
+ v.weights[0] = 1.f;
+ }
- v.bone_id[1] = v.bone_id[2] = v.bone_id[3] = UINT_MAX;
- v.weights[1] = v.weights[2] = v.weights[3] = 0.f;
- v.weights[0] = 1.f;
- }
+ uint16_t tris;
+ stream >> tris;
- uint16_t tris;
- stream >> tris;
+ std::vector<TempTriangle> triangles(tris);
+ for (unsigned int i = 0;i < tris; ++i) {
+ TempTriangle& t = triangles[i];
- std::vector<TempTriangle> triangles(tris);
- for (unsigned int i = 0;i < tris; ++i) {
- TempTriangle& t = triangles[i];
+ stream.IncPtr(2);
+ for (unsigned int i = 0; i < 3; ++i) {
+ t.indices[i] = stream.GetI2();
+ }
- stream.IncPtr(2);
- for (unsigned int i = 0; i < 3; ++i) {
- t.indices[i] = stream.GetI2();
- }
+ for (unsigned int i = 0; i < 3; ++i) {
+ ReadVector(stream,t.normals[i]);
+ }
- for (unsigned int i = 0; i < 3; ++i) {
- ReadVector(stream,t.normals[i]);
- }
+ for (unsigned int i = 0; i < 3; ++i) {
+ stream >> (float&)(t.uv[i].x); // see note in ReadColor()
+ }
+ for (unsigned int i = 0; i < 3; ++i) {
+ stream >> (float&)(t.uv[i].y);
+ }
+
+ t.sg = stream.GetI1();
+ t.group = stream.GetI1();
+ }
+
+ uint16_t grp;
+ stream >> grp;
+
+ bool need_default = false;
+ std::vector<TempGroup> groups(grp);
+ for (unsigned int i = 0;i < grp; ++i) {
+ TempGroup& t = groups[i];
+
+ stream.IncPtr(1);
+ stream.CopyAndAdvance(t.name,32);
+
+ t.name[32] = '\0';
+ uint16_t num;
+ stream >> num;
+
+ t.triangles.resize(num);
+ for (unsigned int i = 0; i < num; ++i) {
+ t.triangles[i] = stream.GetI2();
+ }
+ t.mat = stream.GetI1();
+ if (t.mat == UINT_MAX) {
+ need_default = true;
+ }
+ }
+
+ uint16_t mat;
+ stream >> mat;
+
+ std::vector<TempMaterial> materials(mat);
+ for (unsigned int i = 0;i < mat; ++i) {
+ TempMaterial& t = materials[i];
+
+ stream.CopyAndAdvance(t.name,32);
+ t.name[32] = '\0';
+
+ ReadColor(stream,t.ambient);
+ ReadColor(stream,t.diffuse);
+ ReadColor(stream,t.specular);
+ ReadColor(stream,t.emissive);
+ stream >> t.shininess >> t.transparency;
+
+ stream.IncPtr(1);
+
+ stream.CopyAndAdvance(t.texture,128);
+ t.texture[128] = '\0';
+
+ stream.CopyAndAdvance(t.alphamap,128);
+ t.alphamap[128] = '\0';
+ }
+
+ float animfps, currenttime;
+ uint32_t totalframes;
+ stream >> animfps >> currenttime >> totalframes;
+
+ uint16_t joint;
+ stream >> joint;
+
+ std::vector<TempJoint> joints(joint);
+ for(unsigned int i = 0; i < joint; ++i) {
+ TempJoint& j = joints[i];
+
+ stream.IncPtr(1);
+ stream.CopyAndAdvance(j.name,32);
+ j.name[32] = '\0';
+
+ stream.CopyAndAdvance(j.parentName,32);
+ j.parentName[32] = '\0';
+
+ // DefaultLogger::get()->debug(j.name);
+ // DefaultLogger::get()->debug(j.parentName);
+
+ ReadVector(stream,j.rotation);
+ ReadVector(stream,j.position);
+
+ j.rotFrames.resize(stream.GetI2());
+ j.posFrames.resize(stream.GetI2());
+
+ for(unsigned int a = 0; a < j.rotFrames.size(); ++a) {
+ TempKeyFrame& kf = j.rotFrames[a];
+ stream >> kf.time;
+ ReadVector(stream,kf.value);
+ }
+ for(unsigned int a = 0; a < j.posFrames.size(); ++a) {
+ TempKeyFrame& kf = j.posFrames[a];
+ stream >> kf.time;
+ ReadVector(stream,kf.value);
+ }
+ }
+
+ if(stream.GetRemainingSize() > 4) {
+ uint32_t subversion;
+ stream >> subversion;
+ if (subversion == 1) {
+ ReadComments<TempGroup>(stream,groups);
+ ReadComments<TempMaterial>(stream,materials);
+ ReadComments<TempJoint>(stream,joints);
+
+ // model comment - print it for we have such a nice log.
+ if (stream.GetI4()) {
+ const size_t len = static_cast<size_t>(stream.GetI4());
+ if (len > stream.GetRemainingSize()) {
+ throw DeadlyImportError("MS3D: Model comment is too long");
+ }
+
+ const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len);
+ DefaultLogger::get()->debug("MS3D: Model comment: " + s);
+ }
+
+ if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) {
+ for(unsigned int i = 0; i < verts; ++i) {
+ TempVertex& v = vertices[i];
+ v.weights[3]=1.f;
+ for(unsigned int n = 0; n < 3; v.weights[3]-=v.weights[n++]) {
+ v.bone_id[n+1] = stream.GetI1();
+ v.weights[n] = static_cast<float>(static_cast<unsigned int>(stream.GetI1()))/255.f;
+ }
+ stream.IncPtr((subversion-1)<<2u);
+ }
+
+ // even further extra data is not of interest for us, at least now now.
+ }
+ }
+ }
+
+ // 2 ------------ convert to proper aiXX data structures -----------------------------------
+
+ if (need_default && materials.size()) {
+ DefaultLogger::get()->warn("MS3D: Found group with no material assigned, spawning default material");
+ // if one of the groups has no material assigned, but there are other
+ // groups with materials, a default material needs to be added (
+ // scenepreprocessor adds a default material only if nummat==0).
+ materials.push_back(TempMaterial());
+ TempMaterial& m = materials.back();
+
+ strcpy(m.name,"<MS3D_DefaultMat>");
+ m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0);
+ m.transparency = 1.f;
+ m.shininess = 0.f;
+
+ // this is because these TempXXX struct's have no c'tors.
+ m.texture[0] = m.alphamap[0] = '\0';
+
+ for (unsigned int i = 0; i < groups.size(); ++i) {
+ TempGroup& g = groups[i];
+ if (g.mat == UINT_MAX) {
+ g.mat = materials.size()-1;
+ }
+ }
+ }
+
+ // convert materials to our generic key-value dict-alike
+ if (materials.size()) {
+ pScene->mMaterials = new aiMaterial*[materials.size()];
+ for (size_t i = 0; i < materials.size(); ++i) {
+
+ aiMaterial* mo = new aiMaterial();
+ pScene->mMaterials[pScene->mNumMaterials++] = mo;
+
+ const TempMaterial& mi = materials[i];
+
+ aiString tmp;
+ if (0[mi.alphamap]) {
+ tmp = aiString(mi.alphamap);
+ mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_OPACITY(0));
+ }
+ if (0[mi.texture]) {
+ tmp = aiString(mi.texture);
+ mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ if (0[mi.name]) {
+ tmp = aiString(mi.name);
+ mo->AddProperty(&tmp,AI_MATKEY_NAME);
+ }
+
+ mo->AddProperty(&mi.ambient,1,AI_MATKEY_COLOR_AMBIENT);
+ mo->AddProperty(&mi.diffuse,1,AI_MATKEY_COLOR_DIFFUSE);
+ mo->AddProperty(&mi.specular,1,AI_MATKEY_COLOR_SPECULAR);
+ mo->AddProperty(&mi.emissive,1,AI_MATKEY_COLOR_EMISSIVE);
+
+ mo->AddProperty(&mi.shininess,1,AI_MATKEY_SHININESS);
+ mo->AddProperty(&mi.transparency,1,AI_MATKEY_OPACITY);
+
+ const int sm = mi.shininess>0.f?aiShadingMode_Phong:aiShadingMode_Gouraud;
+ mo->AddProperty(&sm,1,AI_MATKEY_SHADING_MODEL);
+ }
+ }
+
+ // convert groups to meshes
+ if (groups.empty()) {
+ throw DeadlyImportError("MS3D: Didn't get any group records, file is malformed");
+ }
+
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes=static_cast<unsigned int>(groups.size())]();
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+
+ aiMesh* m = pScene->mMeshes[i] = new aiMesh();
+ const TempGroup& g = groups[i];
+
+ if (pScene->mNumMaterials && g.mat > pScene->mNumMaterials) {
+ throw DeadlyImportError("MS3D: Encountered invalid material index, file is malformed");
+ } // no error if no materials at all - scenepreprocessor adds one then
+
+ m->mMaterialIndex = g.mat;
+ m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ m->mFaces = new aiFace[m->mNumFaces = g.triangles.size()];
+ m->mNumVertices = m->mNumFaces*3;
+
+ // storage for vertices - verbose format, as requested by the postprocessing pipeline
+ m->mVertices = new aiVector3D[m->mNumVertices];
+ m->mNormals = new aiVector3D[m->mNumVertices];
+ m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
+ m->mNumUVComponents[0] = 2;
+
+ typedef std::map<unsigned int,unsigned int> BoneSet;
+ BoneSet mybones;
+
+ for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
+ aiFace& f = m->mFaces[i];
+ if (g.triangles[i]>triangles.size()) {
+ throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
+ }
+
+ TempTriangle& t = triangles[g.triangles[i]];
+ f.mIndices = new unsigned int[f.mNumIndices=3];
+
+ for (unsigned int i = 0; i < 3; ++i,++n) {
+ if (t.indices[i]>vertices.size()) {
+ throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
+ }
+
+ const TempVertex& v = vertices[t.indices[i]];
+ for(unsigned int a = 0; a < 4; ++a) {
+ if (v.bone_id[a] != UINT_MAX) {
+ if (v.bone_id[a] >= joints.size()) {
+ throw DeadlyImportError("MS3D: Encountered invalid bone index, file is malformed");
+ }
+ if (mybones.find(v.bone_id[a]) == mybones.end()) {
+ mybones[v.bone_id[a]] = 1;
+ }
+ else ++mybones[v.bone_id[a]];
+ }
+ }
+
+ // collect vertex components
+ m->mVertices[n] = v.pos;
+
+ m->mNormals[n] = t.normals[i];
+ m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0);
+ f.mIndices[i] = n;
+ }
+ }
+
+ // allocate storage for bones
+ if(!mybones.empty()) {
+ std::vector<unsigned int> bmap(joints.size());
+ m->mBones = new aiBone*[mybones.size()]();
+ for(BoneSet::const_iterator it = mybones.begin(); it != mybones.end(); ++it) {
+ aiBone* const bn = m->mBones[m->mNumBones] = new aiBone();
+ const TempJoint& jnt = joints[(*it).first];
+
+ bn->mName.Set(jnt.name);
+ bn->mWeights = new aiVertexWeight[(*it).second];
+
+ bmap[(*it).first] = m->mNumBones++;
+ }
+
+ // .. and collect bone weights
+ for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
+ TempTriangle& t = triangles[g.triangles[i]];
+
+ for (unsigned int i = 0; i < 3; ++i,++n) {
+ const TempVertex& v = vertices[t.indices[i]];
+ for(unsigned int a = 0; a < 4; ++a) {
+ const unsigned int bone = v.bone_id[a];
+ if(bone==UINT_MAX){
+ continue;
+ }
+
+ aiBone* const outbone = m->mBones[bmap[bone]];
+ aiVertexWeight& outwght = outbone->mWeights[outbone->mNumWeights++];
+
+ outwght.mVertexId = n;
+ outwght.mWeight = v.weights[a];
+ }
+ }
+ }
+ }
+ }
+
+ // ... add dummy nodes under a single root, each holding a reference to one
+ // mesh. If we didn't do this, we'd lose the group name.
+ aiNode* rt = pScene->mRootNode = new aiNode("<MS3DRoot>");
- for (unsigned int i = 0; i < 3; ++i) {
- stream >> (float&)(t.uv[i].x); // see note in ReadColor()
- }
- for (unsigned int i = 0; i < 3; ++i) {
- stream >> (float&)(t.uv[i].y);
- }
-
- t.sg = stream.GetI1();
- t.group = stream.GetI1();
- }
-
- uint16_t grp;
- stream >> grp;
-
- bool need_default = false;
- std::vector<TempGroup> groups(grp);
- for (unsigned int i = 0;i < grp; ++i) {
- TempGroup& t = groups[i];
-
- stream.IncPtr(1);
- stream.CopyAndAdvance(t.name,32);
-
- t.name[32] = '\0';
- uint16_t num;
- stream >> num;
-
- t.triangles.resize(num);
- for (unsigned int i = 0; i < num; ++i) {
- t.triangles[i] = stream.GetI2();
- }
- t.mat = stream.GetI1();
- if (t.mat == UINT_MAX) {
- need_default = true;
- }
- }
-
- uint16_t mat;
- stream >> mat;
-
- std::vector<TempMaterial> materials(mat);
- for (unsigned int i = 0;i < mat; ++i) {
- TempMaterial& t = materials[i];
-
- stream.CopyAndAdvance(t.name,32);
- t.name[32] = '\0';
-
- ReadColor(stream,t.ambient);
- ReadColor(stream,t.diffuse);
- ReadColor(stream,t.specular);
- ReadColor(stream,t.emissive);
- stream >> t.shininess >> t.transparency;
-
- stream.IncPtr(1);
-
- stream.CopyAndAdvance(t.texture,128);
- t.texture[128] = '\0';
-
- stream.CopyAndAdvance(t.alphamap,128);
- t.alphamap[128] = '\0';
- }
-
- float animfps, currenttime;
- uint32_t totalframes;
- stream >> animfps >> currenttime >> totalframes;
-
- uint16_t joint;
- stream >> joint;
-
- std::vector<TempJoint> joints(joint);
- for(unsigned int i = 0; i < joint; ++i) {
- TempJoint& j = joints[i];
-
- stream.IncPtr(1);
- stream.CopyAndAdvance(j.name,32);
- j.name[32] = '\0';
-
- stream.CopyAndAdvance(j.parentName,32);
- j.parentName[32] = '\0';
-
- // DefaultLogger::get()->debug(j.name);
- // DefaultLogger::get()->debug(j.parentName);
-
- ReadVector(stream,j.rotation);
- ReadVector(stream,j.position);
-
- j.rotFrames.resize(stream.GetI2());
- j.posFrames.resize(stream.GetI2());
-
- for(unsigned int a = 0; a < j.rotFrames.size(); ++a) {
- TempKeyFrame& kf = j.rotFrames[a];
- stream >> kf.time;
- ReadVector(stream,kf.value);
- }
- for(unsigned int a = 0; a < j.posFrames.size(); ++a) {
- TempKeyFrame& kf = j.posFrames[a];
- stream >> kf.time;
- ReadVector(stream,kf.value);
- }
- }
-
- if(stream.GetRemainingSize() > 4) {
- uint32_t subversion;
- stream >> subversion;
- if (subversion == 1) {
- ReadComments<TempGroup>(stream,groups);
- ReadComments<TempMaterial>(stream,materials);
- ReadComments<TempJoint>(stream,joints);
-
- // model comment - print it for we have such a nice log.
- if (stream.GetI4()) {
- const size_t len = static_cast<size_t>(stream.GetI4());
- if (len > stream.GetRemainingSize()) {
- throw DeadlyImportError("MS3D: Model comment is too long");
- }
-
- const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len);
- DefaultLogger::get()->debug("MS3D: Model comment: " + s);
- }
-
- if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) {
- for(unsigned int i = 0; i < verts; ++i) {
- TempVertex& v = vertices[i];
- v.weights[3]=1.f;
- for(unsigned int n = 0; n < 3; v.weights[3]-=v.weights[n++]) {
- v.bone_id[n+1] = stream.GetI1();
- v.weights[n] = static_cast<float>(static_cast<unsigned int>(stream.GetI1()))/255.f;
- }
- stream.IncPtr((subversion-1)<<2u);
- }
-
- // even further extra data is not of interest for us, at least now now.
- }
- }
- }
-
- // 2 ------------ convert to proper aiXX data structures -----------------------------------
-
- if (need_default && materials.size()) {
- DefaultLogger::get()->warn("MS3D: Found group with no material assigned, spawning default material");
- // if one of the groups has no material assigned, but there are other
- // groups with materials, a default material needs to be added (
- // scenepreprocessor adds a default material only if nummat==0).
- materials.push_back(TempMaterial());
- TempMaterial& m = materials.back();
-
- strcpy(m.name,"<MS3D_DefaultMat>");
- m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0);
- m.transparency = 1.f;
- m.shininess = 0.f;
-
- // this is because these TempXXX struct's have no c'tors.
- m.texture[0] = m.alphamap[0] = '\0';
-
- for (unsigned int i = 0; i < groups.size(); ++i) {
- TempGroup& g = groups[i];
- if (g.mat == UINT_MAX) {
- g.mat = materials.size()-1;
- }
- }
- }
-
- // convert materials to our generic key-value dict-alike
- if (materials.size()) {
- pScene->mMaterials = new aiMaterial*[materials.size()];
- for (size_t i = 0; i < materials.size(); ++i) {
-
- aiMaterial* mo = new aiMaterial();
- pScene->mMaterials[pScene->mNumMaterials++] = mo;
-
- const TempMaterial& mi = materials[i];
-
- aiString tmp;
- if (0[mi.alphamap]) {
- tmp = aiString(mi.alphamap);
- mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_OPACITY(0));
- }
- if (0[mi.texture]) {
- tmp = aiString(mi.texture);
- mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- if (0[mi.name]) {
- tmp = aiString(mi.name);
- mo->AddProperty(&tmp,AI_MATKEY_NAME);
- }
-
- mo->AddProperty(&mi.ambient,1,AI_MATKEY_COLOR_AMBIENT);
- mo->AddProperty(&mi.diffuse,1,AI_MATKEY_COLOR_DIFFUSE);
- mo->AddProperty(&mi.specular,1,AI_MATKEY_COLOR_SPECULAR);
- mo->AddProperty(&mi.emissive,1,AI_MATKEY_COLOR_EMISSIVE);
-
- mo->AddProperty(&mi.shininess,1,AI_MATKEY_SHININESS);
- mo->AddProperty(&mi.transparency,1,AI_MATKEY_OPACITY);
-
- const int sm = mi.shininess>0.f?aiShadingMode_Phong:aiShadingMode_Gouraud;
- mo->AddProperty(&sm,1,AI_MATKEY_SHADING_MODEL);
- }
- }
-
- // convert groups to meshes
- if (groups.empty()) {
- throw DeadlyImportError("MS3D: Didn't get any group records, file is malformed");
- }
-
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes=static_cast<unsigned int>(groups.size())]();
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
-
- aiMesh* m = pScene->mMeshes[i] = new aiMesh();
- const TempGroup& g = groups[i];
-
- if (pScene->mNumMaterials && g.mat > pScene->mNumMaterials) {
- throw DeadlyImportError("MS3D: Encountered invalid material index, file is malformed");
- } // no error if no materials at all - scenepreprocessor adds one then
-
- m->mMaterialIndex = g.mat;
- m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- m->mFaces = new aiFace[m->mNumFaces = g.triangles.size()];
- m->mNumVertices = m->mNumFaces*3;
-
- // storage for vertices - verbose format, as requested by the postprocessing pipeline
- m->mVertices = new aiVector3D[m->mNumVertices];
- m->mNormals = new aiVector3D[m->mNumVertices];
- m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
- m->mNumUVComponents[0] = 2;
-
- typedef std::map<unsigned int,unsigned int> BoneSet;
- BoneSet mybones;
-
- for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
- aiFace& f = m->mFaces[i];
- if (g.triangles[i]>triangles.size()) {
- throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
- }
-
- TempTriangle& t = triangles[g.triangles[i]];
- f.mIndices = new unsigned int[f.mNumIndices=3];
-
- for (unsigned int i = 0; i < 3; ++i,++n) {
- if (t.indices[i]>vertices.size()) {
- throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
- }
-
- const TempVertex& v = vertices[t.indices[i]];
- for(unsigned int a = 0; a < 4; ++a) {
- if (v.bone_id[a] != UINT_MAX) {
- if (v.bone_id[a] >= joints.size()) {
- throw DeadlyImportError("MS3D: Encountered invalid bone index, file is malformed");
- }
- if (mybones.find(v.bone_id[a]) == mybones.end()) {
- mybones[v.bone_id[a]] = 1;
- }
- else ++mybones[v.bone_id[a]];
- }
- }
-
- // collect vertex components
- m->mVertices[n] = v.pos;
-
- m->mNormals[n] = t.normals[i];
- m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0);
- f.mIndices[i] = n;
- }
- }
-
- // allocate storage for bones
- if(mybones.size()) {
- std::vector<unsigned int> bmap(joints.size());
- m->mBones = new aiBone*[mybones.size()]();
- for(BoneSet::const_iterator it = mybones.begin(); it != mybones.end(); ++it) {
- aiBone* const bn = m->mBones[m->mNumBones] = new aiBone();
- const TempJoint& jnt = joints[(*it).first];
-
- bn->mName.Set(jnt.name);
- bn->mWeights = new aiVertexWeight[(*it).second];
-
- bmap[(*it).first] = m->mNumBones++;
- }
-
- // .. and collect bone weights
- for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) {
- TempTriangle& t = triangles[g.triangles[i]];
-
- for (unsigned int i = 0; i < 3; ++i,++n) {
- const TempVertex& v = vertices[t.indices[i]];
- for(unsigned int a = 0; a < 4; ++a) {
- const unsigned int bone = v.bone_id[a];
- if(bone==UINT_MAX){
- continue;
- }
-
- aiBone* const outbone = m->mBones[bmap[bone]];
- aiVertexWeight& outwght = outbone->mWeights[outbone->mNumWeights++];
-
- outwght.mVertexId = n;
- outwght.mWeight = v.weights[a];
- }
- }
- }
- }
- }
-
- // ... add dummy nodes under a single root, each holding a reference to one
- // mesh. If we didn't do this, we'd lose the group name.
- aiNode* rt = pScene->mRootNode = new aiNode("<MS3DRoot>");
-
#ifdef ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH
- rt->mChildren = new aiNode*[rt->mNumChildren=pScene->mNumMeshes+(joints.size()?1:0)]();
+ rt->mChildren = new aiNode*[rt->mNumChildren=pScene->mNumMeshes+(joints.size()?1:0)]();
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- aiNode* nd = rt->mChildren[i] = new aiNode();
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ aiNode* nd = rt->mChildren[i] = new aiNode();
- const TempGroup& g = groups[i];
+ const TempGroup& g = groups[i];
- // we need to generate an unique name for all mesh nodes.
- // since we want to keep the group name, a prefix is
- // prepended.
- nd->mName = aiString("<MS3DMesh>_");
- nd->mName.Append(g.name);
- nd->mParent = rt;
+ // we need to generate an unique name for all mesh nodes.
+ // since we want to keep the group name, a prefix is
+ // prepended.
+ nd->mName = aiString("<MS3DMesh>_");
+ nd->mName.Append(g.name);
+ nd->mParent = rt;
- nd->mMeshes = new unsigned int[nd->mNumMeshes = 1];
- nd->mMeshes[0] = i;
- }
+ nd->mMeshes = new unsigned int[nd->mNumMeshes = 1];
+ nd->mMeshes[0] = i;
+ }
#else
- rt->mMeshes = new unsigned int[pScene->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- rt->mMeshes[rt->mNumMeshes++] = i;
- }
+ rt->mMeshes = new unsigned int[pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ rt->mMeshes[rt->mNumMeshes++] = i;
+ }
#endif
- // convert animations as well
- if(joints.size()) {
+ // convert animations as well
+ if(joints.size()) {
#ifndef ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH
- rt->mChildren = new aiNode*[1]();
- rt->mNumChildren = 1;
+ rt->mChildren = new aiNode*[1]();
+ rt->mNumChildren = 1;
- aiNode* jt = rt->mChildren[0] = new aiNode();
+ aiNode* jt = rt->mChildren[0] = new aiNode();
#else
- aiNode* jt = rt->mChildren[pScene->mNumMeshes] = new aiNode();
+ aiNode* jt = rt->mChildren[pScene->mNumMeshes] = new aiNode();
#endif
- jt->mParent = rt;
- CollectChildJoints(joints,jt);
- jt->mName.Set("<MS3DJointRoot>");
-
- pScene->mAnimations = new aiAnimation*[ pScene->mNumAnimations = 1 ];
- aiAnimation* const anim = pScene->mAnimations[0] = new aiAnimation();
-
- anim->mName.Set("<MS3DMasterAnim>");
-
- // carry the fps info to the user by scaling all times with it
- anim->mTicksPerSecond = animfps;
-
- // leave duration at its default, so ScenePreprocessor will fill an appropriate
- // value (the values taken from some MS3D files seem to be too unreliable
- // to pass the validation)
- // anim->mDuration = totalframes/animfps;
-
- anim->mChannels = new aiNodeAnim*[joints.size()]();
- for(std::vector<TempJoint>::const_iterator it = joints.begin(); it != joints.end(); ++it) {
- if ((*it).rotFrames.empty() && (*it).posFrames.empty()) {
- continue;
- }
-
- aiNodeAnim* nd = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
- nd->mNodeName.Set((*it).name);
-
- if ((*it).rotFrames.size()) {
- nd->mRotationKeys = new aiQuatKey[(*it).rotFrames.size()];
- for(std::vector<TempKeyFrame>::const_iterator rot = (*it).rotFrames.begin(); rot != (*it).rotFrames.end(); ++rot) {
- aiQuatKey& q = nd->mRotationKeys[nd->mNumRotationKeys++];
-
- q.mTime = (*rot).time*animfps;
-
- // XXX it seems our matrix&quaternion code has faults in its conversion routines --
- // aiQuaternion(x,y,z) seems to besomething different as quat(matrix.fromeuler(x,y,z)).
- q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*rot).value)*
- aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)).Transpose());
- }
- }
-
- if ((*it).posFrames.size()) {
- nd->mPositionKeys = new aiVectorKey[(*it).posFrames.size()];
-
- aiQuatKey* qu = nd->mRotationKeys;
- for(std::vector<TempKeyFrame>::const_iterator pos = (*it).posFrames.begin(); pos != (*it).posFrames.end(); ++pos,++qu) {
- aiVectorKey& v = nd->mPositionKeys[nd->mNumPositionKeys++];
-
- v.mTime = (*pos).time*animfps;
- v.mValue = (*it).position + (*pos).value;
- }
- }
- }
- // fixup to pass the validation if not a single animation channel is non-trivial
- if (!anim->mNumChannels) {
- anim->mChannels = NULL;
- }
- }
+ jt->mParent = rt;
+ CollectChildJoints(joints,jt);
+ jt->mName.Set("<MS3DJointRoot>");
+
+ pScene->mAnimations = new aiAnimation*[ pScene->mNumAnimations = 1 ];
+ aiAnimation* const anim = pScene->mAnimations[0] = new aiAnimation();
+
+ anim->mName.Set("<MS3DMasterAnim>");
+
+ // carry the fps info to the user by scaling all times with it
+ anim->mTicksPerSecond = animfps;
+
+ // leave duration at its default, so ScenePreprocessor will fill an appropriate
+ // value (the values taken from some MS3D files seem to be too unreliable
+ // to pass the validation)
+ // anim->mDuration = totalframes/animfps;
+
+ anim->mChannels = new aiNodeAnim*[joints.size()]();
+ for(std::vector<TempJoint>::const_iterator it = joints.begin(); it != joints.end(); ++it) {
+ if ((*it).rotFrames.empty() && (*it).posFrames.empty()) {
+ continue;
+ }
+
+ aiNodeAnim* nd = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+ nd->mNodeName.Set((*it).name);
+
+ if ((*it).rotFrames.size()) {
+ nd->mRotationKeys = new aiQuatKey[(*it).rotFrames.size()];
+ for(std::vector<TempKeyFrame>::const_iterator rot = (*it).rotFrames.begin(); rot != (*it).rotFrames.end(); ++rot) {
+ aiQuatKey& q = nd->mRotationKeys[nd->mNumRotationKeys++];
+
+ q.mTime = (*rot).time*animfps;
+
+ // XXX it seems our matrix&quaternion code has faults in its conversion routines --
+ // aiQuaternion(x,y,z) seems to besomething different as quat(matrix.fromeuler(x,y,z)).
+ q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*rot).value)*
+ aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)).Transpose());
+ }
+ }
+
+ if ((*it).posFrames.size()) {
+ nd->mPositionKeys = new aiVectorKey[(*it).posFrames.size()];
+
+ aiQuatKey* qu = nd->mRotationKeys;
+ for(std::vector<TempKeyFrame>::const_iterator pos = (*it).posFrames.begin(); pos != (*it).posFrames.end(); ++pos,++qu) {
+ aiVectorKey& v = nd->mPositionKeys[nd->mNumPositionKeys++];
+
+ v.mTime = (*pos).time*animfps;
+ v.mValue = (*it).position + (*pos).value;
+ }
+ }
+ }
+ // fixup to pass the validation if not a single animation channel is non-trivial
+ if (!anim->mNumChannels) {
+ anim->mChannels = NULL;
+ }
+ }
}
#endif
diff --git a/src/3rdparty/assimp/code/MS3DLoader.h b/src/3rdparty/assimp/code/MS3DLoader.h
index 34afc57b2..22d12e3cf 100644
--- a/src/3rdparty/assimp/code/MS3DLoader.h
+++ b/src/3rdparty/assimp/code/MS3DLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,112 +45,115 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MS3DLOADER_H_INCLUDED
#include "BaseImporter.h"
-namespace Assimp {
+#include "StreamReader.h"
+struct aiNode;
+
+namespace Assimp {
// ----------------------------------------------------------------------------------------------
/** Milkshape 3D importer implementation */
// ----------------------------------------------------------------------------------------------
-class MS3DImporter
- : public BaseImporter
+class MS3DImporter
+ : public BaseImporter
{
public:
- MS3DImporter();
- ~MS3DImporter();
+ MS3DImporter();
+ ~MS3DImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- struct TempJoint;
- void CollectChildJoints(const std::vector<TempJoint>& joints, std::vector<bool>& hadit, aiNode* nd,const aiMatrix4x4& absTrafo);
- void CollectChildJoints(const std::vector<TempJoint>& joints, aiNode* nd);
+ struct TempJoint;
+ void CollectChildJoints(const std::vector<TempJoint>& joints, std::vector<bool>& hadit, aiNode* nd,const aiMatrix4x4& absTrafo);
+ void CollectChildJoints(const std::vector<TempJoint>& joints, aiNode* nd);
- template<typename T> void ReadComments(StreamReaderLE& stream, std::vector<T>& outp);
+ template<typename T> void ReadComments(StreamReaderLE& stream, std::vector<T>& outp);
private:
- aiScene* mScene;
+ aiScene* mScene;
private:
- struct TempVertex
- {
- aiVector3D pos;
- unsigned int bone_id[4], ref_cnt;
- float weights[4];
- };
-
- struct TempTriangle
- {
- unsigned int indices[3];
- aiVector3D normals[3];
- aiVector2D uv[3];
-
- unsigned int sg, group;
- };
-
- struct TempGroup
- {
- char name[33]; // +0
- std::vector<unsigned int> triangles;
- unsigned int mat; // 0xff is no material
- std::string comment;
- };
-
- struct TempMaterial
- {
- // again, add an extra 0 character to all strings -
- char name[33];
- char texture[129];
- char alphamap[129];
-
- aiColor4D diffuse,specular,ambient,emissive;
- float shininess,transparency;
- std::string comment;
- };
-
- struct TempKeyFrame
- {
- float time;
- aiVector3D value;
- };
-
- struct TempJoint
- {
- char name[33];
- char parentName[33];
- aiVector3D rotation, position;
-
- std::vector<TempKeyFrame> rotFrames;
- std::vector<TempKeyFrame> posFrames;
- std::string comment;
- };
-
- //struct TempModel {
- // std::string comment;
- //};
+ struct TempVertex
+ {
+ aiVector3D pos;
+ unsigned int bone_id[4], ref_cnt;
+ float weights[4];
+ };
+
+ struct TempTriangle
+ {
+ unsigned int indices[3];
+ aiVector3D normals[3];
+ aiVector2D uv[3];
+
+ unsigned int sg, group;
+ };
+
+ struct TempGroup
+ {
+ char name[33]; // +0
+ std::vector<unsigned int> triangles;
+ unsigned int mat; // 0xff is no material
+ std::string comment;
+ };
+
+ struct TempMaterial
+ {
+ // again, add an extra 0 character to all strings -
+ char name[33];
+ char texture[129];
+ char alphamap[129];
+
+ aiColor4D diffuse,specular,ambient,emissive;
+ float shininess,transparency;
+ std::string comment;
+ };
+
+ struct TempKeyFrame
+ {
+ float time;
+ aiVector3D value;
+ };
+
+ struct TempJoint
+ {
+ char name[33];
+ char parentName[33];
+ aiVector3D rotation, position;
+
+ std::vector<TempKeyFrame> rotFrames;
+ std::vector<TempKeyFrame> posFrames;
+ std::string comment;
+ };
+
+ //struct TempModel {
+ // std::string comment;
+ //};
};
}
diff --git a/src/3rdparty/assimp/code/Macros.h b/src/3rdparty/assimp/code/Macros.h
new file mode 100644
index 000000000..4a2d07569
--- /dev/null
+++ b/src/3rdparty/assimp/code/Macros.h
@@ -0,0 +1,49 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+/* Helper macro to set a pointer to NULL in debug builds
+ */
+#if (defined ASSIMP_BUILD_DEBUG)
+# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
+#else
+# define AI_DEBUG_INVALIDATE_PTR(x)
+#endif
+
diff --git a/src/3rdparty/assimp/code/MakeVerboseFormat.cpp b/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
index faab79713..d51642cf6 100644
--- a/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
+++ b/src/3rdparty/assimp/code/MakeVerboseFormat.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,191 +25,195 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the post processing step "MakeVerboseFormat"
*/
-#include "AssimpPCH.h"
+
#include "MakeVerboseFormat.h"
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{
- ai_assert(NULL != pScene);
- DefaultLogger::get()->debug("MakeVerboseFormatProcess begin");
+ ai_assert(NULL != pScene);
+ DefaultLogger::get()->debug("MakeVerboseFormatProcess begin");
- bool bHas = false;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- {
- if( MakeVerboseFormat( pScene->mMeshes[a]))
- bHas = true;
- }
- if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ...");
- else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if( MakeVerboseFormat( pScene->mMeshes[a]))
+ bHas = true;
+ }
+ if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ...");
+ else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
- pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{
- ai_assert(NULL != pcMesh);
-
- unsigned int iOldNumVertices = pcMesh->mNumVertices;
- const unsigned int iNumVerts = pcMesh->mNumFaces*3;
-
- aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];
-
- aiVector3D* pvNormals = NULL;
- if (pcMesh->HasNormals())
- {
- pvNormals = new aiVector3D[iNumVerts];
- }
- aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
- if (pcMesh->HasTangentsAndBitangents())
- {
- pvTangents = new aiVector3D[iNumVerts];
- pvBitangents = new aiVector3D[iNumVerts];
- }
-
- aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
- aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};
-
- unsigned int p = 0;
- while (pcMesh->HasTextureCoords(p))
- apvTextureCoords[p++] = new aiVector3D[iNumVerts];
-
- p = 0;
- while (pcMesh->HasVertexColors(p))
- apvColorSets[p++] = new aiColor4D[iNumVerts];
-
- // allocate enough memory to hold output bones and vertex weights ...
- std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
- for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
- newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
- }
-
- // iterate through all faces and build a clean list
- unsigned int iIndex = 0;
- for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
- {
- aiFace* pcFace = &pcMesh->mFaces[a];
- for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
- {
- // need to build a clean list of bones, too
- for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
- {
- for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++)
- {
- const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a];
- if(pcFace->mIndices[q] == w.mVertexId)
- {
- aiVertexWeight wNew;
- wNew.mVertexId = iIndex;
- wNew.mWeight = w.mWeight;
- newWeights[i].push_back(wNew);
- }
- }
- }
-
- pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
-
- if (pcMesh->HasNormals())
- {
- pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
- }
- if (pcMesh->HasTangentsAndBitangents())
- {
- pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
- pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
- }
-
- unsigned int p = 0;
- while (pcMesh->HasTextureCoords(p))
- {
- apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
- ++p;
- }
- p = 0;
- while (pcMesh->HasVertexColors(p))
- {
- apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
- ++p;
- }
- pcFace->mIndices[q] = iIndex;
- }
- }
-
- // build output vertex weights
- for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
- {
- delete pcMesh->mBones[i]->mWeights;
- if (!newWeights[i].empty())
- {
- pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
- memcpy(pcMesh->mBones[i]->mWeights,&newWeights[i][0],
- sizeof(aiVertexWeight) * newWeights[i].size());
- }
- else pcMesh->mBones[i]->mWeights = NULL;
- }
-
- // delete the old members
- delete[] pcMesh->mVertices;
- pcMesh->mVertices = pvPositions;
-
- p = 0;
- while (pcMesh->HasTextureCoords(p))
- {
- delete pcMesh->mTextureCoords[p];
- pcMesh->mTextureCoords[p] = apvTextureCoords[p];
- ++p;
- }
- p = 0;
- while (pcMesh->HasVertexColors(p))
- {
- delete pcMesh->mColors[p];
- pcMesh->mColors[p] = apvColorSets[p];
- ++p;
- }
- pcMesh->mNumVertices = iNumVerts;
-
- if (pcMesh->HasNormals())
- {
- delete[] pcMesh->mNormals;
- pcMesh->mNormals = pvNormals;
- }
- if (pcMesh->HasTangentsAndBitangents())
- {
- delete[] pcMesh->mTangents;
- pcMesh->mTangents = pvTangents;
- delete[] pcMesh->mBitangents;
- pcMesh->mBitangents = pvBitangents;
- }
- return (pcMesh->mNumVertices != iOldNumVertices);
+ ai_assert(NULL != pcMesh);
+
+ unsigned int iOldNumVertices = pcMesh->mNumVertices;
+ const unsigned int iNumVerts = pcMesh->mNumFaces*3;
+
+ aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];
+
+ aiVector3D* pvNormals = NULL;
+ if (pcMesh->HasNormals())
+ {
+ pvNormals = new aiVector3D[iNumVerts];
+ }
+ aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ pvTangents = new aiVector3D[iNumVerts];
+ pvBitangents = new aiVector3D[iNumVerts];
+ }
+
+ aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
+ aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};
+
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ apvTextureCoords[p++] = new aiVector3D[iNumVerts];
+
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ apvColorSets[p++] = new aiColor4D[iNumVerts];
+
+ // allocate enough memory to hold output bones and vertex weights ...
+ std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
+ newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
+ }
+
+ // iterate through all faces and build a clean list
+ unsigned int iIndex = 0;
+ for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
+ {
+ aiFace* pcFace = &pcMesh->mFaces[a];
+ for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
+ {
+ // need to build a clean list of bones, too
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
+ {
+ for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++)
+ {
+ const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a];
+ if(pcFace->mIndices[q] == w.mVertexId)
+ {
+ aiVertexWeight wNew;
+ wNew.mVertexId = iIndex;
+ wNew.mWeight = w.mWeight;
+ newWeights[i].push_back(wNew);
+ }
+ }
+ }
+
+ pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];
+
+ if (pcMesh->HasNormals())
+ {
+ pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
+ }
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
+ pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
+ }
+
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
+ ++p;
+ }
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ {
+ apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
+ ++p;
+ }
+ pcFace->mIndices[q] = iIndex;
+ }
+ }
+
+ // build output vertex weights
+ for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
+ {
+ delete pcMesh->mBones[i]->mWeights;
+ if (!newWeights[i].empty()) {
+ pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
+ aiVertexWeight *weightToCopy = &( newWeights[i][0] );
+ memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
+ sizeof(aiVertexWeight) * newWeights[i].size());
+ delete[] newWeights;
+ } else {
+ pcMesh->mBones[i]->mWeights = NULL;
+ }
+ }
+
+ // delete the old members
+ delete[] pcMesh->mVertices;
+ pcMesh->mVertices = pvPositions;
+
+ p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ delete pcMesh->mTextureCoords[p];
+ pcMesh->mTextureCoords[p] = apvTextureCoords[p];
+ ++p;
+ }
+ p = 0;
+ while (pcMesh->HasVertexColors(p))
+ {
+ delete pcMesh->mColors[p];
+ pcMesh->mColors[p] = apvColorSets[p];
+ ++p;
+ }
+ pcMesh->mNumVertices = iNumVerts;
+
+ if (pcMesh->HasNormals())
+ {
+ delete[] pcMesh->mNormals;
+ pcMesh->mNormals = pvNormals;
+ }
+ if (pcMesh->HasTangentsAndBitangents())
+ {
+ delete[] pcMesh->mTangents;
+ pcMesh->mTangents = pvTangents;
+ delete[] pcMesh->mBitangents;
+ pcMesh->mBitangents = pvBitangents;
+ }
+ return (pcMesh->mNumVertices != iOldNumVertices);
}
diff --git a/src/3rdparty/assimp/code/MakeVerboseFormat.h b/src/3rdparty/assimp/code/MakeVerboseFormat.h
index 8a888f403..1b32cf19e 100644
--- a/src/3rdparty/assimp/code/MakeVerboseFormat.h
+++ b/src/3rdparty/assimp/code/MakeVerboseFormat.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,37 +23,39 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Defines a post processing step to bring a given scene
- into the verbose format that is expected by most postprocess steps.
+ into the verbose format that is expected by most postprocess steps.
This is the inverse of the "JoinIdenticalVertices" step. */
#ifndef AI_MAKEVERBOSEFORMAT_H_INC
#define AI_MAKEVERBOSEFORMAT_H_INC
#include "BaseProcess.h"
-namespace Assimp {
+struct aiMesh;
+
+namespace Assimp {
// ---------------------------------------------------------------------------
-/** MakeVerboseFormatProcess: Class to convert an asset to the verbose
+/** MakeVerboseFormatProcess: Class to convert an asset to the verbose
* format which is expected by most postprocess steps.
*
- * This is the inverse of what the "JoinIdenticalVertices" step is doing.
- * This step has no official flag (since it wouldn't make sense to run it
- * during import). It is intended for applications intending to modify the
+ * This is the inverse of what the "JoinIdenticalVertices" step is doing.
+ * This step has no official flag (since it wouldn't make sense to run it
+ * during import). It is intended for applications intending to modify the
* returned aiScene. After this step has been executed, they can execute
* other postprocess steps on the data. The code might also be useful to
* quickly adapt code that doesn't result in a verbose representation of
@@ -65,37 +67,37 @@ class ASSIMP_API_WINONLY MakeVerboseFormatProcess : public BaseProcess
{
public:
-
- MakeVerboseFormatProcess();
- ~MakeVerboseFormatProcess();
+
+ MakeVerboseFormatProcess();
+ ~MakeVerboseFormatProcess();
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
- {
- // NOTE: There is no direct flag that corresponds to
- // this postprocess step.
- return false;
- }
-
- // -------------------------------------------------------------------
- /** 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);
+ // -------------------------------------------------------------------
+ /** 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
+ {
+ // NOTE: There is no direct flag that corresponds to
+ // this postprocess step.
+ return false;
+ }
+
+ // -------------------------------------------------------------------
+ /** 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);
private:
- //! Apply the postprocess step to a given submesh
- bool MakeVerboseFormat (aiMesh* pcMesh);
+ //! Apply the postprocess step to a given submesh
+ bool MakeVerboseFormat (aiMesh* pcMesh);
};
-
+
} // end of namespace Assimp
#endif // !!AI_KILLNORMALPROCESS_H_INC
diff --git a/src/3rdparty/assimp/code/MaterialSystem.cpp b/src/3rdparty/assimp/code/MaterialSystem.cpp
index 5223c9bae..94ca4364e 100644
--- a/src/3rdparty/assimp/code/MaterialSystem.cpp
+++ b/src/3rdparty/assimp/code/MaterialSystem.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,277 +42,281 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the material system of the library
*/
-#include "AssimpPCH.h"
+
#include "Hash.h"
#include "fast_atof.h"
#include "ParsingUtils.h"
#include "MaterialSystem.h"
+#include <assimp/types.h>
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
+#include "Macros.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Get a specific property from a material
-aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
- const char* pKey,
- unsigned int type,
+aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
unsigned int index,
- const aiMaterialProperty** pPropOut)
+ 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 wildcard, but this is undocumented :-) */
- && (UINT_MAX == index || prop->mIndex == index))
- {
- *pPropOut = pMat->mProperties[i];
- return AI_SUCCESS;
- }
- }
- *pPropOut = NULL;
- return AI_FAILURE;
+ 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 wildcard, 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,
+aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
unsigned int index,
- float* pOut,
- unsigned int* pMax)
+ float* 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 floats, simply copy it
- 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<float> ( reinterpret_cast<float*>(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<float> ( 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 && !prop->mData[prop->mDataLength-1]);
- for (unsigned int a = 0; ;++a) {
- cur = fast_atoreal_move<float>(cur,pOut[a]);
- if(a==iWrite-1) {
- break;
- }
- if(!IsSpace(*cur)) {
- DefaultLogger::get()->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;
+ 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 floats, simply copy it
+ 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<float> ( reinterpret_cast<float*>(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<float> ( 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 && !prop->mData[prop->mDataLength-1]);
+ for (unsigned int a = 0; ;++a) {
+ cur = fast_atoreal_move<float>(cur,pOut[a]);
+ if(a==iWrite-1) {
+ break;
+ }
+ if(!IsSpace(*cur)) {
+ DefaultLogger::get()->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,
+aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
unsigned int index,
- int* pOut,
- unsigned int* pMax)
+ 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 = prop->mDataLength / sizeof(int32_t);
- if (pMax) {
- iWrite = std::min(*pMax,iWrite); ;
- }
- 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 && !prop->mData[prop->mDataLength-1]);
- for (unsigned int a = 0; ;++a) {
- pOut[a] = strtol10(cur,&cur);
- if(a==iWrite-1) {
- break;
- }
- if(!IsSpace(*cur)) {
- DefaultLogger::get()->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;
+ 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 = prop->mDataLength / sizeof(int32_t);
+ if (pMax) {
+ iWrite = std::min(*pMax,iWrite); ;
+ }
+ 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 && !prop->mData[prop->mDataLength-1]);
+ for (unsigned int a = 0; ;++a) {
+ pOut[a] = strtol10(cur,&cur);
+ if(a==iWrite-1) {
+ break;
+ }
+ if(!IsSpace(*cur)) {
+ DefaultLogger::get()->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)
+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,(float*)pOut,&iMax);
+ unsigned int iMax = 4;
+ const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
- // if no alpha channel is defined: set it to 1.0
- if (3 == iMax) {
- pOut->a = 1.0f;
- }
+ // if no alpha channel is defined: set it to 1.0
+ if (3 == iMax) {
+ pOut->a = 1.0f;
+ }
- return eRet;
+ 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)
+aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat,
+ const char* pKey,
+ unsigned int type,
+ unsigned int index,
+ aiUVTransform* pOut)
{
- unsigned int iMax = 4;
- return aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
+ unsigned int iMax = 4;
+ return aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
}
// ------------------------------------------------------------------------------------------------
// Get a string from the material
-aiReturn aiGetMaterialString(const aiMaterial* pMat,
- const char* pKey,
- unsigned int type,
- unsigned int index,
- aiString* pOut)
+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 && !prop->mData[prop->mDataLength-1]);
- memcpy(pOut->data,prop->mData+4,pOut->length+1);
- }
- else {
- // TODO - implement lexical cast as well
- DefaultLogger::get()->error("Material property" + std::string(pKey) +
- " was found, but is no string" );
- return AI_FAILURE;
- }
- return AI_SUCCESS;
+ 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 && !prop->mData[prop->mDataLength-1]);
+ memcpy(pOut->data,prop->mData+4,pOut->length+1);
+ }
+ else {
+ // TODO - implement lexical cast as well
+ DefaultLogger::get()->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
-ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
- C_ENUM aiTextureType type)
+ASSIMP_API 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;
+ 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;
}
// ------------------------------------------------------------------------------------------------
@@ -320,283 +324,285 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
aiTextureType type,
unsigned int index,
C_STRUCT aiString* path,
- aiTextureMapping* _mapping /*= NULL*/,
- unsigned int* uvindex /*= NULL*/,
- float* blend /*= NULL*/,
- aiTextureOp* op /*= NULL*/,
- aiTextureMapMode* mapmode /*= NULL*/,
- unsigned int* flags /*= NULL*/
- )
+ aiTextureMapping* _mapping /*= NULL*/,
+ unsigned int* uvindex /*= NULL*/,
+ float* blend /*= NULL*/,
+ aiTextureOp* op /*= NULL*/,
+ aiTextureMapMode* mapmode /*= NULL*/,
+ unsigned int* flags /*= NULL*/
+ )
{
- ai_assert(NULL != mat && 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
- aiTextureMapping mapping = aiTextureMapping_UV;
- aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&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;
+ ai_assert(NULL != mat && 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
+ aiTextureMapping mapping = aiTextureMapping_UV;
+ aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&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;
}
// ------------------------------------------------------------------------------------------------
// Construction. Actually the one and only way to get an aiMaterial instance
aiMaterial::aiMaterial()
{
- // Allocate 5 entries by default
- mNumProperties = 0;
- mNumAllocated = 5;
- mProperties = new aiMaterialProperty*[5];
+ // Allocate 5 entries by default
+ mNumProperties = 0;
+ mNumAllocated = 5;
+ mProperties = new aiMaterialProperty*[5];
}
// ------------------------------------------------------------------------------------------------
aiMaterial::~aiMaterial()
{
- Clear();
+ Clear();
- delete[] mProperties;
+ delete[] mProperties;
}
// ------------------------------------------------------------------------------------------------
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
+ 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(NULL != 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;
+ ai_assert(NULL != 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 pSizeInBytes,
+ const char* pKey,
+ unsigned int type,
unsigned int index,
- aiPropertyTypeInfo pType
- )
+ aiPropertyTypeInfo pType
+ )
{
- ai_assert (pInput != NULL);
- ai_assert (pKey != NULL);
- ai_assert (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&) {
- 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;
+ ai_assert (pInput != NULL);
+ ai_assert (pKey != NULL);
+ ai_assert (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,
+ const char* pKey,
+ unsigned int type,
unsigned int index)
{
- // We don't want to add the whole buffer .. write a 32 bit length
- // prefix followed by the zero-terminated UTF8 string.
- // (HACK) I don't want to break the ABI now, but we definitely
- // ought to change aiString::mLength to uint32_t one day.
- if (sizeof(size_t) == 8) {
- aiString copy = *pInput;
- uint32_t* s = reinterpret_cast<uint32_t*>(&copy.length);
- s[1] = static_cast<uint32_t>(pInput->length);
-
- return AddBinaryProperty(s+1,
- pInput->length+1+4,
- pKey,
- type,
- index,
- aiPTI_String);
- }
- ai_assert(sizeof(size_t)==4);
- return AddBinaryProperty(pInput,
- pInput->length+1+4,
- pKey,
- type,
- index,
- aiPTI_String);
+ // We don't want to add the whole buffer .. write a 32 bit length
+ // prefix followed by the zero-terminated UTF8 string.
+ // (HACK) I don't want to break the ABI now, but we definitely
+ // ought to change aiString::mLength to uint32_t one day.
+ if (sizeof(size_t) == 8) {
+ aiString copy = *pInput;
+ uint32_t* s = reinterpret_cast<uint32_t*>(&copy.length);
+ s[1] = static_cast<uint32_t>(pInput->length);
+
+ return AddBinaryProperty(s+1,
+ pInput->length+1+4,
+ pKey,
+ type,
+ index,
+ aiPTI_String);
+ }
+ ai_assert(sizeof(size_t)==4);
+ return AddBinaryProperty(pInput,
+ 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;
+ 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
- )
+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];
- }
-
- 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);
- }
- return;
+ 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);
+ }
+ return;
}
-
diff --git a/src/3rdparty/assimp/code/MaterialSystem.h b/src/3rdparty/assimp/code/MaterialSystem.h
index a891982a0..6726e0518 100644
--- a/src/3rdparty/assimp/code/MaterialSystem.h
+++ b/src/3rdparty/assimp/code/MaterialSystem.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,16 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_MATERIALSYSTEM_H_INC
#define AI_MATERIALSYSTEM_H_INC
-namespace Assimp {
+#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
+ * 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.
+ * '?' as initial character in their name into account.
* Currently #AI_MATKEY_NAME is the only example.
* @return 32 Bit jash value for the material
*/
diff --git a/src/3rdparty/assimp/code/MathFunctions.h b/src/3rdparty/assimp/code/MathFunctions.h
new file mode 100644
index 000000000..cb3b69607
--- /dev/null
+++ b/src/3rdparty/assimp/code/MathFunctions.h
@@ -0,0 +1,77 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+/** @file MathFunctions.h
+ * @brief Implementation of the math functions (gcd and lcm)
+ *
+ * Copied from BoostWorkaround/math
+ */
+
+namespace Assimp {
+namespace Math {
+
+// TODO: use binary GCD for unsigned integers ....
+template < typename IntegerType >
+IntegerType gcd( IntegerType a, IntegerType b )
+{
+ const IntegerType zero = (IntegerType)0;
+ while ( true )
+ {
+ if ( a == zero )
+ return b;
+ b %= a;
+
+ if ( b == zero )
+ return a;
+ a %= b;
+ }
+}
+
+template < typename IntegerType >
+IntegerType lcm( IntegerType a, IntegerType b )
+{
+ const IntegerType t = gcd (a,b);
+ if (!t)return t;
+ return a / t * b;
+}
+
+}
+}
diff --git a/src/3rdparty/assimp/code/MemoryIOWrapper.h b/src/3rdparty/assimp/code/MemoryIOWrapper.h
index 910843a8d..d6aaafae0 100644
--- a/src/3rdparty/assimp/code/MemoryIOWrapper.h
+++ b/src/3rdparty/assimp/code/MemoryIOWrapper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Handy IOStream/IOSystem implemetation to read directly from a memory buffer */
#ifndef AI_MEMORYIOSTREAM_H_INC
#define AI_MEMORYIOSTREAM_H_INC
-namespace Assimp {
+
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/ai_assert.h>
+#include <stdint.h>
+
+namespace Assimp {
#define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$"
#define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17
@@ -51,88 +57,88 @@ namespace Assimp {
// ----------------------------------------------------------------------------------
class MemoryIOStream : public IOStream
{
- //friend class MemoryIOSystem;
+ //friend class MemoryIOSystem;
public:
- MemoryIOStream (const uint8_t* buff, size_t len, bool own = false)
- : buffer (buff)
- , length(len)
- , pos((size_t)0)
- , own(own)
- {
- }
+ MemoryIOStream (const uint8_t* buff, size_t len, bool own = false)
+ : buffer (buff)
+ , length(len)
+ , pos((size_t)0)
+ , own(own)
+ {
+ }
public:
- ~MemoryIOStream () {
- if(own) {
- delete[] buffer;
- }
- }
-
- // -------------------------------------------------------------------
- // Read from stream
- size_t Read(void* pvBuffer, size_t pSize, size_t pCount) {
- const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt;
-
- memcpy(pvBuffer,buffer+pos,ofs);
- pos += ofs;
-
- return cnt;
- }
-
- // -------------------------------------------------------------------
- // Write to stream
- size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/,size_t /*pCount*/) {
- ai_assert(false); // won't be needed
- return 0;
- }
-
- // -------------------------------------------------------------------
- // Seek specific position
- aiReturn Seek(size_t pOffset, aiOrigin pOrigin) {
- if (aiOrigin_SET == pOrigin) {
- if (pOffset >= length) {
- return AI_FAILURE;
- }
- pos = pOffset;
- }
- else if (aiOrigin_END == pOrigin) {
- if (pOffset >= length) {
- return AI_FAILURE;
- }
- pos = length-pOffset;
- }
- else {
- if (pOffset+pos >= length) {
- return AI_FAILURE;
- }
- pos += pOffset;
- }
- return AI_SUCCESS;
- }
-
- // -------------------------------------------------------------------
- // Get current seek position
- size_t Tell() const {
- return pos;
- }
-
- // -------------------------------------------------------------------
- // Get size of file
- size_t FileSize() const {
- return length;
- }
-
- // -------------------------------------------------------------------
- // Flush file contents
- void Flush() {
- ai_assert(false); // won't be needed
- }
+ ~MemoryIOStream () {
+ if(own) {
+ delete[] buffer;
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Read from stream
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount) {
+ const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt;
+
+ memcpy(pvBuffer,buffer+pos,ofs);
+ pos += ofs;
+
+ return cnt;
+ }
+
+ // -------------------------------------------------------------------
+ // Write to stream
+ size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/,size_t /*pCount*/) {
+ ai_assert(false); // won't be needed
+ return 0;
+ }
+
+ // -------------------------------------------------------------------
+ // Seek specific position
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin) {
+ if (aiOrigin_SET == pOrigin) {
+ if (pOffset >= length) {
+ return AI_FAILURE;
+ }
+ pos = pOffset;
+ }
+ else if (aiOrigin_END == pOrigin) {
+ if (pOffset >= length) {
+ return AI_FAILURE;
+ }
+ pos = length-pOffset;
+ }
+ else {
+ if (pOffset+pos >= length) {
+ return AI_FAILURE;
+ }
+ pos += pOffset;
+ }
+ return AI_SUCCESS;
+ }
+
+ // -------------------------------------------------------------------
+ // Get current seek position
+ size_t Tell() const {
+ return pos;
+ }
+
+ // -------------------------------------------------------------------
+ // Get size of file
+ size_t FileSize() const {
+ return length;
+ }
+
+ // -------------------------------------------------------------------
+ // Flush file contents
+ void Flush() {
+ ai_assert(false); // won't be needed
+ }
private:
- const uint8_t* buffer;
- size_t length,pos;
- bool own;
+ const uint8_t* buffer;
+ size_t length,pos;
+ bool own;
};
// ---------------------------------------------------------------------------
@@ -140,50 +146,51 @@ private:
class MemoryIOSystem : public IOSystem
{
public:
- /** Constructor. */
- MemoryIOSystem (const uint8_t* buff, size_t len)
- : buffer (buff), length(len) {
- }
-
- /** Destructor. */
- ~MemoryIOSystem() {
- }
-
- // -------------------------------------------------------------------
- /** Tests for the existence of a file at the given path. */
- bool Exists( const char* pFile) const {
- return !strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH);
- }
-
- // -------------------------------------------------------------------
- /** Returns the directory separator. */
- char getOsSeparator() const {
- return '/'; // why not? it doesn't care
- }
-
- // -------------------------------------------------------------------
- /** Open a new file with a given path. */
- IOStream* Open( const char* pFile, const char* /*pMode*/ = "rb") {
- if (strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
- return NULL;
- }
- return new MemoryIOStream(buffer,length);
- }
-
- // -------------------------------------------------------------------
- /** Closes the given file and releases all resources associated with it. */
- void Close( IOStream* /*pFile*/) {
- }
-
- // -------------------------------------------------------------------
- /** Compare two paths */
- bool ComparePaths (const char* /*one*/, const char* /*second*/) const {
- return false;
- }
+ /** Constructor. */
+ MemoryIOSystem (const uint8_t* buff, size_t len)
+ : buffer (buff), length(len) {
+ }
+
+ /** Destructor. */
+ ~MemoryIOSystem() {
+ }
+
+ // -------------------------------------------------------------------
+ /** Tests for the existence of a file at the given path. */
+ bool Exists( const char* pFile) const {
+ return !strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH);
+ }
+
+ // -------------------------------------------------------------------
+ /** Returns the directory separator. */
+ char getOsSeparator() const {
+ return '/'; // why not? it doesn't care
+ }
+
+ // -------------------------------------------------------------------
+ /** Open a new file with a given path. */
+ IOStream* Open( const char* pFile, const char* /*pMode*/ = "rb") {
+ if (strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) {
+ return NULL;
+ }
+ return new MemoryIOStream(buffer,length);
+ }
+
+ // -------------------------------------------------------------------
+ /** Closes the given file and releases all resources associated with it. */
+ void Close( IOStream* pFile) {
+ delete pFile;
+ }
+
+ // -------------------------------------------------------------------
+ /** Compare two paths */
+ bool ComparePaths (const char* /*one*/, const char* /*second*/) const {
+ return false;
+ }
private:
- const uint8_t* buffer;
- size_t length;
+ const uint8_t* buffer;
+ size_t length;
};
} // end namespace Assimp
diff --git a/src/3rdparty/assimp/code/NDOLoader.cpp b/src/3rdparty/assimp/code/NDOLoader.cpp
index 65306b396..f04eb5345 100644
--- a/src/3rdparty/assimp/code/NDOLoader.cpp
+++ b/src/3rdparty/assimp/code/NDOLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,24 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implementation of the NDO importer class.
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
#include "NDOLoader.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include "StreamReader.h"
using namespace Assimp;
-#define for_each BOOST_FOREACH
static const aiImporterDesc desc = {
- "Nendo Mesh Importer",
- "",
- "",
- "http://www.izware.com/nendo/index.htm",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "ndo"
+ "Nendo Mesh Importer",
+ "",
+ "",
+ "http://www.izware.com/nendo/index.htm",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ndo"
};
// ------------------------------------------------------------------------------------------------
@@ -69,234 +72,234 @@ NDOImporter::NDOImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
NDOImporter::~NDOImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- // check file extension
- const std::string extension = GetExtension(pFile);
-
- if( extension == "ndo")
- return true;
-
- if ((checkSig || !extension.length()) && pIOHandler) {
- const char* tokens[] = {"nendo"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5);
- }
- return false;
+ // check file extension
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "ndo")
+ return true;
+
+ if ((checkSig || !extension.length()) && pIOHandler) {
+ const char* tokens[] = {"nendo"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported
const aiImporterDesc* NDOImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void NDOImporter::SetupProperties(const Importer* /*pImp*/)
{
- // nothing to be done for the moment
+ // nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void NDOImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void NDOImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
-
- // first 9 bytes are nendo file format ("nendo 1.n")
- const char* head = (const char*)reader.GetPtr();
- reader.IncPtr(9);
-
- if (strncmp("nendo ",head,6)) {
- throw DeadlyImportError("Not a Nendo file; magic signature missing");
- }
- // check if this is a supported version. if not, continue, too -- users,
- // please don't complain if it doesn't work then ...
- unsigned int file_format = 12;
- if (!strncmp("1.0",head+6,3)) {
- file_format = 10;
- DefaultLogger::get()->info("NDO file format is 1.0");
- }
- else if (!strncmp("1.1",head+6,3)) {
- file_format = 11;
- DefaultLogger::get()->info("NDO file format is 1.1");
- }
- else if (!strncmp("1.2",head+6,3)) {
- file_format = 12;
- DefaultLogger::get()->info("NDO file format is 1.2");
- }
- else {
- DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6));
- }
-
- reader.IncPtr(2); /* skip flags */
- if (file_format >= 12) {
- reader.IncPtr(2);
- }
- unsigned int temp = reader.GetU1();
-
- std::vector<Object> objects(temp); /* buffer to store all the loaded objects in */
-
- // read all objects
- for (unsigned int o = 0; o < objects.size(); ++o) {
-
-// if (file_format < 12) {
- if (!reader.GetI1()) {
- continue; /* skip over empty object */
- }
- // reader.GetI2();
-// }
- Object& obj = objects[o];
-
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- head = (const char*)reader.GetPtr();
- reader.IncPtr(temp + 76); /* skip unknown stuff */
-
- obj.name = std::string(head, temp);
-
- // read edge table
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- obj.edges.reserve(temp);
- for (unsigned int e = 0; e < temp; ++e) {
-
- obj.edges.push_back(Edge());
- Edge& edge = obj.edges.back();
-
- for (unsigned int i = 0; i< 8; ++i) {
- edge.edge[i] = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- }
- edge.hard = file_format >= 11 ? reader.GetU1() : 0;
- for (unsigned int i = 0; i< 8; ++i) {
- edge.color[i] = reader.GetU1();
- }
- }
-
- // read face table
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- obj.faces.reserve(temp);
- for (unsigned int e = 0; e < temp; ++e) {
-
- obj.faces.push_back(Face());
- Face& face = obj.faces.back();
-
- face.elem = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- }
-
- // read vertex table
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- obj.vertices.reserve(temp);
- for (unsigned int e = 0; e < temp; ++e) {
-
- obj.vertices.push_back(Vertex());
- Vertex& v = obj.vertices.back();
-
- v.num = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- v.val.x = reader.GetF4();
- v.val.y = reader.GetF4();
- v.val.z = reader.GetF4();
- }
-
- // read UVs
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- for (unsigned int e = 0; e < temp; ++e) {
- file_format >= 12 ? reader.GetU4() : reader.GetU2();
- }
-
- temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
- for (unsigned int e = 0; e < temp; ++e) {
- file_format >= 12 ? reader.GetU4() : reader.GetU2();
- }
-
- if (reader.GetU1()) {
- const unsigned int x = reader.GetU2(), y = reader.GetU2();
- temp = 0;
- while (temp < x*y) {
- unsigned int repeat = reader.GetU1();
- reader.GetU1();
- reader.GetU1();
- reader.GetU1();
- temp += repeat;
- }
- }
- }
-
- // construct a dummy node graph and add all named objects as child nodes
- aiNode* root = pScene->mRootNode = new aiNode("$NDODummyRoot");
- aiNode** cc = root->mChildren = new aiNode* [ root->mNumChildren = static_cast<unsigned int>( objects.size()) ] ();
- pScene->mMeshes = new aiMesh* [ root->mNumChildren] ();
-
- std::vector<aiVector3D> vertices;
- std::vector<unsigned int> indices;
-
- for_each(const Object& obj,objects) {
- aiNode* nd = *cc++ = new aiNode(obj.name);
- nd->mParent = root;
-
- // translated from a python dict() - a vector might be sufficient as well
- typedef std::map<unsigned int, unsigned int> FaceTable;
- FaceTable face_table;
-
- unsigned int n = 0;
- for_each(const Edge& edge, obj.edges) {
-
- face_table[edge.edge[2]] = n;
- face_table[edge.edge[3]] = n;
-
- ++n;
- }
-
- aiMesh* mesh = new aiMesh();
- aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()];
-
- vertices.clear();
- vertices.reserve(4 * face_table.size()); // arbitrarily choosen
- for_each(FaceTable::value_type& v, face_table) {
- indices.clear();
-
- aiFace& f = *faces++;
-
- const unsigned int key = v.first;
- unsigned int cur_edge = v.second;
- while (1) {
- unsigned int next_edge, next_vert;
- if (key == obj.edges[cur_edge].edge[3]) {
- next_edge = obj.edges[cur_edge].edge[5];
- next_vert = obj.edges[cur_edge].edge[1];
- }
- else {
- next_edge = obj.edges[cur_edge].edge[4];
- next_vert = obj.edges[cur_edge].edge[0];
- }
- indices.push_back( vertices.size() );
- vertices.push_back(obj.vertices[ next_vert ].val);
-
- cur_edge = next_edge;
- if (cur_edge == v.second) {
- break;
- }
- }
-
- f.mIndices = new unsigned int[f.mNumIndices = indices.size()];
- std::copy(indices.begin(),indices.end(),f.mIndices);
- }
-
- mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()];
- std::copy(vertices.begin(),vertices.end(),mesh->mVertices);
-
- if (mesh->mNumVertices) {
- pScene->mMeshes[pScene->mNumMeshes] = mesh;
-
- (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++;
- }
- }
+ StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
+
+ // first 9 bytes are nendo file format ("nendo 1.n")
+ const char* head = (const char*)reader.GetPtr();
+ reader.IncPtr(9);
+
+ if (strncmp("nendo ",head,6)) {
+ throw DeadlyImportError("Not a Nendo file; magic signature missing");
+ }
+ // check if this is a supported version. if not, continue, too -- users,
+ // please don't complain if it doesn't work then ...
+ unsigned int file_format = 12;
+ if (!strncmp("1.0",head+6,3)) {
+ file_format = 10;
+ DefaultLogger::get()->info("NDO file format is 1.0");
+ }
+ else if (!strncmp("1.1",head+6,3)) {
+ file_format = 11;
+ DefaultLogger::get()->info("NDO file format is 1.1");
+ }
+ else if (!strncmp("1.2",head+6,3)) {
+ file_format = 12;
+ DefaultLogger::get()->info("NDO file format is 1.2");
+ }
+ else {
+ DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6));
+ }
+
+ reader.IncPtr(2); /* skip flags */
+ if (file_format >= 12) {
+ reader.IncPtr(2);
+ }
+ unsigned int temp = reader.GetU1();
+
+ std::vector<Object> objects(temp); /* buffer to store all the loaded objects in */
+
+ // read all objects
+ for (unsigned int o = 0; o < objects.size(); ++o) {
+
+// if (file_format < 12) {
+ if (!reader.GetI1()) {
+ continue; /* skip over empty object */
+ }
+ // reader.GetI2();
+// }
+ Object& obj = objects[o];
+
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ head = (const char*)reader.GetPtr();
+ reader.IncPtr(temp + 76); /* skip unknown stuff */
+
+ obj.name = std::string(head, temp);
+
+ // read edge table
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ obj.edges.reserve(temp);
+ for (unsigned int e = 0; e < temp; ++e) {
+
+ obj.edges.push_back(Edge());
+ Edge& edge = obj.edges.back();
+
+ for (unsigned int i = 0; i< 8; ++i) {
+ edge.edge[i] = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ }
+ edge.hard = file_format >= 11 ? reader.GetU1() : 0;
+ for (unsigned int i = 0; i< 8; ++i) {
+ edge.color[i] = reader.GetU1();
+ }
+ }
+
+ // read face table
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ obj.faces.reserve(temp);
+ for (unsigned int e = 0; e < temp; ++e) {
+
+ obj.faces.push_back(Face());
+ Face& face = obj.faces.back();
+
+ face.elem = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ }
+
+ // read vertex table
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ obj.vertices.reserve(temp);
+ for (unsigned int e = 0; e < temp; ++e) {
+
+ obj.vertices.push_back(Vertex());
+ Vertex& v = obj.vertices.back();
+
+ v.num = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ v.val.x = reader.GetF4();
+ v.val.y = reader.GetF4();
+ v.val.z = reader.GetF4();
+ }
+
+ // read UVs
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ for (unsigned int e = 0; e < temp; ++e) {
+ file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ }
+
+ temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ for (unsigned int e = 0; e < temp; ++e) {
+ file_format >= 12 ? reader.GetU4() : reader.GetU2();
+ }
+
+ if (reader.GetU1()) {
+ const unsigned int x = reader.GetU2(), y = reader.GetU2();
+ temp = 0;
+ while (temp < x*y) {
+ unsigned int repeat = reader.GetU1();
+ reader.GetU1();
+ reader.GetU1();
+ reader.GetU1();
+ temp += repeat;
+ }
+ }
+ }
+
+ // construct a dummy node graph and add all named objects as child nodes
+ aiNode* root = pScene->mRootNode = new aiNode("$NDODummyRoot");
+ aiNode** cc = root->mChildren = new aiNode* [ root->mNumChildren = static_cast<unsigned int>( objects.size()) ] ();
+ pScene->mMeshes = new aiMesh* [ root->mNumChildren] ();
+
+ std::vector<aiVector3D> vertices;
+ std::vector<unsigned int> indices;
+
+ for(const Object& obj : objects) {
+ aiNode* nd = *cc++ = new aiNode(obj.name);
+ nd->mParent = root;
+
+ // translated from a python dict() - a vector might be sufficient as well
+ typedef std::map<unsigned int, unsigned int> FaceTable;
+ FaceTable face_table;
+
+ unsigned int n = 0;
+ for(const Edge& edge : obj.edges) {
+
+ face_table[edge.edge[2]] = n;
+ face_table[edge.edge[3]] = n;
+
+ ++n;
+ }
+
+ aiMesh* mesh = new aiMesh();
+ aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()];
+
+ vertices.clear();
+ vertices.reserve(4 * face_table.size()); // arbitrarily chosen
+ for(FaceTable::value_type& v : face_table) {
+ indices.clear();
+
+ aiFace& f = *faces++;
+
+ const unsigned int key = v.first;
+ unsigned int cur_edge = v.second;
+ while (1) {
+ unsigned int next_edge, next_vert;
+ if (key == obj.edges[cur_edge].edge[3]) {
+ next_edge = obj.edges[cur_edge].edge[5];
+ next_vert = obj.edges[cur_edge].edge[1];
+ }
+ else {
+ next_edge = obj.edges[cur_edge].edge[4];
+ next_vert = obj.edges[cur_edge].edge[0];
+ }
+ indices.push_back( vertices.size() );
+ vertices.push_back(obj.vertices[ next_vert ].val);
+
+ cur_edge = next_edge;
+ if (cur_edge == v.second) {
+ break;
+ }
+ }
+
+ f.mIndices = new unsigned int[f.mNumIndices = indices.size()];
+ std::copy(indices.begin(),indices.end(),f.mIndices);
+ }
+
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()];
+ std::copy(vertices.begin(),vertices.end(),mesh->mVertices);
+
+ if (mesh->mNumVertices) {
+ pScene->mMeshes[pScene->mNumMeshes] = mesh;
+
+ (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++;
+ }
+ }
}
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/NDOLoader.h b/src/3rdparty/assimp/code/NDOLoader.h
index 348800346..4fd315691 100644
--- a/src/3rdparty/assimp/code/NDOLoader.h
+++ b/src/3rdparty/assimp/code/NDOLoader.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,68 +43,81 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INCLUDED_AI_NDO_LOADER_H
#define INCLUDED_AI_NDO_LOADER_H
-namespace Assimp {
+
+#include <assimp/vector3.h>
+#include "BaseImporter.h"
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+
+struct aiImporterDesc;
+struct aiScene;
+
+namespace Assimp {
+ class IOSystem;
+ class Importer;
// ---------------------------------------------------------------------------
/** @brief Importer class to load meshes from Nendo.
*
* Basing on
- * <blender>/blender/release/scripts/nendo_import.py by Anthony D'Agostino.
+ * <blender>/blender/release/scripts/nendo_import.py by Anthony D'Agostino.
*/
class NDOImporter : public BaseImporter
{
public:
- NDOImporter();
- ~NDOImporter();
+ NDOImporter();
+ ~NDOImporter();
public:
- //! Represents a single edge
- struct Edge
- {
- unsigned int edge[8];
- unsigned int hard;
- uint8_t color[8];
- };
-
- //! Represents a single face
- struct Face
- {
- unsigned int elem;
- };
-
- struct Vertex
- {
- unsigned int num;
- aiVector3D val;
- };
-
- //! Represents a single object
- struct Object
- {
- std::string name;
-
- std::vector<Edge> edges;
- std::vector<Face> faces;
- std::vector<Vertex> vertices;
- };
-
- // -------------------------------------------------------------------
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ //! Represents a single edge
+ struct Edge
+ {
+ unsigned int edge[8];
+ unsigned int hard;
+ uint8_t color[8];
+ };
+
+ //! Represents a single face
+ struct Face
+ {
+ unsigned int elem;
+ };
+
+ struct Vertex
+ {
+ unsigned int num;
+ aiVector3D val;
+ };
+
+ //! Represents a single object
+ struct Object
+ {
+ std::string name;
+
+ std::vector<Edge> edges;
+ std::vector<Face> faces;
+ std::vector<Vertex> vertices;
+ };
+
+ // -------------------------------------------------------------------
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
- // -------------------------------------------------------------------
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
diff --git a/src/3rdparty/assimp/code/NFFLoader.cpp b/src/3rdparty/assimp/code/NFFLoader.cpp
index b81698a56..8bec63ea3 100644
--- a/src/3rdparty/assimp/code/NFFLoader.cpp
+++ b/src/3rdparty/assimp/code/NFFLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,45 +25,51 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the STL importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER
// internal headers
#include "NFFLoader.h"
#include "ParsingUtils.h"
#include "StandardShapes.h"
+#include "qnan.h"
#include "fast_atof.h"
#include "RemoveComments.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <memory>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Neutral File Format Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "enff nff"
+ "Neutral File Format Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "enff nff"
};
// ------------------------------------------------------------------------------------------------
@@ -72,1197 +78,1194 @@ NFFImporter::NFFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
NFFImporter::~NFFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool NFFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
{
- return SimpleExtensionCheck(pFile,"nff","enff");
+ return SimpleExtensionCheck(pFile,"nff","enff");
}
// ------------------------------------------------------------------------------------------------
// Get the list of all supported file extensions
const aiImporterDesc* NFFImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_FLOAT(f) \
- SkipSpaces(&sz); \
- if (!::IsLineEnd(*sz))sz = fast_atoreal_move<float>(sz, (float&)f);
+ SkipSpaces(&sz); \
+ if (!::IsLineEnd(*sz))sz = fast_atoreal_move<float>(sz, (float&)f);
// ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_TRIPLE(v) \
- AI_NFF_PARSE_FLOAT(v[0]) \
- AI_NFF_PARSE_FLOAT(v[1]) \
- AI_NFF_PARSE_FLOAT(v[2])
+ AI_NFF_PARSE_FLOAT(v[0]) \
+ AI_NFF_PARSE_FLOAT(v[1]) \
+ AI_NFF_PARSE_FLOAT(v[2])
// ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_SHAPE_INFORMATION() \
- aiVector3D center, radius(1.0f,get_qnan(),get_qnan()); \
- AI_NFF_PARSE_TRIPLE(center); \
- AI_NFF_PARSE_TRIPLE(radius); \
- if (is_qnan(radius.z))radius.z = radius.x; \
- if (is_qnan(radius.y))radius.y = radius.x; \
- currentMesh.radius = radius; \
- currentMesh.center = center;
+ aiVector3D center, radius(1.0f,get_qnan(),get_qnan()); \
+ AI_NFF_PARSE_TRIPLE(center); \
+ AI_NFF_PARSE_TRIPLE(radius); \
+ if (is_qnan(radius.z))radius.z = radius.x; \
+ if (is_qnan(radius.y))radius.y = radius.x; \
+ currentMesh.radius = radius; \
+ currentMesh.center = center;
// ------------------------------------------------------------------------------------------------
#define AI_NFF2_GET_NEXT_TOKEN() \
- do \
- { \
- if (!GetNextLine(buffer,line)) \
- {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read next token");break;} \
- SkipSpaces(line,&sz); \
- } \
- while(IsLineEnd(*sz))
+ do \
+ { \
+ if (!GetNextLine(buffer,line)) \
+ {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read next token");break;} \
+ SkipSpaces(line,&sz); \
+ } \
+ while(IsLineEnd(*sz))
// ------------------------------------------------------------------------------------------------
// Loads the materail table for the NFF2 file format from an external file
void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo>& output,
- const std::string& path, IOSystem* pIOHandler)
+ const std::string& path, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( path, "rb"));
-
- // Check whether we can read from the file
- if( !file.get()) {
- DefaultLogger::get()->error("NFF2: Unable to open material library " + path + ".");
- return;
- }
-
- // get the size of the file
- const unsigned int m = (unsigned int)file->FileSize();
-
- // allocate storage and copy the contents of the file to a memory buffer
- // (terminate it with zero)
- std::vector<char> mBuffer2(m+1);
- TextFileToBuffer(file.get(),mBuffer2);
- const char* buffer = &mBuffer2[0];
-
- // First of all: remove all comments from the file
- CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
-
- // The file should start with the magic sequence "mat"
- if (!TokenMatch(buffer,"mat",3)) {
- DefaultLogger::get()->error("NFF2: Not a valid material library " + path + ".");
- return;
- }
-
- ShadingInfo* curShader = NULL;
-
- // No read the file line per line
- char line[4096];
- const char* sz;
- while (GetNextLine(buffer,line))
- {
- SkipSpaces(line,&sz);
-
- // 'version' defines the version of the file format
- if (TokenMatch(sz,"version",7))
- {
- DefaultLogger::get()->info("NFF (Sense8) material library file format: " + std::string(sz));
- }
- // 'matdef' starts a new material in the file
- else if (TokenMatch(sz,"matdef",6))
- {
- // add a new material to the list
- output.push_back( ShadingInfo() );
- curShader = & output.back();
-
- // parse the name of the material
- }
- else if (!TokenMatch(sz,"valid",5))
- {
- // check whether we have an active material at the moment
- if (!IsLineEnd(*sz))
- {
- if (!curShader)
- {
- DefaultLogger::get()->error(std::string("NFF2 material library: Found element ") +
- sz + "but there is no active material");
- continue;
- }
- }
- else continue;
-
- // now read the material property and determine its type
- aiColor3D c;
- if (TokenMatch(sz,"ambient",7))
- {
- AI_NFF_PARSE_TRIPLE(c);
- curShader->ambient = c;
- }
- else if (TokenMatch(sz,"diffuse",7) || TokenMatch(sz,"ambientdiffuse",14) /* correct? */)
- {
- AI_NFF_PARSE_TRIPLE(c);
- curShader->diffuse = curShader->ambient = c;
- }
- else if (TokenMatch(sz,"specular",8))
- {
- AI_NFF_PARSE_TRIPLE(c);
- curShader->specular = c;
- }
- else if (TokenMatch(sz,"emission",8))
- {
- AI_NFF_PARSE_TRIPLE(c);
- curShader->emissive = c;
- }
- else if (TokenMatch(sz,"shininess",9))
- {
- AI_NFF_PARSE_FLOAT(curShader->shininess);
- }
- else if (TokenMatch(sz,"opacity",7))
- {
- AI_NFF_PARSE_FLOAT(curShader->opacity);
- }
- }
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( path, "rb"));
+
+ // Check whether we can read from the file
+ if( !file.get()) {
+ DefaultLogger::get()->error("NFF2: Unable to open material library " + path + ".");
+ return;
+ }
+
+ // get the size of the file
+ const unsigned int m = (unsigned int)file->FileSize();
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ // (terminate it with zero)
+ std::vector<char> mBuffer2(m+1);
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ // First of all: remove all comments from the file
+ CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
+
+ // The file should start with the magic sequence "mat"
+ if (!TokenMatch(buffer,"mat",3)) {
+ DefaultLogger::get()->error("NFF2: Not a valid material library " + path + ".");
+ return;
+ }
+
+ ShadingInfo* curShader = NULL;
+
+ // No read the file line per line
+ char line[4096];
+ const char* sz;
+ while (GetNextLine(buffer,line))
+ {
+ SkipSpaces(line,&sz);
+
+ // 'version' defines the version of the file format
+ if (TokenMatch(sz,"version",7))
+ {
+ DefaultLogger::get()->info("NFF (Sense8) material library file format: " + std::string(sz));
+ }
+ // 'matdef' starts a new material in the file
+ else if (TokenMatch(sz,"matdef",6))
+ {
+ // add a new material to the list
+ output.push_back( ShadingInfo() );
+ curShader = & output.back();
+
+ // parse the name of the material
+ }
+ else if (!TokenMatch(sz,"valid",5))
+ {
+ // check whether we have an active material at the moment
+ if (!IsLineEnd(*sz))
+ {
+ if (!curShader)
+ {
+ DefaultLogger::get()->error(std::string("NFF2 material library: Found element ") +
+ sz + "but there is no active material");
+ continue;
+ }
+ }
+ else continue;
+
+ // now read the material property and determine its type
+ aiColor3D c;
+ if (TokenMatch(sz,"ambient",7))
+ {
+ AI_NFF_PARSE_TRIPLE(c);
+ curShader->ambient = c;
+ }
+ else if (TokenMatch(sz,"diffuse",7) || TokenMatch(sz,"ambientdiffuse",14) /* correct? */)
+ {
+ AI_NFF_PARSE_TRIPLE(c);
+ curShader->diffuse = curShader->ambient = c;
+ }
+ else if (TokenMatch(sz,"specular",8))
+ {
+ AI_NFF_PARSE_TRIPLE(c);
+ curShader->specular = c;
+ }
+ else if (TokenMatch(sz,"emission",8))
+ {
+ AI_NFF_PARSE_TRIPLE(c);
+ curShader->emissive = c;
+ }
+ else if (TokenMatch(sz,"shininess",9))
+ {
+ AI_NFF_PARSE_FLOAT(curShader->shininess);
+ }
+ else if (TokenMatch(sz,"opacity",7))
+ {
+ AI_NFF_PARSE_FLOAT(curShader->opacity);
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void NFFImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void NFFImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( !file.get())
- throw DeadlyImportError( "Failed to open NFF file " + pFile + ".");
-
- unsigned int m = (unsigned int)file->FileSize();
-
- // allocate storage and copy the contents of the file to a memory buffer
- // (terminate it with zero)
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
- const char* buffer = &mBuffer2[0];
-
- // mesh arrays - separate here to make the handling of the pointers below easier.
- std::vector<MeshInfo> meshes;
- std::vector<MeshInfo> meshesWithNormals;
- std::vector<MeshInfo> meshesWithUVCoords;
- std::vector<MeshInfo> meshesLocked;
-
- char line[4096];
- const char* sz;
-
- // camera parameters
- aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f);
- float angle = 45.f;
- aiVector2D resolution;
-
- bool hasCam = false;
-
- MeshInfo* currentMeshWithNormals = NULL;
- MeshInfo* currentMesh = NULL;
- MeshInfo* currentMeshWithUVCoords = NULL;
-
- ShadingInfo s; // current material info
-
- // degree of tesselation
- unsigned int iTesselation = 4;
-
- // some temporary variables we need to parse the file
- unsigned int sphere = 0,
- cylinder = 0,
- cone = 0,
- numNamed = 0,
- dodecahedron = 0,
- octahedron = 0,
- tetrahedron = 0,
- hexahedron = 0;
-
- // lights imported from the file
- std::vector<Light> lights;
-
- // check whether this is the NFF2 file format
- if (TokenMatch(buffer,"nff",3))
- {
- const float qnan = get_qnan();
- const aiColor4D cQNAN = aiColor4D (qnan,0.f,0.f,1.f);
- const aiVector3D vQNAN = aiVector3D(qnan,0.f,0.f);
-
- // another NFF file format ... just a raw parser has been implemented
- // no support for further details, I don't think it is worth the effort
- // http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html
- // http://www.netghost.narod.ru/gff/graphics/summary/sense8.htm
-
- // First of all: remove all comments from the file
- CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
-
- while (GetNextLine(buffer,line))
- {
- SkipSpaces(line,&sz);
- if (TokenMatch(sz,"version",7))
- {
- DefaultLogger::get()->info("NFF (Sense8) file format: " + std::string(sz));
- }
- else if (TokenMatch(sz,"viewpos",7))
- {
- AI_NFF_PARSE_TRIPLE(camPos);
- hasCam = true;
- }
- else if (TokenMatch(sz,"viewdir",7))
- {
- AI_NFF_PARSE_TRIPLE(camLookAt);
- hasCam = true;
- }
- // This starts a new object section
- else if (!IsSpaceOrNewLine(*sz))
- {
- unsigned int subMeshIdx = 0;
-
- // read the name of the object, skip all spaces
- // at the end of it.
- const char* sz3 = sz;
- while (!IsSpaceOrNewLine(*sz))++sz;
- std::string objectName = std::string(sz3,(unsigned int)(sz-sz3));
-
- const unsigned int objStart = (unsigned int)meshes.size();
-
- // There could be a material table in a separate file
- std::vector<ShadingInfo> materialTable;
- while (true)
- {
- AI_NFF2_GET_NEXT_TOKEN();
-
- // material table - an external file
- if (TokenMatch(sz,"mtable",6))
- {
- SkipSpaces(&sz);
- sz3 = sz;
- while (!IsSpaceOrNewLine(*sz))++sz;
- const unsigned int diff = (unsigned int)(sz-sz3);
- if (!diff)DefaultLogger::get()->warn("NFF2: Found empty mtable token");
- else
- {
- // The material table has the file extension .mat.
- // If it is not there, we need to append it
- std::string path = std::string(sz3,diff);
- if(std::string::npos == path.find_last_of(".mat"))
- {
- path.append(".mat");
- }
-
- // Now extract the working directory from the path to
- // this file and append the material library filename
- // to it.
- std::string::size_type s;
- if ((std::string::npos == (s = path.find_last_of('\\')) || !s) &&
- (std::string::npos == (s = path.find_last_of('/')) || !s) )
- {
- s = pFile.find_last_of('\\');
- if (std::string::npos == s)s = pFile.find_last_of('/');
- if (std::string::npos != s)
- {
- path = pFile.substr(0,s+1) + path;
- }
- }
- LoadNFF2MaterialTable(materialTable,path,pIOHandler);
- }
- }
- else break;
- }
-
- // read the numbr of vertices
- unsigned int num = ::strtoul10(sz,&sz);
-
- // temporary storage
- std::vector<aiColor4D> tempColors;
- std::vector<aiVector3D> tempPositions,tempTextureCoords,tempNormals;
-
- bool hasNormals = false,hasUVs = false,hasColor = false;
-
- tempPositions.reserve (num);
- tempColors.reserve (num);
- tempNormals.reserve (num);
- tempTextureCoords.reserve (num);
- for (unsigned int i = 0; i < num; ++i)
- {
- AI_NFF2_GET_NEXT_TOKEN();
- aiVector3D v;
- AI_NFF_PARSE_TRIPLE(v);
- tempPositions.push_back(v);
-
- // parse all other attributes in the line
- while (true)
- {
- SkipSpaces(&sz);
- if (IsLineEnd(*sz))break;
-
- // color definition
- if (TokenMatch(sz,"0x",2))
- {
- hasColor = true;
- unsigned int numIdx = ::strtoul16(sz,&sz);
- aiColor4D clr;
- clr.a = 1.f;
-
- // 0xRRGGBB
- clr.r = ((numIdx >> 16u) & 0xff) / 255.f;
- clr.g = ((numIdx >> 8u) & 0xff) / 255.f;
- clr.b = ((numIdx) & 0xff) / 255.f;
- tempColors.push_back(clr);
- }
- // normal vector
- else if (TokenMatch(sz,"norm",4))
- {
- hasNormals = true;
- AI_NFF_PARSE_TRIPLE(v);
- tempNormals.push_back(v);
- }
- // UV coordinate
- else if (TokenMatch(sz,"uv",2))
- {
- hasUVs = true;
- AI_NFF_PARSE_FLOAT(v.x);
- AI_NFF_PARSE_FLOAT(v.y);
- v.z = 0.f;
- tempTextureCoords.push_back(v);
- }
- }
-
- // fill in dummies for all attributes that have not been set
- if (tempNormals.size() != tempPositions.size())
- tempNormals.push_back(vQNAN);
-
- if (tempTextureCoords.size() != tempPositions.size())
- tempTextureCoords.push_back(vQNAN);
-
- if (tempColors.size() != tempPositions.size())
- tempColors.push_back(cQNAN);
- }
-
- AI_NFF2_GET_NEXT_TOKEN();
- if (!num)throw DeadlyImportError("NFF2: There are zero vertices");
- num = ::strtoul10(sz,&sz);
-
- std::vector<unsigned int> tempIdx;
- tempIdx.reserve(10);
- for (unsigned int i = 0; i < num; ++i)
- {
- AI_NFF2_GET_NEXT_TOKEN();
- SkipSpaces(line,&sz);
- unsigned int numIdx = ::strtoul10(sz,&sz);
-
- // read all faces indices
- if (numIdx)
- {
- // mesh.faces.push_back(numIdx);
- // tempIdx.erase(tempIdx.begin(),tempIdx.end());
- tempIdx.resize(numIdx);
-
- for (unsigned int a = 0; a < numIdx;++a)
- {
- SkipSpaces(sz,&sz);
- m = ::strtoul10(sz,&sz);
- if (m >= (unsigned int)tempPositions.size())
- {
- DefaultLogger::get()->error("NFF2: Vertex index overflow");
- m= 0;
- }
- // mesh.vertices.push_back (tempPositions[idx]);
- tempIdx[a] = m;
- }
- }
-
- // build a temporary shader object for the face.
- ShadingInfo shader;
- unsigned int matIdx = 0;
-
- // white material color - we have vertex colors
- shader.color = aiColor3D(1.f,1.f,1.f);
- aiColor4D c = aiColor4D(1.f,1.f,1.f,1.f);
- while (true)
- {
- SkipSpaces(sz,&sz);
- if(IsLineEnd(*sz))break;
-
- // per-polygon colors
- if (TokenMatch(sz,"0x",2))
- {
- hasColor = true;
- const char* sz2 = sz;
- numIdx = ::strtoul16(sz,&sz);
- const unsigned int diff = (unsigned int)(sz-sz2);
-
- // 0xRRGGBB
- if (diff > 3)
- {
- c.r = ((numIdx >> 16u) & 0xff) / 255.f;
- c.g = ((numIdx >> 8u) & 0xff) / 255.f;
- c.b = ((numIdx) & 0xff) / 255.f;
- }
- // 0xRGB
- else
- {
- c.r = ((numIdx >> 8u) & 0xf) / 16.f;
- c.g = ((numIdx >> 4u) & 0xf) / 16.f;
- c.b = ((numIdx) & 0xf) / 16.f;
- }
- }
- // TODO - implement texture mapping here
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( !file.get())
+ throw DeadlyImportError( "Failed to open NFF file " + pFile + ".");
+
+ unsigned int m = (unsigned int)file->FileSize();
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ // (terminate it with zero)
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ // mesh arrays - separate here to make the handling of the pointers below easier.
+ std::vector<MeshInfo> meshes;
+ std::vector<MeshInfo> meshesWithNormals;
+ std::vector<MeshInfo> meshesWithUVCoords;
+ std::vector<MeshInfo> meshesLocked;
+
+ char line[4096];
+ const char* sz;
+
+ // camera parameters
+ aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f);
+ float angle = 45.f;
+ aiVector2D resolution;
+
+ bool hasCam = false;
+
+ MeshInfo* currentMeshWithNormals = NULL;
+ MeshInfo* currentMesh = NULL;
+ MeshInfo* currentMeshWithUVCoords = NULL;
+
+ ShadingInfo s; // current material info
+
+ // degree of tesselation
+ unsigned int iTesselation = 4;
+
+ // some temporary variables we need to parse the file
+ unsigned int sphere = 0,
+ cylinder = 0,
+ cone = 0,
+ numNamed = 0,
+ dodecahedron = 0,
+ octahedron = 0,
+ tetrahedron = 0,
+ hexahedron = 0;
+
+ // lights imported from the file
+ std::vector<Light> lights;
+
+ // check whether this is the NFF2 file format
+ if (TokenMatch(buffer,"nff",3))
+ {
+ const float qnan = get_qnan();
+ const aiColor4D cQNAN = aiColor4D (qnan,0.f,0.f,1.f);
+ const aiVector3D vQNAN = aiVector3D(qnan,0.f,0.f);
+
+ // another NFF file format ... just a raw parser has been implemented
+ // no support for further details, I don't think it is worth the effort
+ // http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html
+ // http://www.netghost.narod.ru/gff/graphics/summary/sense8.htm
+
+ // First of all: remove all comments from the file
+ CommentRemover::RemoveLineComments("//",&mBuffer2[0]);
+
+ while (GetNextLine(buffer,line))
+ {
+ SkipSpaces(line,&sz);
+ if (TokenMatch(sz,"version",7))
+ {
+ DefaultLogger::get()->info("NFF (Sense8) file format: " + std::string(sz));
+ }
+ else if (TokenMatch(sz,"viewpos",7))
+ {
+ AI_NFF_PARSE_TRIPLE(camPos);
+ hasCam = true;
+ }
+ else if (TokenMatch(sz,"viewdir",7))
+ {
+ AI_NFF_PARSE_TRIPLE(camLookAt);
+ hasCam = true;
+ }
+ // This starts a new object section
+ else if (!IsSpaceOrNewLine(*sz))
+ {
+ unsigned int subMeshIdx = 0;
+
+ // read the name of the object, skip all spaces
+ // at the end of it.
+ const char* sz3 = sz;
+ while (!IsSpaceOrNewLine(*sz))++sz;
+ std::string objectName = std::string(sz3,(unsigned int)(sz-sz3));
+
+ const unsigned int objStart = (unsigned int)meshes.size();
+
+ // There could be a material table in a separate file
+ std::vector<ShadingInfo> materialTable;
+ while (true)
+ {
+ AI_NFF2_GET_NEXT_TOKEN();
+
+ // material table - an external file
+ if (TokenMatch(sz,"mtable",6))
+ {
+ SkipSpaces(&sz);
+ sz3 = sz;
+ while (!IsSpaceOrNewLine(*sz))++sz;
+ const unsigned int diff = (unsigned int)(sz-sz3);
+ if (!diff)DefaultLogger::get()->warn("NFF2: Found empty mtable token");
+ else
+ {
+ // The material table has the file extension .mat.
+ // If it is not there, we need to append it
+ std::string path = std::string(sz3,diff);
+ if(std::string::npos == path.find_last_of(".mat"))
+ {
+ path.append(".mat");
+ }
+
+ // Now extract the working directory from the path to
+ // this file and append the material library filename
+ // to it.
+ std::string::size_type s;
+ if ((std::string::npos == (s = path.find_last_of('\\')) || !s) &&
+ (std::string::npos == (s = path.find_last_of('/')) || !s) )
+ {
+ s = pFile.find_last_of('\\');
+ if (std::string::npos == s)s = pFile.find_last_of('/');
+ if (std::string::npos != s)
+ {
+ path = pFile.substr(0,s+1) + path;
+ }
+ }
+ LoadNFF2MaterialTable(materialTable,path,pIOHandler);
+ }
+ }
+ else break;
+ }
+
+ // read the numbr of vertices
+ unsigned int num = ::strtoul10(sz,&sz);
+
+ // temporary storage
+ std::vector<aiColor4D> tempColors;
+ std::vector<aiVector3D> tempPositions,tempTextureCoords,tempNormals;
+
+ bool hasNormals = false,hasUVs = false,hasColor = false;
+
+ tempPositions.reserve (num);
+ tempColors.reserve (num);
+ tempNormals.reserve (num);
+ tempTextureCoords.reserve (num);
+ for (unsigned int i = 0; i < num; ++i)
+ {
+ AI_NFF2_GET_NEXT_TOKEN();
+ aiVector3D v;
+ AI_NFF_PARSE_TRIPLE(v);
+ tempPositions.push_back(v);
+
+ // parse all other attributes in the line
+ while (true)
+ {
+ SkipSpaces(&sz);
+ if (IsLineEnd(*sz))break;
+
+ // color definition
+ if (TokenMatch(sz,"0x",2))
+ {
+ hasColor = true;
+ unsigned int numIdx = ::strtoul16(sz,&sz);
+ aiColor4D clr;
+ clr.a = 1.f;
+
+ // 0xRRGGBB
+ clr.r = ((numIdx >> 16u) & 0xff) / 255.f;
+ clr.g = ((numIdx >> 8u) & 0xff) / 255.f;
+ clr.b = ((numIdx) & 0xff) / 255.f;
+ tempColors.push_back(clr);
+ }
+ // normal vector
+ else if (TokenMatch(sz,"norm",4))
+ {
+ hasNormals = true;
+ AI_NFF_PARSE_TRIPLE(v);
+ tempNormals.push_back(v);
+ }
+ // UV coordinate
+ else if (TokenMatch(sz,"uv",2))
+ {
+ hasUVs = true;
+ AI_NFF_PARSE_FLOAT(v.x);
+ AI_NFF_PARSE_FLOAT(v.y);
+ v.z = 0.f;
+ tempTextureCoords.push_back(v);
+ }
+ }
+
+ // fill in dummies for all attributes that have not been set
+ if (tempNormals.size() != tempPositions.size())
+ tempNormals.push_back(vQNAN);
+
+ if (tempTextureCoords.size() != tempPositions.size())
+ tempTextureCoords.push_back(vQNAN);
+
+ if (tempColors.size() != tempPositions.size())
+ tempColors.push_back(cQNAN);
+ }
+
+ AI_NFF2_GET_NEXT_TOKEN();
+ if (!num)throw DeadlyImportError("NFF2: There are zero vertices");
+ num = ::strtoul10(sz,&sz);
+
+ std::vector<unsigned int> tempIdx;
+ tempIdx.reserve(10);
+ for (unsigned int i = 0; i < num; ++i)
+ {
+ AI_NFF2_GET_NEXT_TOKEN();
+ SkipSpaces(line,&sz);
+ unsigned int numIdx = ::strtoul10(sz,&sz);
+
+ // read all faces indices
+ if (numIdx)
+ {
+ // mesh.faces.push_back(numIdx);
+ // tempIdx.erase(tempIdx.begin(),tempIdx.end());
+ tempIdx.resize(numIdx);
+
+ for (unsigned int a = 0; a < numIdx;++a)
+ {
+ SkipSpaces(sz,&sz);
+ m = ::strtoul10(sz,&sz);
+ if (m >= (unsigned int)tempPositions.size())
+ {
+ DefaultLogger::get()->error("NFF2: Vertex index overflow");
+ m= 0;
+ }
+ // mesh.vertices.push_back (tempPositions[idx]);
+ tempIdx[a] = m;
+ }
+ }
+
+ // build a temporary shader object for the face.
+ ShadingInfo shader;
+ unsigned int matIdx = 0;
+
+ // white material color - we have vertex colors
+ shader.color = aiColor3D(1.f,1.f,1.f);
+ aiColor4D c = aiColor4D(1.f,1.f,1.f,1.f);
+ while (true)
+ {
+ SkipSpaces(sz,&sz);
+ if(IsLineEnd(*sz))break;
+
+ // per-polygon colors
+ if (TokenMatch(sz,"0x",2))
+ {
+ hasColor = true;
+ const char* sz2 = sz;
+ numIdx = ::strtoul16(sz,&sz);
+ const unsigned int diff = (unsigned int)(sz-sz2);
+
+ // 0xRRGGBB
+ if (diff > 3)
+ {
+ c.r = ((numIdx >> 16u) & 0xff) / 255.f;
+ c.g = ((numIdx >> 8u) & 0xff) / 255.f;
+ c.b = ((numIdx) & 0xff) / 255.f;
+ }
+ // 0xRGB
+ else
+ {
+ c.r = ((numIdx >> 8u) & 0xf) / 16.f;
+ c.g = ((numIdx >> 4u) & 0xf) / 16.f;
+ c.b = ((numIdx) & 0xf) / 16.f;
+ }
+ }
+ // TODO - implement texture mapping here
#if 0
- // mirror vertex texture coordinate?
- else if (TokenMatch(sz,"mirror",6))
- {
- }
- // texture coordinate scaling
- else if (TokenMatch(sz,"scale",5))
- {
- }
- // texture coordinate translation
- else if (TokenMatch(sz,"trans",5))
- {
- }
- // texture coordinate rotation angle
- else if (TokenMatch(sz,"rot",3))
- {
- }
+ // mirror vertex texture coordinate?
+ else if (TokenMatch(sz,"mirror",6))
+ {
+ }
+ // texture coordinate scaling
+ else if (TokenMatch(sz,"scale",5))
+ {
+ }
+ // texture coordinate translation
+ else if (TokenMatch(sz,"trans",5))
+ {
+ }
+ // texture coordinate rotation angle
+ else if (TokenMatch(sz,"rot",3))
+ {
+ }
#endif
- // texture file name for this polygon + mapping information
- else if ('_' == sz[0])
- {
- // get mapping information
- switch (sz[1])
- {
- case 'v':
- case 'V':
-
- shader.shaded = false;
- break;
-
- case 't':
- case 'T':
- case 'u':
- case 'U':
-
- DefaultLogger::get()->warn("Unsupported NFF2 texture attribute: trans");
- };
- if (!sz[1] || '_' != sz[2])
- {
- DefaultLogger::get()->warn("NFF2: Expected underscore after texture attributes");
- continue;
- }
- const char* sz2 = sz+3;
- while (!IsSpaceOrNewLine( *sz ))++sz;
- const unsigned int diff = (unsigned int)(sz-sz2);
- if (diff)shader.texFile = std::string(sz2,diff);
- }
-
- // Two-sided material?
- else if (TokenMatch(sz,"both",4))
- {
- shader.twoSided = true;
- }
-
- // Material ID?
- else if (!materialTable.empty() && TokenMatch(sz,"matid",5))
- {
- SkipSpaces(&sz);
- matIdx = ::strtoul10(sz,&sz);
- if (matIdx >= materialTable.size())
- {
- DefaultLogger::get()->error("NFF2: Material index overflow.");
- matIdx = 0;
- }
-
- // now combine our current shader with the shader we
- // read from the material table.
- ShadingInfo& mat = materialTable[matIdx];
- shader.ambient = mat.ambient;
- shader.diffuse = mat.diffuse;
- shader.emissive = mat.emissive;
- shader.opacity = mat.opacity;
- shader.specular = mat.specular;
- shader.shininess = mat.shininess;
- }
- else SkipToken(sz);
- }
-
- // search the list of all shaders we have for this object whether
- // there is an identical one. In this case, we append our mesh
- // data to it.
- MeshInfo* mesh = NULL;
- for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
- it != end; ++it)
- {
- if ((*it).shader == shader && (*it).matIndex == matIdx)
- {
- // we have one, we can append our data to it
- mesh = &(*it);
- }
- }
- if (!mesh)
- {
- meshes.push_back(MeshInfo(PatchType_Simple,false));
- mesh = &meshes.back();
- mesh->matIndex = matIdx;
-
- // We need to add a new mesh to the list. We assign
- // an unique name to it to make sure the scene will
- // pass the validation step for the moment.
- // TODO: fix naming of objects in the scenegraph later
- if (objectName.length())
- {
- ::strcpy(mesh->name,objectName.c_str());
- ASSIMP_itoa10(&mesh->name[objectName.length()],30,subMeshIdx++);
- }
-
- // copy the shader to the mesh.
- mesh->shader = shader;
- }
-
- // fill the mesh with data
- if (!tempIdx.empty())
- {
- mesh->faces.push_back((unsigned int)tempIdx.size());
- for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end();
- it != end;++it)
- {
- m = *it;
-
- // copy colors -vertex color specifications override polygon color specifications
- if (hasColor)
- {
- const aiColor4D& clr = tempColors[m];
- mesh->colors.push_back((is_qnan( clr.r ) ? c : clr));
- }
-
- // positions should always be there
- mesh->vertices.push_back (tempPositions[m]);
-
- // copy normal vectors
- if (hasNormals)
- mesh->normals.push_back (tempNormals[m]);
-
- // copy texture coordinates
- if (hasUVs)
- mesh->uvs.push_back (tempTextureCoords[m]);
- }
- }
- }
- if (!num)throw DeadlyImportError("NFF2: There are zero faces");
- }
- }
- camLookAt = camLookAt + camPos;
- }
- else // "Normal" Neutral file format that is quite more common
- {
- while (GetNextLine(buffer,line))
- {
- sz = line;
- if ('p' == line[0] || TokenMatch(sz,"tpp",3))
- {
- MeshInfo* out = NULL;
-
- // 'tpp' - texture polygon patch primitive
- if ('t' == line[0])
- {
- currentMeshWithUVCoords = NULL;
- for (std::vector<MeshInfo>::iterator it = meshesWithUVCoords.begin(), end = meshesWithUVCoords.end();
- it != end;++it)
- {
- if ((*it).shader == s)
- {
- currentMeshWithUVCoords = &(*it);
- break;
- }
- }
-
- if (!currentMeshWithUVCoords)
- {
- meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
- currentMeshWithUVCoords = &meshesWithUVCoords.back();
- currentMeshWithUVCoords->shader = s;
- }
- out = currentMeshWithUVCoords;
- }
- // 'pp' - polygon patch primitive
- else if ('p' == line[1])
- {
- currentMeshWithNormals = NULL;
- for (std::vector<MeshInfo>::iterator it = meshesWithNormals.begin(), end = meshesWithNormals.end();
- it != end;++it)
- {
- if ((*it).shader == s)
- {
- currentMeshWithNormals = &(*it);
- break;
- }
- }
-
- if (!currentMeshWithNormals)
- {
- meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
- currentMeshWithNormals = &meshesWithNormals.back();
- currentMeshWithNormals->shader = s;
- }
- sz = &line[2];out = currentMeshWithNormals;
- }
- // 'p' - polygon primitive
- else
- {
- currentMesh = NULL;
- for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
- it != end;++it)
- {
- if ((*it).shader == s)
- {
- currentMesh = &(*it);
- break;
- }
- }
-
- if (!currentMesh)
- {
- meshes.push_back(MeshInfo(PatchType_Simple));
- currentMesh = &meshes.back();
- currentMesh->shader = s;
- }
- sz = &line[1];out = currentMesh;
- }
- SkipSpaces(sz,&sz);
- m = strtoul10(sz);
-
- // ---- flip the face order
- out->vertices.resize(out->vertices.size()+m);
- if (out != currentMesh)
- {
- out->normals.resize(out->vertices.size());
- }
- if (out == currentMeshWithUVCoords)
- {
- out->uvs.resize(out->vertices.size());
- }
- for (unsigned int n = 0; n < m;++n)
- {
- if(!GetNextLine(buffer,line))
- {
- DefaultLogger::get()->error("NFF: Unexpected EOF was encountered. Patch definition incomplete");
- continue;
- }
-
- aiVector3D v; sz = &line[0];
- AI_NFF_PARSE_TRIPLE(v);
- out->vertices[out->vertices.size()-n-1] = v;
-
- if (out != currentMesh)
- {
- AI_NFF_PARSE_TRIPLE(v);
- out->normals[out->vertices.size()-n-1] = v;
- }
- if (out == currentMeshWithUVCoords)
- {
- // FIX: in one test file this wraps over multiple lines
- SkipSpaces(&sz);
- if (IsLineEnd(*sz))
- {
- GetNextLine(buffer,line);
- sz = line;
- }
- AI_NFF_PARSE_FLOAT(v.x);
- SkipSpaces(&sz);
- if (IsLineEnd(*sz))
- {
- GetNextLine(buffer,line);
- sz = line;
- }
- AI_NFF_PARSE_FLOAT(v.y);
- v.y = 1.f - v.y;
- out->uvs[out->vertices.size()-n-1] = v;
- }
- }
- out->faces.push_back(m);
- }
- // 'f' - shading information block
- else if (TokenMatch(sz,"f",1))
- {
- float d;
-
- // read the RGB colors
- AI_NFF_PARSE_TRIPLE(s.color);
-
- // read the other properties
- AI_NFF_PARSE_FLOAT(s.diffuse.r);
- AI_NFF_PARSE_FLOAT(s.specular.r);
- AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance
- AI_NFF_PARSE_FLOAT(d);
- AI_NFF_PARSE_FLOAT(s.refracti);
-
- // NFF2 uses full colors here so we need to use them too
- // although NFF uses simple scaling factors
- s.diffuse.g = s.diffuse.b = s.diffuse.r;
- s.specular.g = s.specular.b = s.specular.r;
-
- // if the next one is NOT a number we assume it is a texture file name
- // this feature is used by some NFF files on the internet and it has
- // been implemented as it can be really useful
- SkipSpaces(&sz);
- if (!IsNumeric(*sz))
- {
- // TODO: Support full file names with spaces and quotation marks ...
- const char* p = sz;
- while (!IsSpaceOrNewLine( *sz ))++sz;
-
- unsigned int diff = (unsigned int)(sz-p);
- if (diff)
- {
- s.texFile = std::string(p,diff);
- }
- }
- else
- {
- AI_NFF_PARSE_FLOAT(s.ambient); // optional
- }
- }
- // 'shader' - other way to specify a texture
- else if (TokenMatch(sz,"shader",6))
- {
- SkipSpaces(&sz);
- const char* old = sz;
- while (!IsSpaceOrNewLine(*sz))++sz;
- s.texFile = std::string(old, (uintptr_t)sz - (uintptr_t)old);
- }
- // 'l' - light source
- else if (TokenMatch(sz,"l",1))
- {
- lights.push_back(Light());
- Light& light = lights.back();
-
- AI_NFF_PARSE_TRIPLE(light.position);
- AI_NFF_PARSE_FLOAT (light.intensity);
- AI_NFF_PARSE_TRIPLE(light.color);
- }
- // 's' - sphere
- else if (TokenMatch(sz,"s",1))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_SPHERE;
-
- AI_NFF_PARSE_SHAPE_INFORMATION();
-
- // we don't need scaling or translation here - we do it in the node's transform
- StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh
- ::sprintf(currentMesh.name,"sphere_%i",sphere++);
- }
- // 'dod' - dodecahedron
- else if (TokenMatch(sz,"dod",3))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_SPHERE;
-
- AI_NFF_PARSE_SHAPE_INFORMATION();
-
- // we don't need scaling or translation here - we do it in the node's transform
- StandardShapes::MakeDodecahedron(currentMesh.vertices);
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh
- ::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++);
- }
-
- // 'oct' - octahedron
- else if (TokenMatch(sz,"oct",3))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_SPHERE;
-
- AI_NFF_PARSE_SHAPE_INFORMATION();
-
- // we don't need scaling or translation here - we do it in the node's transform
- StandardShapes::MakeOctahedron(currentMesh.vertices);
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh
- ::sprintf(currentMesh.name,"octahedron_%i",octahedron++);
- }
-
- // 'tet' - tetrahedron
- else if (TokenMatch(sz,"tet",3))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_SPHERE;
-
- AI_NFF_PARSE_SHAPE_INFORMATION();
-
- // we don't need scaling or translation here - we do it in the node's transform
- StandardShapes::MakeTetrahedron(currentMesh.vertices);
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh
- ::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++);
- }
-
- // 'hex' - hexahedron
- else if (TokenMatch(sz,"hex",3))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_BOX;
-
- AI_NFF_PARSE_SHAPE_INFORMATION();
-
- // we don't need scaling or translation here - we do it in the node's transform
- StandardShapes::MakeHexahedron(currentMesh.vertices);
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh
- ::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++);
- }
- // 'c' - cone
- else if (TokenMatch(sz,"c",1))
- {
- meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
- MeshInfo& currentMesh = meshesLocked.back();
- currentMesh.shader = s;
- currentMesh.shader.mapping = aiTextureMapping_CYLINDER;
-
- if(!GetNextLine(buffer,line))
- {
- DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
- break;
- }
- sz = line;
-
- // read the two center points and the respective radii
- aiVector3D center1, center2; float radius1, radius2;
- AI_NFF_PARSE_TRIPLE(center1);
- AI_NFF_PARSE_FLOAT(radius1);
-
- if(!GetNextLine(buffer,line))
- {
- DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
- break;
- }
- sz = line;
-
- AI_NFF_PARSE_TRIPLE(center2);
- AI_NFF_PARSE_FLOAT(radius2);
-
- // compute the center point of the cone/cylinder -
- // it is its local transformation origin
- currentMesh.dir = center2-center1;
- currentMesh.center = center1+currentMesh.dir/2.f;
-
- float f;
- if (( f = currentMesh.dir.Length()) < 10e-3f )
- {
- DefaultLogger::get()->error("NFF: Cone height is close to zero");
- continue;
- }
- currentMesh.dir /= f; // normalize
-
- // generate the cone - it consists of simple triangles
- StandardShapes::MakeCone(f, radius1, radius2,
- integer_pow(4, iTesselation), currentMesh.vertices);
-
- // MakeCone() returns tris
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
-
- // generate a name for the mesh. 'cone' if it a cone,
- // 'cylinder' if it is a cylinder. Funny, isn't it?
- if (radius1 != radius2)
- ::sprintf(currentMesh.name,"cone_%i",cone++);
- else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
- }
- // 'tess' - tesselation
- else if (TokenMatch(sz,"tess",4))
- {
- SkipSpaces(&sz);
- iTesselation = strtoul10(sz);
- }
- // 'from' - camera position
- else if (TokenMatch(sz,"from",4))
- {
- AI_NFF_PARSE_TRIPLE(camPos);
- hasCam = true;
- }
- // 'at' - camera look-at vector
- else if (TokenMatch(sz,"at",2))
- {
- AI_NFF_PARSE_TRIPLE(camLookAt);
- hasCam = true;
- }
- // 'up' - camera up vector
- else if (TokenMatch(sz,"up",2))
- {
- AI_NFF_PARSE_TRIPLE(camUp);
- hasCam = true;
- }
- // 'angle' - (half?) camera field of view
- else if (TokenMatch(sz,"angle",5))
- {
- AI_NFF_PARSE_FLOAT(angle);
- hasCam = true;
- }
- // 'resolution' - used to compute the screen aspect
- else if (TokenMatch(sz,"resolution",10))
- {
- AI_NFF_PARSE_FLOAT(resolution.x);
- AI_NFF_PARSE_FLOAT(resolution.y);
- hasCam = true;
- }
- // 'pb' - bezier patch. Not supported yet
- else if (TokenMatch(sz,"pb",2))
- {
- DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch");
- }
- // 'pn' - NURBS. Not supported yet
- else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3))
- {
- DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS");
- }
- // '' - comment
- else if ('#' == line[0])
- {
- const char* sz;SkipSpaces(&line[1],&sz);
- if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
- }
- }
- }
-
- // copy all arrays into one large
- meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size());
- meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end());
- meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
- meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end());
-
- // now generate output meshes. first find out how many meshes we'll need
- std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
- for (;it != end;++it)
- {
- if (!(*it).faces.empty())
- {
- ++pScene->mNumMeshes;
- if ((*it).name[0])++numNamed;
- }
- }
-
- // generate a dummy root node - assign all unnamed elements such
- // as polygons and polygon patches to the root node and generate
- // sub nodes for named objects such as spheres and cones.
- aiNode* const root = new aiNode();
- root->mName.Set("<NFF_Root>");
- root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size();
- root->mNumMeshes = pScene->mNumMeshes-numNamed;
-
- aiNode** ppcChildren = NULL;
- unsigned int* pMeshes = NULL;
- if (root->mNumMeshes)
- pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes];
- if (root->mNumChildren)
- ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
-
- // generate the camera
- if (hasCam)
- {
- aiNode* nd = *ppcChildren = new aiNode();
- nd->mName.Set("<NFF_Camera>");
- nd->mParent = root;
-
- // allocate the camera in the scene
- pScene->mNumCameras = 1;
- pScene->mCameras = new aiCamera*[1];
- aiCamera* c = pScene->mCameras[0] = new aiCamera;
-
- c->mName = nd->mName; // make sure the names are identical
- c->mHorizontalFOV = AI_DEG_TO_RAD( angle );
- c->mLookAt = camLookAt - camPos;
- c->mPosition = camPos;
- c->mUp = camUp;
-
- // If the resolution is not specified in the file, we
- // need to set 1.0 as aspect.
- c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y);
- ++ppcChildren;
- }
-
- // generate light sources
- if (!lights.empty())
- {
- pScene->mNumLights = (unsigned int)lights.size();
- pScene->mLights = new aiLight*[pScene->mNumLights];
- for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren)
- {
- const Light& l = lights[i];
-
- aiNode* nd = *ppcChildren = new aiNode();
- nd->mParent = root;
-
- nd->mName.length = ::sprintf(nd->mName.data,"<NFF_Light%i>",i);
-
- // allocate the light in the scene data structure
- aiLight* out = pScene->mLights[i] = new aiLight();
- out->mName = nd->mName; // make sure the names are identical
- out->mType = aiLightSource_POINT;
- out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity;
- out->mPosition = l.position;
- }
- }
-
- if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded");
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
- for (it = meshes.begin(), m = 0; it != end;++it)
- {
- if ((*it).faces.empty())continue;
-
- const MeshInfo& src = *it;
- aiMesh* const mesh = pScene->mMeshes[m] = new aiMesh();
- mesh->mNumVertices = (unsigned int)src.vertices.size();
- mesh->mNumFaces = (unsigned int)src.faces.size();
-
- // Generate sub nodes for named meshes
- if (src.name[0])
- {
- aiNode* const node = *ppcChildren = new aiNode();
- node->mParent = root;
- node->mNumMeshes = 1;
- node->mMeshes = new unsigned int[1];
- node->mMeshes[0] = m;
- node->mName.Set(src.name);
-
- // setup the transformation matrix of the node
- aiMatrix4x4::FromToMatrix(aiVector3D(0.f,1.f,0.f),
- src.dir,node->mTransformation);
-
- aiMatrix4x4& mat = node->mTransformation;
- mat.a1 *= src.radius.x; mat.b1 *= src.radius.x; mat.c1 *= src.radius.x;
- mat.a2 *= src.radius.y; mat.b2 *= src.radius.y; mat.c2 *= src.radius.y;
- mat.a3 *= src.radius.z; mat.b3 *= src.radius.z; mat.c3 *= src.radius.z;
- mat.a4 = src.center.x;
- mat.b4 = src.center.y;
- mat.c4 = src.center.z;
-
- ++ppcChildren;
- }
- else *pMeshes++ = m;
-
- // copy vertex positions
- mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- ::memcpy(mesh->mVertices,&src.vertices[0],
- sizeof(aiVector3D)*mesh->mNumVertices);
-
- // NFF2: there could be vertex colors
- if (!src.colors.empty())
- {
- ai_assert(src.colors.size() == src.vertices.size());
-
- // copy vertex colors
- mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
- ::memcpy(mesh->mColors[0],&src.colors[0],
- sizeof(aiColor4D)*mesh->mNumVertices);
- }
-
- if (!src.normals.empty())
- {
- ai_assert(src.normals.size() == src.vertices.size());
-
- // copy normal vectors
- mesh->mNormals = new aiVector3D[mesh->mNumVertices];
- ::memcpy(mesh->mNormals,&src.normals[0],
- sizeof(aiVector3D)*mesh->mNumVertices);
- }
-
- if (!src.uvs.empty())
- {
- ai_assert(src.uvs.size() == src.vertices.size());
-
- // copy texture coordinates
- mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
- ::memcpy(mesh->mTextureCoords[0],&src.uvs[0],
- sizeof(aiVector3D)*mesh->mNumVertices);
- }
-
- // generate faces
- unsigned int p = 0;
- aiFace* pFace = mesh->mFaces = new aiFace[mesh->mNumFaces];
- for (std::vector<unsigned int>::const_iterator it2 = src.faces.begin(),
- end2 = src.faces.end();
- it2 != end2;++it2,++pFace)
- {
- pFace->mIndices = new unsigned int [ pFace->mNumIndices = *it2 ];
- for (unsigned int o = 0; o < pFace->mNumIndices;++o)
- pFace->mIndices[o] = p++;
- }
-
- // generate a material for the mesh
- aiMaterial* pcMat = (aiMaterial*)(pScene->mMaterials[m] = new aiMaterial());
-
- mesh->mMaterialIndex = m++;
-
- aiString s;
- s.Set(AI_DEFAULT_MATERIAL_NAME);
- pcMat->AddProperty(&s, AI_MATKEY_NAME);
-
- // FIX: Ignore diffuse == 0
- aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f,1.f,1.f));
- pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
- c = src.shader.color * src.shader.specular;
- pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
-
- // NFF2 - default values for NFF
- pcMat->AddProperty(&src.shader.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
- pcMat->AddProperty(&src.shader.emissive,1,AI_MATKEY_COLOR_EMISSIVE);
- pcMat->AddProperty(&src.shader.opacity, 1,AI_MATKEY_OPACITY);
-
- // setup the first texture layer, if existing
- if (src.shader.texFile.length())
- {
- s.Set(src.shader.texFile);
- pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
- if (aiTextureMapping_UV != src.shader.mapping) {
-
- aiVector3D v(0.f,-1.f,0.f);
- pcMat->AddProperty(&v, 1,AI_MATKEY_TEXMAP_AXIS_DIFFUSE(0));
- pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0));
- }
- }
-
- // setup the name of the material
- if (src.shader.name.length())
- {
- s.Set(src.shader.texFile);
- pcMat->AddProperty(&s,AI_MATKEY_NAME);
- }
-
- // setup some more material properties that are specific to NFF2
- int i;
- if (src.shader.twoSided)
- {
- i = 1;
- pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
- }
- i = (src.shader.shaded ? aiShadingMode_Gouraud : aiShadingMode_NoShading);
- if (src.shader.shininess)
- {
- i = aiShadingMode_Phong;
- pcMat->AddProperty(&src.shader.shininess,1,AI_MATKEY_SHININESS);
- }
- pcMat->AddProperty(&i,1,AI_MATKEY_SHADING_MODEL);
- }
- pScene->mRootNode = root;
+ // texture file name for this polygon + mapping information
+ else if ('_' == sz[0])
+ {
+ // get mapping information
+ switch (sz[1])
+ {
+ case 'v':
+ case 'V':
+
+ shader.shaded = false;
+ break;
+
+ case 't':
+ case 'T':
+ case 'u':
+ case 'U':
+
+ DefaultLogger::get()->warn("Unsupported NFF2 texture attribute: trans");
+ };
+ if (!sz[1] || '_' != sz[2])
+ {
+ DefaultLogger::get()->warn("NFF2: Expected underscore after texture attributes");
+ continue;
+ }
+ const char* sz2 = sz+3;
+ while (!IsSpaceOrNewLine( *sz ))++sz;
+ const unsigned int diff = (unsigned int)(sz-sz2);
+ if (diff)shader.texFile = std::string(sz2,diff);
+ }
+
+ // Two-sided material?
+ else if (TokenMatch(sz,"both",4))
+ {
+ shader.twoSided = true;
+ }
+
+ // Material ID?
+ else if (!materialTable.empty() && TokenMatch(sz,"matid",5))
+ {
+ SkipSpaces(&sz);
+ matIdx = ::strtoul10(sz,&sz);
+ if (matIdx >= materialTable.size())
+ {
+ DefaultLogger::get()->error("NFF2: Material index overflow.");
+ matIdx = 0;
+ }
+
+ // now combine our current shader with the shader we
+ // read from the material table.
+ ShadingInfo& mat = materialTable[matIdx];
+ shader.ambient = mat.ambient;
+ shader.diffuse = mat.diffuse;
+ shader.emissive = mat.emissive;
+ shader.opacity = mat.opacity;
+ shader.specular = mat.specular;
+ shader.shininess = mat.shininess;
+ }
+ else SkipToken(sz);
+ }
+
+ // search the list of all shaders we have for this object whether
+ // there is an identical one. In this case, we append our mesh
+ // data to it.
+ MeshInfo* mesh = NULL;
+ for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
+ it != end; ++it)
+ {
+ if ((*it).shader == shader && (*it).matIndex == matIdx)
+ {
+ // we have one, we can append our data to it
+ mesh = &(*it);
+ }
+ }
+ if (!mesh)
+ {
+ meshes.push_back(MeshInfo(PatchType_Simple,false));
+ mesh = &meshes.back();
+ mesh->matIndex = matIdx;
+
+ // We need to add a new mesh to the list. We assign
+ // an unique name to it to make sure the scene will
+ // pass the validation step for the moment.
+ // TODO: fix naming of objects in the scenegraph later
+ if (objectName.length())
+ {
+ ::strcpy(mesh->name,objectName.c_str());
+ ASSIMP_itoa10(&mesh->name[objectName.length()],30,subMeshIdx++);
+ }
+
+ // copy the shader to the mesh.
+ mesh->shader = shader;
+ }
+
+ // fill the mesh with data
+ if (!tempIdx.empty())
+ {
+ mesh->faces.push_back((unsigned int)tempIdx.size());
+ for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end();
+ it != end;++it)
+ {
+ m = *it;
+
+ // copy colors -vertex color specifications override polygon color specifications
+ if (hasColor)
+ {
+ const aiColor4D& clr = tempColors[m];
+ mesh->colors.push_back((is_qnan( clr.r ) ? c : clr));
+ }
+
+ // positions should always be there
+ mesh->vertices.push_back (tempPositions[m]);
+
+ // copy normal vectors
+ if (hasNormals)
+ mesh->normals.push_back (tempNormals[m]);
+
+ // copy texture coordinates
+ if (hasUVs)
+ mesh->uvs.push_back (tempTextureCoords[m]);
+ }
+ }
+ }
+ if (!num)throw DeadlyImportError("NFF2: There are zero faces");
+ }
+ }
+ camLookAt = camLookAt + camPos;
+ }
+ else // "Normal" Neutral file format that is quite more common
+ {
+ while (GetNextLine(buffer,line))
+ {
+ sz = line;
+ if ('p' == line[0] || TokenMatch(sz,"tpp",3))
+ {
+ MeshInfo* out = NULL;
+
+ // 'tpp' - texture polygon patch primitive
+ if ('t' == line[0])
+ {
+ currentMeshWithUVCoords = NULL;
+ for (auto &mesh : meshesWithUVCoords)
+ {
+ if (mesh.shader == s)
+ {
+ currentMeshWithUVCoords = &mesh;
+ break;
+ }
+ }
+
+ if (!currentMeshWithUVCoords)
+ {
+ meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
+ currentMeshWithUVCoords = &meshesWithUVCoords.back();
+ currentMeshWithUVCoords->shader = s;
+ }
+ out = currentMeshWithUVCoords;
+ }
+ // 'pp' - polygon patch primitive
+ else if ('p' == line[1])
+ {
+ currentMeshWithNormals = NULL;
+ for (auto &mesh : meshesWithNormals)
+ {
+ if (mesh.shader == s)
+ {
+ currentMeshWithNormals = &mesh;
+ break;
+ }
+ }
+
+ if (!currentMeshWithNormals)
+ {
+ meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
+ currentMeshWithNormals = &meshesWithNormals.back();
+ currentMeshWithNormals->shader = s;
+ }
+ sz = &line[2];out = currentMeshWithNormals;
+ }
+ // 'p' - polygon primitive
+ else
+ {
+ currentMesh = NULL;
+ for (auto &mesh : meshes)
+ {
+ if (mesh.shader == s)
+ {
+ currentMesh = &mesh;
+ break;
+ }
+ }
+
+ if (!currentMesh)
+ {
+ meshes.push_back(MeshInfo(PatchType_Simple));
+ currentMesh = &meshes.back();
+ currentMesh->shader = s;
+ }
+ sz = &line[1];out = currentMesh;
+ }
+ SkipSpaces(sz,&sz);
+ m = strtoul10(sz);
+
+ // ---- flip the face order
+ out->vertices.resize(out->vertices.size()+m);
+ if (out != currentMesh)
+ {
+ out->normals.resize(out->vertices.size());
+ }
+ if (out == currentMeshWithUVCoords)
+ {
+ out->uvs.resize(out->vertices.size());
+ }
+ for (unsigned int n = 0; n < m;++n)
+ {
+ if(!GetNextLine(buffer,line))
+ {
+ DefaultLogger::get()->error("NFF: Unexpected EOF was encountered. Patch definition incomplete");
+ continue;
+ }
+
+ aiVector3D v; sz = &line[0];
+ AI_NFF_PARSE_TRIPLE(v);
+ out->vertices[out->vertices.size()-n-1] = v;
+
+ if (out != currentMesh)
+ {
+ AI_NFF_PARSE_TRIPLE(v);
+ out->normals[out->vertices.size()-n-1] = v;
+ }
+ if (out == currentMeshWithUVCoords)
+ {
+ // FIX: in one test file this wraps over multiple lines
+ SkipSpaces(&sz);
+ if (IsLineEnd(*sz))
+ {
+ GetNextLine(buffer,line);
+ sz = line;
+ }
+ AI_NFF_PARSE_FLOAT(v.x);
+ SkipSpaces(&sz);
+ if (IsLineEnd(*sz))
+ {
+ GetNextLine(buffer,line);
+ sz = line;
+ }
+ AI_NFF_PARSE_FLOAT(v.y);
+ v.y = 1.f - v.y;
+ out->uvs[out->vertices.size()-n-1] = v;
+ }
+ }
+ out->faces.push_back(m);
+ }
+ // 'f' - shading information block
+ else if (TokenMatch(sz,"f",1))
+ {
+ float d;
+
+ // read the RGB colors
+ AI_NFF_PARSE_TRIPLE(s.color);
+
+ // read the other properties
+ AI_NFF_PARSE_FLOAT(s.diffuse.r);
+ AI_NFF_PARSE_FLOAT(s.specular.r);
+ AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance
+ AI_NFF_PARSE_FLOAT(d);
+ AI_NFF_PARSE_FLOAT(s.refracti);
+
+ // NFF2 uses full colors here so we need to use them too
+ // although NFF uses simple scaling factors
+ s.diffuse.g = s.diffuse.b = s.diffuse.r;
+ s.specular.g = s.specular.b = s.specular.r;
+
+ // if the next one is NOT a number we assume it is a texture file name
+ // this feature is used by some NFF files on the internet and it has
+ // been implemented as it can be really useful
+ SkipSpaces(&sz);
+ if (!IsNumeric(*sz))
+ {
+ // TODO: Support full file names with spaces and quotation marks ...
+ const char* p = sz;
+ while (!IsSpaceOrNewLine( *sz ))++sz;
+
+ unsigned int diff = (unsigned int)(sz-p);
+ if (diff)
+ {
+ s.texFile = std::string(p,diff);
+ }
+ }
+ else
+ {
+ AI_NFF_PARSE_FLOAT(s.ambient); // optional
+ }
+ }
+ // 'shader' - other way to specify a texture
+ else if (TokenMatch(sz,"shader",6))
+ {
+ SkipSpaces(&sz);
+ const char* old = sz;
+ while (!IsSpaceOrNewLine(*sz))++sz;
+ s.texFile = std::string(old, (uintptr_t)sz - (uintptr_t)old);
+ }
+ // 'l' - light source
+ else if (TokenMatch(sz,"l",1))
+ {
+ lights.push_back(Light());
+ Light& light = lights.back();
+
+ AI_NFF_PARSE_TRIPLE(light.position);
+ AI_NFF_PARSE_FLOAT (light.intensity);
+ AI_NFF_PARSE_TRIPLE(light.color);
+ }
+ // 's' - sphere
+ else if (TokenMatch(sz,"s",1))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_SPHERE;
+
+ AI_NFF_PARSE_SHAPE_INFORMATION();
+
+ // we don't need scaling or translation here - we do it in the node's transform
+ StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh
+ ::ai_snprintf(currentMesh.name,128,"sphere_%i",sphere++);
+ }
+ // 'dod' - dodecahedron
+ else if (TokenMatch(sz,"dod",3))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_SPHERE;
+
+ AI_NFF_PARSE_SHAPE_INFORMATION();
+
+ // we don't need scaling or translation here - we do it in the node's transform
+ StandardShapes::MakeDodecahedron(currentMesh.vertices);
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh
+ ::ai_snprintf(currentMesh.name,128,"dodecahedron_%i",dodecahedron++);
+ }
+
+ // 'oct' - octahedron
+ else if (TokenMatch(sz,"oct",3))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_SPHERE;
+
+ AI_NFF_PARSE_SHAPE_INFORMATION();
+
+ // we don't need scaling or translation here - we do it in the node's transform
+ StandardShapes::MakeOctahedron(currentMesh.vertices);
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh
+ ::ai_snprintf(currentMesh.name,128,"octahedron_%i",octahedron++);
+ }
+
+ // 'tet' - tetrahedron
+ else if (TokenMatch(sz,"tet",3))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_SPHERE;
+
+ AI_NFF_PARSE_SHAPE_INFORMATION();
+
+ // we don't need scaling or translation here - we do it in the node's transform
+ StandardShapes::MakeTetrahedron(currentMesh.vertices);
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh
+ ::ai_snprintf(currentMesh.name,128,"tetrahedron_%i",tetrahedron++);
+ }
+
+ // 'hex' - hexahedron
+ else if (TokenMatch(sz,"hex",3))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_BOX;
+
+ AI_NFF_PARSE_SHAPE_INFORMATION();
+
+ // we don't need scaling or translation here - we do it in the node's transform
+ StandardShapes::MakeHexahedron(currentMesh.vertices);
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh
+ ::ai_snprintf(currentMesh.name,128,"hexahedron_%i",hexahedron++);
+ }
+ // 'c' - cone
+ else if (TokenMatch(sz,"c",1))
+ {
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
+ MeshInfo& currentMesh = meshesLocked.back();
+ currentMesh.shader = s;
+ currentMesh.shader.mapping = aiTextureMapping_CYLINDER;
+
+ if(!GetNextLine(buffer,line))
+ {
+ DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
+ break;
+ }
+ sz = line;
+
+ // read the two center points and the respective radii
+ aiVector3D center1, center2; float radius1, radius2;
+ AI_NFF_PARSE_TRIPLE(center1);
+ AI_NFF_PARSE_FLOAT(radius1);
+
+ if(!GetNextLine(buffer,line))
+ {
+ DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
+ break;
+ }
+ sz = line;
+
+ AI_NFF_PARSE_TRIPLE(center2);
+ AI_NFF_PARSE_FLOAT(radius2);
+
+ // compute the center point of the cone/cylinder -
+ // it is its local transformation origin
+ currentMesh.dir = center2-center1;
+ currentMesh.center = center1+currentMesh.dir/2.f;
+
+ float f;
+ if (( f = currentMesh.dir.Length()) < 10e-3f )
+ {
+ DefaultLogger::get()->error("NFF: Cone height is close to zero");
+ continue;
+ }
+ currentMesh.dir /= f; // normalize
+
+ // generate the cone - it consists of simple triangles
+ StandardShapes::MakeCone(f, radius1, radius2,
+ integer_pow(4, iTesselation), currentMesh.vertices);
+
+ // MakeCone() returns tris
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
+
+ // generate a name for the mesh. 'cone' if it a cone,
+ // 'cylinder' if it is a cylinder. Funny, isn't it?
+ if (radius1 != radius2)
+ ::ai_snprintf(currentMesh.name,128,"cone_%i",cone++);
+ else ::ai_snprintf(currentMesh.name,128,"cylinder_%i",cylinder++);
+ }
+ // 'tess' - tesselation
+ else if (TokenMatch(sz,"tess",4))
+ {
+ SkipSpaces(&sz);
+ iTesselation = strtoul10(sz);
+ }
+ // 'from' - camera position
+ else if (TokenMatch(sz,"from",4))
+ {
+ AI_NFF_PARSE_TRIPLE(camPos);
+ hasCam = true;
+ }
+ // 'at' - camera look-at vector
+ else if (TokenMatch(sz,"at",2))
+ {
+ AI_NFF_PARSE_TRIPLE(camLookAt);
+ hasCam = true;
+ }
+ // 'up' - camera up vector
+ else if (TokenMatch(sz,"up",2))
+ {
+ AI_NFF_PARSE_TRIPLE(camUp);
+ hasCam = true;
+ }
+ // 'angle' - (half?) camera field of view
+ else if (TokenMatch(sz,"angle",5))
+ {
+ AI_NFF_PARSE_FLOAT(angle);
+ hasCam = true;
+ }
+ // 'resolution' - used to compute the screen aspect
+ else if (TokenMatch(sz,"resolution",10))
+ {
+ AI_NFF_PARSE_FLOAT(resolution.x);
+ AI_NFF_PARSE_FLOAT(resolution.y);
+ hasCam = true;
+ }
+ // 'pb' - bezier patch. Not supported yet
+ else if (TokenMatch(sz,"pb",2))
+ {
+ DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch");
+ }
+ // 'pn' - NURBS. Not supported yet
+ else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3))
+ {
+ DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS");
+ }
+ // '' - comment
+ else if ('#' == line[0])
+ {
+ const char* sz;SkipSpaces(&line[1],&sz);
+ if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
+ }
+ }
+ }
+
+ // copy all arrays into one large
+ meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size());
+ meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end());
+ meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
+ meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end());
+
+ // now generate output meshes. first find out how many meshes we'll need
+ std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
+ for (;it != end;++it)
+ {
+ if (!(*it).faces.empty())
+ {
+ ++pScene->mNumMeshes;
+ if ((*it).name[0])++numNamed;
+ }
+ }
+
+ // generate a dummy root node - assign all unnamed elements such
+ // as polygons and polygon patches to the root node and generate
+ // sub nodes for named objects such as spheres and cones.
+ aiNode* const root = new aiNode();
+ root->mName.Set("<NFF_Root>");
+ root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size();
+ root->mNumMeshes = pScene->mNumMeshes-numNamed;
+
+ aiNode** ppcChildren = NULL;
+ unsigned int* pMeshes = NULL;
+ if (root->mNumMeshes)
+ pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes];
+ if (root->mNumChildren)
+ ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
+
+ // generate the camera
+ if (hasCam)
+ {
+ aiNode* nd = *ppcChildren = new aiNode();
+ nd->mName.Set("<NFF_Camera>");
+ nd->mParent = root;
+
+ // allocate the camera in the scene
+ pScene->mNumCameras = 1;
+ pScene->mCameras = new aiCamera*[1];
+ aiCamera* c = pScene->mCameras[0] = new aiCamera;
+
+ c->mName = nd->mName; // make sure the names are identical
+ c->mHorizontalFOV = AI_DEG_TO_RAD( angle );
+ c->mLookAt = camLookAt - camPos;
+ c->mPosition = camPos;
+ c->mUp = camUp;
+
+ // If the resolution is not specified in the file, we
+ // need to set 1.0 as aspect.
+ c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y);
+ ++ppcChildren;
+ }
+
+ // generate light sources
+ if (!lights.empty())
+ {
+ pScene->mNumLights = (unsigned int)lights.size();
+ pScene->mLights = new aiLight*[pScene->mNumLights];
+ for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren)
+ {
+ const Light& l = lights[i];
+
+ aiNode* nd = *ppcChildren = new aiNode();
+ nd->mParent = root;
+
+ nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"<NFF_Light%u>",i);
+
+ // allocate the light in the scene data structure
+ aiLight* out = pScene->mLights[i] = new aiLight();
+ out->mName = nd->mName; // make sure the names are identical
+ out->mType = aiLightSource_POINT;
+ out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity;
+ out->mPosition = l.position;
+ }
+ }
+
+ if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded");
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
+ for (it = meshes.begin(), m = 0; it != end;++it)
+ {
+ if ((*it).faces.empty())continue;
+
+ const MeshInfo& src = *it;
+ aiMesh* const mesh = pScene->mMeshes[m] = new aiMesh();
+ mesh->mNumVertices = (unsigned int)src.vertices.size();
+ mesh->mNumFaces = (unsigned int)src.faces.size();
+
+ // Generate sub nodes for named meshes
+ if ( src.name[ 0 ] && NULL != ppcChildren ) {
+ aiNode* const node = *ppcChildren = new aiNode();
+ node->mParent = root;
+ node->mNumMeshes = 1;
+ node->mMeshes = new unsigned int[1];
+ node->mMeshes[0] = m;
+ node->mName.Set(src.name);
+
+ // setup the transformation matrix of the node
+ aiMatrix4x4::FromToMatrix(aiVector3D(0.f,1.f,0.f),
+ src.dir,node->mTransformation);
+
+ aiMatrix4x4& mat = node->mTransformation;
+ mat.a1 *= src.radius.x; mat.b1 *= src.radius.x; mat.c1 *= src.radius.x;
+ mat.a2 *= src.radius.y; mat.b2 *= src.radius.y; mat.c2 *= src.radius.y;
+ mat.a3 *= src.radius.z; mat.b3 *= src.radius.z; mat.c3 *= src.radius.z;
+ mat.a4 = src.center.x;
+ mat.b4 = src.center.y;
+ mat.c4 = src.center.z;
+
+ ++ppcChildren;
+ } else {
+ *pMeshes++ = m;
+ }
+
+ // copy vertex positions
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ ::memcpy(mesh->mVertices,&src.vertices[0],
+ sizeof(aiVector3D)*mesh->mNumVertices);
+
+ // NFF2: there could be vertex colors
+ if (!src.colors.empty())
+ {
+ ai_assert(src.colors.size() == src.vertices.size());
+
+ // copy vertex colors
+ mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
+ ::memcpy(mesh->mColors[0],&src.colors[0],
+ sizeof(aiColor4D)*mesh->mNumVertices);
+ }
+
+ if (!src.normals.empty())
+ {
+ ai_assert(src.normals.size() == src.vertices.size());
+
+ // copy normal vectors
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+ ::memcpy(mesh->mNormals,&src.normals[0],
+ sizeof(aiVector3D)*mesh->mNumVertices);
+ }
+
+ if (!src.uvs.empty())
+ {
+ ai_assert(src.uvs.size() == src.vertices.size());
+
+ // copy texture coordinates
+ mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+ ::memcpy(mesh->mTextureCoords[0],&src.uvs[0],
+ sizeof(aiVector3D)*mesh->mNumVertices);
+ }
+
+ // generate faces
+ unsigned int p = 0;
+ aiFace* pFace = mesh->mFaces = new aiFace[mesh->mNumFaces];
+ for (std::vector<unsigned int>::const_iterator it2 = src.faces.begin(),
+ end2 = src.faces.end();
+ it2 != end2;++it2,++pFace)
+ {
+ pFace->mIndices = new unsigned int [ pFace->mNumIndices = *it2 ];
+ for (unsigned int o = 0; o < pFace->mNumIndices;++o)
+ pFace->mIndices[o] = p++;
+ }
+
+ // generate a material for the mesh
+ aiMaterial* pcMat = (aiMaterial*)(pScene->mMaterials[m] = new aiMaterial());
+
+ mesh->mMaterialIndex = m++;
+
+ aiString s;
+ s.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcMat->AddProperty(&s, AI_MATKEY_NAME);
+
+ // FIX: Ignore diffuse == 0
+ aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f,1.f,1.f));
+ pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
+ c = src.shader.color * src.shader.specular;
+ pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
+
+ // NFF2 - default values for NFF
+ pcMat->AddProperty(&src.shader.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
+ pcMat->AddProperty(&src.shader.emissive,1,AI_MATKEY_COLOR_EMISSIVE);
+ pcMat->AddProperty(&src.shader.opacity, 1,AI_MATKEY_OPACITY);
+
+ // setup the first texture layer, if existing
+ if (src.shader.texFile.length())
+ {
+ s.Set(src.shader.texFile);
+ pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+ if (aiTextureMapping_UV != src.shader.mapping) {
+
+ aiVector3D v(0.f,-1.f,0.f);
+ pcMat->AddProperty(&v, 1,AI_MATKEY_TEXMAP_AXIS_DIFFUSE(0));
+ pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0));
+ }
+ }
+
+ // setup the name of the material
+ if (src.shader.name.length())
+ {
+ s.Set(src.shader.texFile);
+ pcMat->AddProperty(&s,AI_MATKEY_NAME);
+ }
+
+ // setup some more material properties that are specific to NFF2
+ int i;
+ if (src.shader.twoSided)
+ {
+ i = 1;
+ pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
+ }
+ i = (src.shader.shaded ? aiShadingMode_Gouraud : aiShadingMode_NoShading);
+ if (src.shader.shininess)
+ {
+ i = aiShadingMode_Phong;
+ pcMat->AddProperty(&src.shader.shininess,1,AI_MATKEY_SHININESS);
+ }
+ pcMat->AddProperty(&i,1,AI_MATKEY_SHADING_MODEL);
+ }
+ pScene->mRootNode = root;
}
#endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER
diff --git a/src/3rdparty/assimp/code/NFFLoader.h b/src/3rdparty/assimp/code/NFFLoader.h
index 7b5d3dcae..2b5232645 100644
--- a/src/3rdparty/assimp/code/NFFLoader.h
+++ b/src/3rdparty/assimp/code/NFFLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,165 +45,166 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_NFFLOADER_H_INCLUDED
#include "BaseImporter.h"
+#include <assimp/types.h>
+#include <assimp/material.h>
#include <vector>
-#include "../include/assimp/types.h"
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
/** NFF (Neutral File Format) Importer class.
*
* The class implements both Eric Haynes NFF format and Sense8's NFF (NFF2) format.
- * Both are quite different and the loading code is somewhat dirty at
+ * Both are quite different and the loading code is somewhat dirty at
* the moment. Sense8 should be moved to a separate loader.
*/
class NFFImporter : public BaseImporter
{
public:
- NFFImporter();
- ~NFFImporter();
+ NFFImporter();
+ ~NFFImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
-
- // describes face material properties
- struct ShadingInfo
- {
- ShadingInfo()
- : color (0.6f,0.6f,0.6f)
- , diffuse (1.f,1.f,1.f)
- , specular (1.f,1.f,1.f)
- , ambient (0.f,0.f,0.f)
- , emissive (0.f,0.f,0.f)
- , refracti (1.f)
- , twoSided (false) // for NFF2
- , shaded (true) // for NFF2
- , opacity (1.f)
- , shininess (0.f)
- , mapping (aiTextureMapping_UV)
- {}
-
- aiColor3D color,diffuse,specular,ambient,emissive;
- float refracti;
-
- std::string texFile;
-
- // For NFF2
- bool twoSided;
- bool shaded;
- float opacity, shininess;
-
- std::string name;
-
- // texture mapping to be generated for the mesh - uv is the default
- // it means: use UV if there, nothing otherwise. This property is
- // used for locked meshes.
- aiTextureMapping mapping;
-
- // shininess is ignored for the moment
- bool operator == (const ShadingInfo& other) const
- {
- return color == other.color &&
- diffuse == other.diffuse &&
- specular == other.specular &&
- ambient == other.ambient &&
- refracti == other.refracti &&
- texFile == other.texFile &&
- twoSided == other.twoSided &&
- shaded == other.shaded;
-
- // Some properties from NFF2 aren't compared by this operator.
- // Comparing MeshInfo::matIndex should do that.
- }
- };
-
- // describes a NFF light source
- struct Light
- {
- Light()
- : intensity (1.f)
- , color (1.f,1.f,1.f)
- {}
-
- aiVector3D position;
- float intensity;
- aiColor3D color;
- };
-
- enum PatchType
- {
- PatchType_Simple = 0x0,
- PatchType_Normals = 0x1,
- PatchType_UVAndNormals = 0x2
- };
-
- // describes a NFF mesh
- struct MeshInfo
- {
- MeshInfo(PatchType _pType, bool bL = false)
- : pType (_pType)
- , bLocked (bL)
- , radius (1.f,1.f,1.f)
- , dir (0.f,1.f,0.f)
- , matIndex (0)
- {
- name[0] = '\0'; // by default meshes are unnamed
- }
-
- ShadingInfo shader;
- PatchType pType;
- bool bLocked;
-
- // for spheres, cones and cylinders: center point of the object
- aiVector3D center, radius, dir;
-
- char name[128];
-
- std::vector<aiVector3D> vertices, normals, uvs;
- std::vector<unsigned int> faces;
-
- // for NFF2
- std::vector<aiColor4D> colors;
- unsigned int matIndex;
- };
-
-
- // -------------------------------------------------------------------
- /** Loads the material table for the NFF2 file format from an
- * external file.
- *
- * @param output Receives the list of output meshes
- * @param path Path to the file (abs. or rel.)
- * @param pIOHandler IOSystem to be used to open the file
- */
- void LoadNFF2MaterialTable(std::vector<ShadingInfo>& output,
- const std::string& path, IOSystem* pIOHandler);
+
+ // describes face material properties
+ struct ShadingInfo
+ {
+ ShadingInfo()
+ : color (0.6f,0.6f,0.6f)
+ , diffuse (1.f,1.f,1.f)
+ , specular (1.f,1.f,1.f)
+ , ambient (0.f,0.f,0.f)
+ , emissive (0.f,0.f,0.f)
+ , refracti (1.f)
+ , twoSided (false) // for NFF2
+ , shaded (true) // for NFF2
+ , opacity (1.f)
+ , shininess (0.f)
+ , mapping (aiTextureMapping_UV)
+ {}
+
+ aiColor3D color,diffuse,specular,ambient,emissive;
+ float refracti;
+
+ std::string texFile;
+
+ // For NFF2
+ bool twoSided;
+ bool shaded;
+ float opacity, shininess;
+
+ std::string name;
+
+ // texture mapping to be generated for the mesh - uv is the default
+ // it means: use UV if there, nothing otherwise. This property is
+ // used for locked meshes.
+ aiTextureMapping mapping;
+
+ // shininess is ignored for the moment
+ bool operator == (const ShadingInfo& other) const
+ {
+ return color == other.color &&
+ diffuse == other.diffuse &&
+ specular == other.specular &&
+ ambient == other.ambient &&
+ refracti == other.refracti &&
+ texFile == other.texFile &&
+ twoSided == other.twoSided &&
+ shaded == other.shaded;
+
+ // Some properties from NFF2 aren't compared by this operator.
+ // Comparing MeshInfo::matIndex should do that.
+ }
+ };
+
+ // describes a NFF light source
+ struct Light
+ {
+ Light()
+ : intensity (1.f)
+ , color (1.f,1.f,1.f)
+ {}
+
+ aiVector3D position;
+ float intensity;
+ aiColor3D color;
+ };
+
+ enum PatchType
+ {
+ PatchType_Simple = 0x0,
+ PatchType_Normals = 0x1,
+ PatchType_UVAndNormals = 0x2
+ };
+
+ // describes a NFF mesh
+ struct MeshInfo
+ {
+ MeshInfo(PatchType _pType, bool bL = false)
+ : pType (_pType)
+ , bLocked (bL)
+ , radius (1.f,1.f,1.f)
+ , dir (0.f,1.f,0.f)
+ , matIndex (0)
+ {
+ name[0] = '\0'; // by default meshes are unnamed
+ }
+
+ ShadingInfo shader;
+ PatchType pType;
+ bool bLocked;
+
+ // for spheres, cones and cylinders: center point of the object
+ aiVector3D center, radius, dir;
+
+ char name[128];
+
+ std::vector<aiVector3D> vertices, normals, uvs;
+ std::vector<unsigned int> faces;
+
+ // for NFF2
+ std::vector<aiColor4D> colors;
+ unsigned int matIndex;
+ };
+
+
+ // -------------------------------------------------------------------
+ /** Loads the material table for the NFF2 file format from an
+ * external file.
+ *
+ * @param output Receives the list of output meshes
+ * @param path Path to the file (abs. or rel.)
+ * @param pIOHandler IOSystem to be used to open the file
+ */
+ void LoadNFF2MaterialTable(std::vector<ShadingInfo>& output,
+ const std::string& path, IOSystem* pIOHandler);
};
diff --git a/src/3rdparty/assimp/code/OFFLoader.cpp b/src/3rdparty/assimp/code/OFFLoader.cpp
index 1741cbf76..fd0542fdf 100644
--- a/src/3rdparty/assimp/code/OFFLoader.cpp
+++ b/src/3rdparty/assimp/code/OFFLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,46 +25,50 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file OFFLoader.cpp
- * @brief Implementation of the OFF importer class
+ * @brief Implementation of the OFF importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
// internal headers
#include "OFFLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
static const aiImporterDesc desc = {
- "OFF Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "off"
+ "OFF Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "off"
};
// ------------------------------------------------------------------------------------------------
@@ -73,152 +77,177 @@ OFFImporter::OFFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
OFFImporter::~OFFImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- if (extension == "off")
- return true;
- else if (!extension.length() || checkSig)
- {
- if (!pIOHandler)return true;
- const char* tokens[] = {"off"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "off")
+ return true;
+ else if (!extension.length() || checkSig)
+ {
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"off"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* OFFImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void OFFImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void OFFImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open OFF file " + pFile + ".");
- }
-
- // allocate storage and copy the contents of the file to a memory buffer
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
- const char* buffer = &mBuffer2[0];
-
- char line[4096];
- GetNextLine(buffer,line);
- if ('O' == line[0]) {
- GetNextLine(buffer,line); // skip the 'OFF' line
- }
-
- const char* sz = line; SkipSpaces(&sz);
- const unsigned int numVertices = strtoul10(sz,&sz);SkipSpaces(&sz);
- const unsigned int numFaces = strtoul10(sz,&sz);
-
- pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ];
- aiMesh* mesh = pScene->mMeshes[0] = new aiMesh();
- aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces];
-
- std::vector<aiVector3D> tempPositions(numVertices);
-
- // now read all vertex lines
- for (unsigned int i = 0; i< numVertices;++i)
- {
- if(!GetNextLine(buffer,line))
- {
- DefaultLogger::get()->error("OFF: The number of verts in the header is incorrect");
- break;
- }
- aiVector3D& v = tempPositions[i];
-
- sz = line; SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz,(float&)v.x); SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz,(float&)v.y); SkipSpaces(&sz);
- fast_atoreal_move<float>(sz,(float&)v.z);
- }
-
-
- // First find out how many vertices we'll need
- const char* old = buffer;
- for (unsigned int i = 0; i< mesh->mNumFaces;++i)
- {
- if(!GetNextLine(buffer,line))
- {
- DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect");
- break;
- }
- sz = line;SkipSpaces(&sz);
- if(!(faces->mNumIndices = strtoul10(sz,&sz)) || faces->mNumIndices > 9)
- {
- DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed");
- --mesh->mNumFaces;
- continue;
- }
- mesh->mNumVertices += faces->mNumIndices;
- ++faces;
- }
-
- if (!mesh->mNumVertices)
- throw DeadlyImportError("OFF: There are no valid faces");
-
- // allocate storage for the output vertices
- aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-
- // second: now parse all face indices
- buffer = old;faces = mesh->mFaces;
- for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;)
- {
- if(!GetNextLine(buffer,line))break;
-
- unsigned int idx;
- sz = line;SkipSpaces(&sz);
- if(!(idx = strtoul10(sz,&sz)) || idx > 9)
- continue;
-
- faces->mIndices = new unsigned int [faces->mNumIndices];
- for (unsigned int m = 0; m < faces->mNumIndices;++m)
- {
- SkipSpaces(&sz);
- if ((idx = strtoul10(sz,&sz)) >= numVertices)
- {
- DefaultLogger::get()->error("OFF: Vertex index is out of range");
- idx = numVertices-1;
- }
- faces->mIndices[m] = p++;
- *verts++ = tempPositions[idx];
- }
- ++i;
- ++faces;
- }
-
- // generate the output node graph
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<OFFRoot>");
- pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes = 1];
- pScene->mRootNode->mMeshes[0] = 0;
-
- // generate a default material
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = 1];
- aiMaterial* pcMat = new aiMaterial();
-
- aiColor4D clr(0.6f,0.6f,0.6f,1.0f);
- pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
- pScene->mMaterials[0] = pcMat;
-
- const int twosided =1;
- pcMat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open OFF file " + pFile + ".");
+ }
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ char line[4096];
+ GetNextLine(buffer,line);
+ if ('O' == line[0]) {
+ GetNextLine(buffer,line); // skip the 'OFF' line
+ }
+
+ const char* sz = line; SkipSpaces(&sz);
+ const unsigned int numVertices = strtoul10(sz,&sz);SkipSpaces(&sz);
+ const unsigned int numFaces = strtoul10(sz,&sz);
+
+ if (!numVertices) {
+ throw DeadlyImportError("OFF: There are no valid vertices");
+ }
+ if (!numFaces) {
+ throw DeadlyImportError("OFF: There are no valid faces");
+ }
+
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+
+ aiMesh* mesh = new aiMesh();
+ pScene->mMeshes[0] = mesh;
+
+ mesh->mNumFaces = numFaces;
+ aiFace* faces = new aiFace [mesh->mNumFaces];
+ mesh->mFaces = faces;
+
+ std::vector<aiVector3D> tempPositions(numVertices);
+
+ // now read all vertex lines
+ for (unsigned int i = 0; i< numVertices;++i)
+ {
+ if(!GetNextLine(buffer,line))
+ {
+ DefaultLogger::get()->error("OFF: The number of verts in the header is incorrect");
+ break;
+ }
+ aiVector3D& v = tempPositions[i];
+
+ sz = line; SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz,(float&)v.x); SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz,(float&)v.y); SkipSpaces(&sz);
+ fast_atoreal_move<float>(sz,(float&)v.z);
+ }
+
+
+ // First find out how many vertices we'll need
+ const char* old = buffer;
+ for (unsigned int i = 0; i< mesh->mNumFaces;++i)
+ {
+ if(!GetNextLine(buffer,line))
+ {
+ DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect");
+ break;
+ }
+ sz = line;SkipSpaces(&sz);
+ faces->mNumIndices = strtoul10(sz,&sz);
+ if(!(faces->mNumIndices) || faces->mNumIndices > 9)
+ {
+ DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed");
+ --mesh->mNumFaces;
+ continue;
+ }
+ mesh->mNumVertices += faces->mNumIndices;
+ ++faces;
+ }
+
+ if (!mesh->mNumVertices)
+ throw DeadlyImportError("OFF: There are no valid faces");
+
+ // allocate storage for the output vertices
+ std::vector<aiVector3D> verts;
+ verts.reserve(mesh->mNumVertices);
+
+ // second: now parse all face indices
+ buffer = old;
+ faces = mesh->mFaces;
+ for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;)
+ {
+ if(!GetNextLine(buffer,line))break;
+
+ unsigned int idx;
+ sz = line;SkipSpaces(&sz);
+ idx = strtoul10(sz,&sz);
+ if(!(idx) || idx > 9)
+ continue;
+
+ faces->mIndices = new unsigned int [faces->mNumIndices];
+ for (unsigned int m = 0; m < faces->mNumIndices;++m)
+ {
+ SkipSpaces(&sz);
+ idx = strtoul10(sz,&sz);
+ if ((idx) >= numVertices)
+ {
+ DefaultLogger::get()->error("OFF: Vertex index is out of range");
+ idx = numVertices-1;
+ }
+ faces->mIndices[m] = p++;
+ verts.push_back(tempPositions[idx]);
+ }
+ ++i;
+ ++faces;
+ }
+
+ if (mesh->mNumVertices != verts.size()) {
+ throw DeadlyImportError("OFF: Vertex count mismatch");
+ }
+ mesh->mVertices = new aiVector3D[verts.size()];
+ memcpy(mesh->mVertices, &verts[0], verts.size() * sizeof(aiVector3D));
+ // generate the output node graph
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<OFFRoot>");
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes];
+ pScene->mRootNode->mMeshes[0] = 0;
+
+ // generate a default material
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ aiMaterial* pcMat = new aiMaterial();
+
+ aiColor4D clr(0.6f,0.6f,0.6f,1.0f);
+ pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ pScene->mMaterials[0] = pcMat;
+
+ const int twosided =1;
+ pcMat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
}
#endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER
diff --git a/src/3rdparty/assimp/code/OFFLoader.h b/src/3rdparty/assimp/code/OFFLoader.h
index c95353a5b..f01dc6244 100644
--- a/src/3rdparty/assimp/code/OFFLoader.h
+++ b/src/3rdparty/assimp/code/OFFLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,32 +23,32 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file OFFLoader.h
- * @brief Declaration of the OFF importer class.
+ * @brief Declaration of the OFF importer class.
*/
#ifndef AI_OFFLOADER_H_INCLUDED
#define AI_OFFLOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include <vector>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the Object File Format (.off)
@@ -56,32 +56,32 @@ namespace Assimp {
class OFFImporter : public BaseImporter
{
public:
- OFFImporter();
- ~OFFImporter();
+ OFFImporter();
+ ~OFFImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
-
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
diff --git a/src/3rdparty/assimp/code/ObjExporter.cpp b/src/3rdparty/assimp/code/ObjExporter.cpp
index 0499031e9..ca07730bc 100644
--- a/src/3rdparty/assimp/code/ObjExporter.cpp
+++ b/src/3rdparty/assimp/code/ObjExporter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,329 +23,343 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
#include "ObjExporter.h"
-#include "../include/assimp/version.h"
+#include "Exceptional.h"
+#include "StringComparison.h"
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <memory>
+
using namespace Assimp;
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp
-void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
- // invoke the exporter
- ObjExporter exporter(pFile, pScene);
-
- // we're still here - export successfully completed. Write both the main OBJ file and the material script
- {
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
- }
- outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
- }
- {
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
- }
- outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
- }
+ // invoke the exporter
+ ObjExporter exporter(pFile, pScene);
+
+ // we're still here - export successfully completed. Write both the main OBJ file and the material script
+ {
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
+ }
+ outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+ }
+ {
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
+ }
+ outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
+ }
}
} // end of namespace Assimp
+static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------
ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
: filename(_filename)
, pScene(pScene)
-, endl("\n")
+, endl("\n")
{
- // make sure that all formatting happens using the standard, C locale and not the user's current locale
- const std::locale& l = std::locale("C");
- mOutput.imbue(l);
- mOutputMat.imbue(l);
-
- WriteGeometryFile();
- WriteMaterialFile();
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ const std::locale& l = std::locale("C");
+ mOutput.imbue(l);
+ mOutput.precision(16);
+ mOutputMat.imbue(l);
+ mOutputMat.precision(16);
+
+ WriteGeometryFile();
+ WriteMaterialFile();
}
// ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialLibName()
-{
- // within the Obj file, we use just the relative file name with the path stripped
- const std::string& s = GetMaterialLibFileName();
- std::string::size_type il = s.find_last_of("/\\");
- if (il != std::string::npos) {
- return s.substr(il + 1);
- }
-
- return s;
+{
+ // within the Obj file, we use just the relative file name with the path stripped
+ const std::string& s = GetMaterialLibFileName();
+ std::string::size_type il = s.find_last_of("/\\");
+ if (il != std::string::npos) {
+ return s.substr(il + 1);
+ }
+
+ return s;
}
// ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialLibFileName()
-{
- return filename + ".mtl";
+{
+ return filename + MaterialExt;
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: WriteHeader(std::ostringstream& out)
{
- out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
- out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl;
+ out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
+ out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl;
}
// ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialName(unsigned int index)
{
- const aiMaterial* const mat = pScene->mMaterials[index];
- aiString s;
- if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
- return std::string(s.data,s.length);
- }
-
- char number[ sizeof(unsigned int) * 3 + 1 ];
- ASSIMP_itoa10(number,index);
- return "$Material_" + std::string(number);
+ const aiMaterial* const mat = pScene->mMaterials[index];
+ aiString s;
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
+ return std::string(s.data,s.length);
+ }
+
+ char number[ sizeof(unsigned int) * 3 + 1 ];
+ ASSIMP_itoa10(number,index);
+ return "$Material_" + std::string(number);
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter :: WriteMaterialFile()
+void ObjExporter::WriteMaterialFile()
{
- WriteHeader(mOutputMat);
-
- for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
- const aiMaterial* const mat = pScene->mMaterials[i];
-
- int illum = 1;
- mOutputMat << "newmtl " << GetMaterialName(i) << endl;
-
- aiColor4D c;
- if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
- mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
- mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
- mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
- mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl;
- }
-
- float o;
- if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
- mOutputMat << "d " << o << endl;
- }
-
- if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
- mOutputMat << "Ns " << o << endl;
- illum = 2;
- }
-
- mOutputMat << "illum " << illum << endl;
-
- aiString s;
- if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
- mOutputMat << "map_kd " << s.data << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
- mOutputMat << "map_ka " << s.data << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
- mOutputMat << "map_ks " << s.data << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
- mOutputMat << "map_ns " << s.data << endl;
- }
- if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
- // implementations seem to vary here, so write both variants
- mOutputMat << "bump " << s.data << endl;
- mOutputMat << "map_bump " << s.data << endl;
- }
-
- mOutputMat << endl;
- }
+ WriteHeader(mOutputMat);
+
+ for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+ const aiMaterial* const mat = pScene->mMaterials[i];
+
+ int illum = 1;
+ mOutputMat << "newmtl " << GetMaterialName(i) << endl;
+
+ aiColor4D c;
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
+ mOutputMat << "Kd " << c.r << " " << c.g << " " << c.b << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
+ mOutputMat << "Ka " << c.r << " " << c.g << " " << c.b << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
+ mOutputMat << "Ks " << c.r << " " << c.g << " " << c.b << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
+ mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
+ }
+
+ float o;
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) {
+ mOutputMat << "d " << o << endl;
+ }
+
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) {
+ mOutputMat << "Ns " << o << endl;
+ illum = 2;
+ }
+
+ mOutputMat << "illum " << illum << endl;
+
+ aiString s;
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
+ mOutputMat << "map_Kd " << s.data << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
+ mOutputMat << "map_Ka " << s.data << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
+ mOutputMat << "map_Ks " << s.data << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
+ mOutputMat << "map_Ns " << s.data << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_OPACITY(0),s)) {
+ mOutputMat << "map_d " << s.data << endl;
+ }
+ if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
+ // implementations seem to vary here, so write both variants
+ mOutputMat << "bump " << s.data << endl;
+ mOutputMat << "map_bump " << s.data << endl;
+ }
+
+ mOutputMat << endl;
+ }
}
// ------------------------------------------------------------------------------------------------
void ObjExporter :: WriteGeometryFile()
{
- WriteHeader(mOutput);
- mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
-
- // collect mesh geometry
- aiMatrix4x4 mBase;
- AddNode(pScene->mRootNode,mBase);
-
- // write vertex positions
- vpMap.getVectors(vp);
- mOutput << "# " << vp.size() << " vertex positions" << endl;
- BOOST_FOREACH(const aiVector3D& v, vp) {
- mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
- }
- mOutput << endl;
-
- // write uv coordinates
- vtMap.getVectors(vt);
- mOutput << "# " << vt.size() << " UV coordinates" << endl;
- BOOST_FOREACH(const aiVector3D& v, vt) {
- mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
- }
- mOutput << endl;
-
- // write vertex normals
- vnMap.getVectors(vn);
- mOutput << "# " << vn.size() << " vertex normals" << endl;
- BOOST_FOREACH(const aiVector3D& v, vn) {
- mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
- }
- mOutput << endl;
-
- // now write all mesh instances
- BOOST_FOREACH(const MeshInstance& m, meshes) {
- mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
- mOutput << "g " << m.name << endl;
- mOutput << "usemtl " << m.matname << endl;
-
- BOOST_FOREACH(const Face& f, m.faces) {
- mOutput << f.kind << ' ';
- BOOST_FOREACH(const FaceVertex& fv, f.indices) {
- mOutput << ' ' << fv.vp;
-
- if (f.kind != 'p') {
- if (fv.vt || f.kind == 'f') {
- mOutput << '/';
- }
- if (fv.vt) {
- mOutput << fv.vt;
- }
- if (f.kind == 'f') {
- mOutput << '/';
- if (fv.vn) {
- mOutput << fv.vn;
- }
- }
- }
- }
-
- mOutput << endl;
- }
- mOutput << endl;
- }
+ WriteHeader(mOutput);
+ mOutput << "mtllib " << GetMaterialLibName() << endl << endl;
+
+ // collect mesh geometry
+ aiMatrix4x4 mBase;
+ AddNode(pScene->mRootNode, mBase);
+
+ // write vertex positions
+ vpMap.getVectors(vp);
+ mOutput << "# " << vp.size() << " vertex positions" << endl;
+ for(const aiVector3D& v : vp) {
+ mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
+ }
+ mOutput << endl;
+
+ // write uv coordinates
+ vtMap.getVectors(vt);
+ mOutput << "# " << vt.size() << " UV coordinates" << endl;
+ for(const aiVector3D& v : vt) {
+ mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
+ }
+ mOutput << endl;
+
+ // write vertex normals
+ vnMap.getVectors(vn);
+ mOutput << "# " << vn.size() << " vertex normals" << endl;
+ for(const aiVector3D& v : vn) {
+ mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
+ }
+ mOutput << endl;
+
+ // now write all mesh instances
+ for(const MeshInstance& m : meshes) {
+ mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
+ if (!m.name.empty()) {
+ mOutput << "g " << m.name << endl;
+ }
+ mOutput << "usemtl " << m.matname << endl;
+
+ for(const Face& f : m.faces) {
+ mOutput << f.kind << ' ';
+ for(const FaceVertex& fv : f.indices) {
+ mOutput << ' ' << fv.vp;
+
+ if (f.kind != 'p') {
+ if (fv.vt || f.kind == 'f') {
+ mOutput << '/';
+ }
+ if (fv.vt) {
+ mOutput << fv.vt;
+ }
+ if (f.kind == 'f' && fv.vn) {
+ mOutput << '/' << fv.vn;
+ }
+ }
+ }
+
+ mOutput << endl;
+ }
+ mOutput << endl;
+ }
}
-
-
-
-
+// ------------------------------------------------------------------------------------------------
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
{
- vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
- if(vertIt != vecMap.end()){// vertex already exists, so reference it
- return vertIt->second;
- }
- vecMap[vec] = mNextIndex;
- int ret = mNextIndex;
- mNextIndex++;
- return ret;
+ vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
+ // vertex already exists, so reference it
+ if(vertIt != vecMap.end()){
+ return vertIt->second;
+ }
+ vecMap[vec] = mNextIndex;
+ int ret = mNextIndex;
+ mNextIndex++;
+ return ret;
}
+// ------------------------------------------------------------------------------------------------
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
{
- vecs.resize(vecMap.size());
- for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); it++){
- vecs[it->second-1] = it->first;
- }
+ vecs.resize(vecMap.size());
+ for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){
+ vecs[it->second-1] = it->first;
+ }
}
-
// ------------------------------------------------------------------------------------------------
-void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
+void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
{
- meshes.push_back(MeshInstance());
- MeshInstance& mesh = meshes.back();
-
- mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_"+std::string(m->mName.data,m->mName.length) : "");
- mesh.matname = GetMaterialName(m->mMaterialIndex);
-
- mesh.faces.resize(m->mNumFaces);
-
- for(unsigned int i = 0; i < m->mNumFaces; ++i) {
- const aiFace& f = m->mFaces[i];
-
- Face& face = mesh.faces[i];
- switch (f.mNumIndices) {
- case 1:
- face.kind = 'p';
- break;
- case 2:
- face.kind = 'l';
- break;
- default:
- face.kind = 'f';
- }
- face.indices.resize(f.mNumIndices);
-
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- const unsigned int idx = f.mIndices[a];
-
- aiVector3D vert = mat * m->mVertices[idx];
- face.indices[a].vp = vpMap.getIndex(vert);
-
- if (m->mNormals) {
- face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]);
- }
- else{
- face.indices[a].vn = 0;
- }
-
- if (m->mTextureCoords[0]) {
- face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
- }
- else{
- face.indices[a].vt = 0;
- }
- }
- }
+ meshes.push_back(MeshInstance());
+ MeshInstance& mesh = meshes.back();
+
+ mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
+ mesh.matname = GetMaterialName(m->mMaterialIndex);
+
+ mesh.faces.resize(m->mNumFaces);
+
+ for(unsigned int i = 0; i < m->mNumFaces; ++i) {
+ const aiFace& f = m->mFaces[i];
+
+ Face& face = mesh.faces[i];
+ switch (f.mNumIndices) {
+ case 1:
+ face.kind = 'p';
+ break;
+ case 2:
+ face.kind = 'l';
+ break;
+ default:
+ face.kind = 'f';
+ }
+ face.indices.resize(f.mNumIndices);
+
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ const unsigned int idx = f.mIndices[a];
+
+ aiVector3D vert = mat * m->mVertices[idx];
+ face.indices[a].vp = vpMap.getIndex(vert);
+
+ if (m->mNormals) {
+ aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
+ face.indices[a].vn = vnMap.getIndex(norm);
+ }
+ else{
+ face.indices[a].vn = 0;
+ }
+
+ if (m->mTextureCoords[0]) {
+ face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
+ }
+ else{
+ face.indices[a].vt = 0;
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
+void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
{
- const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
+ const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
- for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
- AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]],mAbs);
- }
+ for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
+ AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
+ }
- for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
- AddNode(nd->mChildren[i],mAbs);
- }
+ for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
+ AddNode(nd->mChildren[i], mAbs);
+ }
}
-#endif
-#endif
+// ------------------------------------------------------------------------------------------------
+
+#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/ObjExporter.h b/src/3rdparty/assimp/code/ObjExporter.h
index 4efd85636..9d817f067 100644
--- a/src/3rdparty/assimp/code/ObjExporter.h
+++ b/src/3rdparty/assimp/code/ObjExporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,33 +23,37 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file ColladaExporter.h
+/** @file ObjExporter.h
* Declares the exporter class to write a scene to a Collada file
*/
#ifndef AI_OBJEXPORTER_H_INC
#define AI_OBJEXPORTER_H_INC
+#include <assimp/types.h>
#include <sstream>
+#include <vector>
+#include <map>
struct aiScene;
struct aiNode;
+struct aiMesh;
-namespace Assimp
+namespace Assimp
{
// ------------------------------------------------------------------------------------------------
@@ -58,94 +62,94 @@ namespace Assimp
class ObjExporter
{
public:
- /// Constructor for a specific scene to export
- ObjExporter(const char* filename, const aiScene* pScene);
+ /// Constructor for a specific scene to export
+ ObjExporter(const char* filename, const aiScene* pScene);
public:
- std::string GetMaterialLibName();
- std::string GetMaterialLibFileName();
-
+ std::string GetMaterialLibName();
+ std::string GetMaterialLibFileName();
+
public:
- /// public stringstreams to write all output into
- std::ostringstream mOutput, mOutputMat;
+ /// public stringstreams to write all output into
+ std::ostringstream mOutput, mOutputMat;
private:
- // intermediate data structures
- struct FaceVertex
- {
- FaceVertex()
- : vp(),vn(),vt()
- {
- }
+ // intermediate data structures
+ struct FaceVertex
+ {
+ FaceVertex()
+ : vp(),vn(),vt()
+ {
+ }
- // one-based, 0 means: 'does not exist'
- unsigned int vp,vn,vt;
- };
+ // one-based, 0 means: 'does not exist'
+ unsigned int vp,vn,vt;
+ };
- struct Face {
- char kind;
- std::vector<FaceVertex> indices;
- };
+ struct Face {
+ char kind;
+ std::vector<FaceVertex> indices;
+ };
- struct MeshInstance {
+ struct MeshInstance {
- std::string name, matname;
- std::vector<Face> faces;
- };
+ std::string name, matname;
+ std::vector<Face> faces;
+ };
- void WriteHeader(std::ostringstream& out);
+ void WriteHeader(std::ostringstream& out);
- void WriteMaterialFile();
- void WriteGeometryFile();
+ void WriteMaterialFile();
+ void WriteGeometryFile();
- std::string GetMaterialName(unsigned int index);
+ std::string GetMaterialName(unsigned int index);
- void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat);
- void AddNode(const aiNode* nd, const aiMatrix4x4& mParent);
+ void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat);
+ void AddNode(const aiNode* nd, const aiMatrix4x4& mParent);
private:
- const std::string filename;
- const aiScene* const pScene;
+ const std::string filename;
+ const aiScene* const pScene;
- std::vector<aiVector3D> vp, vn, vt;
+ std::vector<aiVector3D> vp, vn, vt;
- struct aiVectorCompare
- {
- bool operator() (const aiVector3D& a, const aiVector3D& b) const
- {
- if(a.x < b.x) return true;
- if(a.x > b.x) return false;
- if(a.y < b.y) return true;
- if(a.y > b.y) return false;
- if(a.z < b.z) return true;
- return false;
- }
- };
+ struct aiVectorCompare
+ {
+ bool operator() (const aiVector3D& a, const aiVector3D& b) const
+ {
+ if(a.x < b.x) return true;
+ if(a.x > b.x) return false;
+ if(a.y < b.y) return true;
+ if(a.y > b.y) return false;
+ if(a.z < b.z) return true;
+ return false;
+ }
+ };
- class vecIndexMap
- {
- int mNextIndex;
- typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
- dataType vecMap;
- public:
+ class vecIndexMap
+ {
+ int mNextIndex;
+ typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
+ dataType vecMap;
+ public:
- vecIndexMap():mNextIndex(1)
- {}
+ vecIndexMap():mNextIndex(1)
+ {}
- int getIndex(const aiVector3D& vec);
- void getVectors( std::vector<aiVector3D>& vecs );
- };
+ int getIndex(const aiVector3D& vec);
+ void getVectors( std::vector<aiVector3D>& vecs );
+ };
- vecIndexMap vpMap, vnMap, vtMap;
- std::vector<MeshInstance> meshes;
+ vecIndexMap vpMap, vnMap, vtMap;
+ std::vector<MeshInstance> meshes;
- // this endl() doesn't flush() the stream
- const std::string endl;
+ // this endl() doesn't flush() the stream
+ const std::string endl;
};
}
diff --git a/src/3rdparty/assimp/code/ObjFileData.h b/src/3rdparty/assimp/code/ObjFileData.h
index 6067e21e7..f4abd643f 100644
--- a/src/3rdparty/assimp/code/ObjFileData.h
+++ b/src/3rdparty/assimp/code/ObjFileData.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,300 +43,310 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <map>
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
-namespace Assimp
-{
+namespace Assimp {
+namespace ObjFile {
-namespace ObjFile
-{
-// ------------------------------------------------------------------------------------------------
struct Object;
struct Face;
struct Material;
// ------------------------------------------------------------------------------------------------
-//! \struct Face
-//! \brief Data structure for a simple obj-face, describes discredit,l.ation and materials
+//! \struct Face
+//! \brief Data structure for a simple obj-face, describes discredit,l.ation and materials
struct Face
{
- typedef std::vector<unsigned int> IndexArray;
-
- //! Primitive type
- aiPrimitiveType m_PrimitiveType;
- //! Vertex indices
- IndexArray *m_pVertices;
- //! Normal indices
- IndexArray *m_pNormals;
- //! Texture coordinates indices
- IndexArray *m_pTexturCoords;
- //! Pointer to assigned material
- Material *m_pMaterial;
-
- //! \brief Default constructor
- //! \param pVertices Pointer to assigned vertex indexbuffer
- //! \param pNormals Pointer to assigned normals indexbuffer
- //! \param pTexCoords Pointer to assigned texture indexbuffer
- Face( std::vector<unsigned int> *pVertices,
- std::vector<unsigned int> *pNormals,
- std::vector<unsigned int> *pTexCoords,
- aiPrimitiveType pt = aiPrimitiveType_POLYGON) :
- m_PrimitiveType( pt ),
- m_pVertices( pVertices ),
- m_pNormals( pNormals ),
- m_pTexturCoords( pTexCoords ),
- m_pMaterial( 0L )
- {
- // empty
- }
-
- //! \brief Destructor
- ~Face()
- {
- delete m_pVertices;
- m_pVertices = NULL;
-
- delete m_pNormals;
- m_pNormals = NULL;
-
- delete m_pTexturCoords;
- m_pTexturCoords = NULL;
- }
+ typedef std::vector<unsigned int> IndexArray;
+
+ //! Primitive type
+ aiPrimitiveType m_PrimitiveType;
+ //! Vertex indices
+ IndexArray *m_pVertices;
+ //! Normal indices
+ IndexArray *m_pNormals;
+ //! Texture coordinates indices
+ IndexArray *m_pTexturCoords;
+ //! Pointer to assigned material
+ Material *m_pMaterial;
+
+ //! \brief Default constructor
+ //! \param pVertices Pointer to assigned vertex indexbuffer
+ //! \param pNormals Pointer to assigned normals indexbuffer
+ //! \param pTexCoords Pointer to assigned texture indexbuffer
+ Face( std::vector<unsigned int> *pVertices,
+ std::vector<unsigned int> *pNormals,
+ std::vector<unsigned int> *pTexCoords,
+ aiPrimitiveType pt = aiPrimitiveType_POLYGON) :
+ m_PrimitiveType( pt ),
+ m_pVertices( pVertices ),
+ m_pNormals( pNormals ),
+ m_pTexturCoords( pTexCoords ),
+ m_pMaterial( 0L )
+ {
+ // empty
+ }
+
+ //! \brief Destructor
+ ~Face()
+ {
+ delete m_pVertices;
+ m_pVertices = NULL;
+
+ delete m_pNormals;
+ m_pNormals = NULL;
+
+ delete m_pTexturCoords;
+ m_pTexturCoords = NULL;
+ }
};
// ------------------------------------------------------------------------------------------------
-//! \struct Object
-//! \brief Stores all objects of an objfile object definition
+//! \struct Object
+//! \brief Stores all objects of an objfile object definition
struct Object
{
- enum ObjectType
- {
- ObjType,
- GroupType
- };
-
- //! Object name
- std::string m_strObjName;
- //! Transformation matrix, stored in OpenGL format
- aiMatrix4x4 m_Transformation;
- //! All sub-objects referenced by this object
- std::vector<Object*> m_SubObjects;
- /// Assigned meshes
- std::vector<unsigned int> m_Meshes;
-
- //! \brief Default constructor
- Object() :
- m_strObjName("")
- {
- // empty
- }
-
- //! \brief Destructor
- ~Object()
- {
- for (std::vector<Object*>::iterator it = m_SubObjects.begin();
- it != m_SubObjects.end(); ++it)
- {
- delete *it;
- }
- m_SubObjects.clear();
- }
+ enum ObjectType
+ {
+ ObjType,
+ GroupType
+ };
+
+ //! Object name
+ std::string m_strObjName;
+ //! Transformation matrix, stored in OpenGL format
+ aiMatrix4x4 m_Transformation;
+ //! All sub-objects referenced by this object
+ std::vector<Object*> m_SubObjects;
+ /// Assigned meshes
+ std::vector<unsigned int> m_Meshes;
+
+ //! \brief Default constructor
+ Object() :
+ m_strObjName("")
+ {
+ // empty
+ }
+
+ //! \brief Destructor
+ ~Object()
+ {
+ for (std::vector<Object*>::iterator it = m_SubObjects.begin();
+ it != m_SubObjects.end(); ++it)
+ {
+ delete *it;
+ }
+ m_SubObjects.clear();
+ }
};
// ------------------------------------------------------------------------------------------------
-//! \struct Material
-//! \brief Data structure to store all material specific data
+//! \struct Material
+//! \brief Data structure to store all material specific data
struct Material
{
- //! Name of material description
- aiString MaterialName;
-
- //! Texture names
- aiString texture;
- aiString textureSpecular;
- aiString textureAmbient;
- aiString textureEmissive;
- aiString textureBump;
- aiString textureNormal;
- aiString textureSpecularity;
- aiString textureOpacity;
- aiString textureDisp;
- enum TextureType
- {
- TextureDiffuseType = 0,
- TextureSpecularType,
- TextureAmbientType,
- TextureEmissiveType,
- TextureBumpType,
- TextureNormalType,
- TextureSpecularityType,
- TextureOpacityType,
- TextureDispType,
- TextureTypeCount
- };
- bool clamp[TextureTypeCount];
-
- //! Ambient color
- aiColor3D ambient;
- //! Diffuse color
- aiColor3D diffuse;
- //! Specular color
- aiColor3D specular;
- //! Emissive color
- aiColor3D emissive;
- //! Alpha value
- float alpha;
- //! Shineness factor
- float shineness;
- //! Illumination model
- int illumination_model;
- //! Index of refraction
- float ior;
-
- //! Constructor
- Material()
- : diffuse (0.6f,0.6f,0.6f)
- , alpha (1.f)
- , shineness (0.0f)
- , illumination_model (1)
- , ior (1.f)
- {
- // empty
- for (size_t i = 0; i < TextureTypeCount; ++i)
- {
- clamp[i] = false;
- }
- }
-
- // Destructor
- ~Material()
- {
- // empty
- }
+ //! Name of material description
+ aiString MaterialName;
+
+ //! Texture names
+ aiString texture;
+ aiString textureSpecular;
+ aiString textureAmbient;
+ aiString textureEmissive;
+ aiString textureBump;
+ aiString textureNormal;
+ aiString textureReflection[6];
+ aiString textureSpecularity;
+ aiString textureOpacity;
+ aiString textureDisp;
+ enum TextureType
+ {
+ TextureDiffuseType = 0,
+ TextureSpecularType,
+ TextureAmbientType,
+ TextureEmissiveType,
+ TextureBumpType,
+ TextureNormalType,
+ TextureReflectionSphereType,
+ TextureReflectionCubeTopType,
+ TextureReflectionCubeBottomType,
+ TextureReflectionCubeFrontType,
+ TextureReflectionCubeBackType,
+ TextureReflectionCubeLeftType,
+ TextureReflectionCubeRightType,
+ TextureSpecularityType,
+ TextureOpacityType,
+ TextureDispType,
+ TextureTypeCount
+ };
+ bool clamp[TextureTypeCount];
+
+ //! Ambient color
+ aiColor3D ambient;
+ //! Diffuse color
+ aiColor3D diffuse;
+ //! Specular color
+ aiColor3D specular;
+ //! Emissive color
+ aiColor3D emissive;
+ //! Alpha value
+ float alpha;
+ //! Shineness factor
+ float shineness;
+ //! Illumination model
+ int illumination_model;
+ //! Index of refraction
+ float ior;
+
+ //! Constructor
+ Material()
+ : diffuse (0.6f,0.6f,0.6f)
+ , alpha (1.f)
+ , shineness (0.0f)
+ , illumination_model (1)
+ , ior (1.f)
+ {
+ // empty
+ for (size_t i = 0; i < TextureTypeCount; ++i)
+ {
+ clamp[i] = false;
+ }
+ }
+
+ // Destructor
+ ~Material()
+ {
+ // empty
+ }
};
// ------------------------------------------------------------------------------------------------
-//! \struct Mesh
-//! \brief Data structure to store a mesh
-struct Mesh
-{
- static const unsigned int NoMaterial = ~0u;
-
- /// Array with pointer to all stored faces
- std::vector<Face*> m_Faces;
- /// Assigned material
- Material *m_pMaterial;
- /// Number of stored indices.
- unsigned int m_uiNumIndices;
- /// Number of UV
- unsigned int m_uiUVCoordinates[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
- /// Material index.
- unsigned int m_uiMaterialIndex;
- /// True, if normals are stored.
- bool m_hasNormals;
- /// Constructor
- Mesh() :
- m_pMaterial(NULL),
- m_uiNumIndices(0),
- m_uiMaterialIndex( NoMaterial ),
- m_hasNormals(false)
- {
- memset(m_uiUVCoordinates, 0, sizeof( unsigned int ) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
- }
-
- /// Destructor
- ~Mesh()
- {
- for (std::vector<Face*>::iterator it = m_Faces.begin();
- it != m_Faces.end(); ++it)
- {
- delete *it;
- }
- }
+//! \struct Mesh
+//! \brief Data structure to store a mesh
+struct Mesh {
+ static const unsigned int NoMaterial = ~0u;
+ /// The name for the mesh
+ std::string m_name;
+ /// Array with pointer to all stored faces
+ std::vector<Face*> m_Faces;
+ /// Assigned material
+ Material *m_pMaterial;
+ /// Number of stored indices.
+ unsigned int m_uiNumIndices;
+ /// Number of UV
+ unsigned int m_uiUVCoordinates[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ /// Material index.
+ unsigned int m_uiMaterialIndex;
+ /// True, if normals are stored.
+ bool m_hasNormals;
+ /// True, if vertex colors are stored.
+ bool m_hasVertexColors;
+
+ /// Constructor
+ explicit Mesh( const std::string &name )
+ : m_name( name )
+ , m_pMaterial(NULL)
+ , m_uiNumIndices(0)
+ , m_uiMaterialIndex( NoMaterial )
+ , m_hasNormals(false) {
+ memset(m_uiUVCoordinates, 0, sizeof( unsigned int ) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
+ }
+
+ /// Destructor
+ ~Mesh()
+ {
+ for (std::vector<Face*>::iterator it = m_Faces.begin();
+ it != m_Faces.end(); ++it)
+ {
+ delete *it;
+ }
+ }
};
// ------------------------------------------------------------------------------------------------
-//! \struct Model
-//! \brief Data structure to store all obj-specific model datas
+//! \struct Model
+//! \brief Data structure to store all obj-specific model datas
struct Model
{
- typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
- typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
- typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
-
- //! Model name
- std::string m_ModelName;
- //! List ob assigned objects
- std::vector<Object*> m_Objects;
- //! Pointer to current object
- ObjFile::Object *m_pCurrent;
- //! Pointer to current material
- ObjFile::Material *m_pCurrentMaterial;
- //! Pointer to default material
- ObjFile::Material *m_pDefaultMaterial;
- //! Vector with all generated materials
- std::vector<std::string> m_MaterialLib;
- //! Vector with all generated group
- std::vector<std::string> m_GroupLib;
- //! Vector with all generated vertices
- std::vector<aiVector3D> m_Vertices;
- //! vector with all generated normals
- std::vector<aiVector3D> m_Normals;
- //! Group map
- GroupMap m_Groups;
- //! Group to face id assignment
- std::vector<unsigned int> *m_pGroupFaceIDs;
- //! Active group
- std::string m_strActiveGroup;
- //! Vector with generated texture coordinates
- std::vector<aiVector3D> m_TextureCoord;
- //! Current mesh instance
- Mesh *m_pCurrentMesh;
- //! Vector with stored meshes
- std::vector<Mesh*> m_Meshes;
- //! Material map
- std::map<std::string, Material*> m_MaterialMap;
-
- //! \brief The default class constructor
- Model() :
- m_ModelName(""),
- m_pCurrent(NULL),
- m_pCurrentMaterial(NULL),
- m_pDefaultMaterial(NULL),
+ typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
+ typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
+ typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
+
+ //! Model name
+ std::string m_ModelName;
+ //! List ob assigned objects
+ std::vector<Object*> m_Objects;
+ //! Pointer to current object
+ ObjFile::Object *m_pCurrent;
+ //! Pointer to current material
+ ObjFile::Material *m_pCurrentMaterial;
+ //! Pointer to default material
+ ObjFile::Material *m_pDefaultMaterial;
+ //! Vector with all generated materials
+ std::vector<std::string> m_MaterialLib;
+ //! Vector with all generated group
+ std::vector<std::string> m_GroupLib;
+ //! Vector with all generated vertices
+ std::vector<aiVector3D> m_Vertices;
+ //! vector with all generated normals
+ std::vector<aiVector3D> m_Normals;
+ //! vector with all vertex colors
+ std::vector<aiVector3D> m_VertexColors;
+ //! Group map
+ GroupMap m_Groups;
+ //! Group to face id assignment
+ std::vector<unsigned int> *m_pGroupFaceIDs;
+ //! Active group
+ std::string m_strActiveGroup;
+ //! Vector with generated texture coordinates
+ std::vector<aiVector3D> m_TextureCoord;
+ //! Current mesh instance
+ Mesh *m_pCurrentMesh;
+ //! Vector with stored meshes
+ std::vector<Mesh*> m_Meshes;
+ //! Material map
+ std::map<std::string, Material*> m_MaterialMap;
+
+ //! \brief The default class constructor
+ Model() :
+ m_ModelName(""),
+ m_pCurrent(NULL),
+ m_pCurrentMaterial(NULL),
+ m_pDefaultMaterial(NULL),
m_pGroupFaceIDs(NULL),
- m_strActiveGroup(""),
- m_pCurrentMesh(NULL)
- {
- // empty
- }
-
- //! \brief The class destructor
- ~Model()
- {
- // Clear all stored object instances
- for (std::vector<Object*>::iterator it = m_Objects.begin();
- it != m_Objects.end(); ++it) {
- delete *it;
- }
- m_Objects.clear();
-
- // Clear all stored mesh instances
- for (std::vector<Mesh*>::iterator it = m_Meshes.begin();
- it != m_Meshes.end(); ++it) {
- delete *it;
- }
- m_Meshes.clear();
-
- for(GroupMapIt it = m_Groups.begin(); it != m_Groups.end(); ++it) {
- delete it->second;
- }
- m_Groups.clear();
-
- for ( std::map<std::string, Material*>::iterator it = m_MaterialMap.begin(); it != m_MaterialMap.end(); ++it ) {
- delete it->second;
- }
- }
+ m_strActiveGroup(""),
+ m_pCurrentMesh(NULL)
+ {
+ // empty
+ }
+
+ //! \brief The class destructor
+ ~Model()
+ {
+ // Clear all stored object instances
+ for (std::vector<Object*>::iterator it = m_Objects.begin();
+ it != m_Objects.end(); ++it) {
+ delete *it;
+ }
+ m_Objects.clear();
+
+ // Clear all stored mesh instances
+ for (std::vector<Mesh*>::iterator it = m_Meshes.begin();
+ it != m_Meshes.end(); ++it) {
+ delete *it;
+ }
+ m_Meshes.clear();
+
+ for(GroupMapIt it = m_Groups.begin(); it != m_Groups.end(); ++it) {
+ delete it->second;
+ }
+ m_Groups.clear();
+
+ for ( std::map<std::string, Material*>::iterator it = m_MaterialMap.begin(); it != m_MaterialMap.end(); ++it ) {
+ delete it->second;
+ }
+ }
};
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/ObjFileImporter.cpp b/src/3rdparty/assimp/code/ObjFileImporter.cpp
index af0038a31..082709dc7 100644
--- a/src/3rdparty/assimp/code/ObjFileImporter.cpp
+++ b/src/3rdparty/assimp/code/ObjFileImporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,674 +25,734 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "DefaultIOSystem.h"
#include "ObjFileImporter.h"
#include "ObjFileParser.h"
#include "ObjFileData.h"
+#include <memory>
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
+#include <assimp/DefaultLogger.hpp>
+
static const aiImporterDesc desc = {
- "Wavefront Object Importer",
- "",
- "",
- "surfaces not supported",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "obj"
+ "Wavefront Object Importer",
+ "",
+ "",
+ "surfaces not supported",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "obj"
};
static const unsigned int ObjMinSize = 16;
-namespace Assimp {
+namespace Assimp {
using namespace std;
// ------------------------------------------------------------------------------------------------
-// Default constructor
+// Default constructor
ObjFileImporter::ObjFileImporter() :
- m_Buffer(),
- m_pRootObject( NULL ),
- m_strAbsPath( "" )
+ m_Buffer(),
+ m_pRootObject( NULL ),
+ m_strAbsPath( "" )
{
DefaultIOSystem io;
- m_strAbsPath = io.getOsSeparator();
+ m_strAbsPath = io.getOsSeparator();
}
// ------------------------------------------------------------------------------------------------
-// Destructor.
+// Destructor.
ObjFileImporter::~ObjFileImporter()
{
- delete m_pRootObject;
- m_pRootObject = NULL;
+ delete m_pRootObject;
+ m_pRootObject = NULL;
}
// ------------------------------------------------------------------------------------------------
-// Returns true, if file is an obj file.
+// Returns true, if file is an obj file.
bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const
{
- if(!checkSig) //Check File Extension
- {
- return SimpleExtensionCheck(pFile,"obj");
- }
- else //Check file Header
- {
- static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
- return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
- }
+ if(!checkSig) //Check File Extension
+ {
+ return SimpleExtensionCheck(pFile,"obj");
+ }
+ else //Check file Header
+ {
+ static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
+ return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9 );
+ }
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* ObjFileImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Obj-file import implementation
-void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
-{
- DefaultIOSystem io;
-
- // Read file into memory
- const std::string mode = "rb";
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
- if( !file.get() ) {
- throw DeadlyImportError( "Failed to open file " + pFile + "." );
+// Obj-file import implementation
+void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSystem* pIOHandler) {
+ // Read file into memory
+ static const std::string mode = "rb";
+ std::unique_ptr<IOStream> fileStream( pIOHandler->Open( file, mode));
+ if( !fileStream.get() ) {
+ throw DeadlyImportError( "Failed to open file " + file + "." );
}
- // Get the file-size and validate it, throwing an exception when fails
- size_t fileSize = file->FileSize();
+ // Get the file-size and validate it, throwing an exception when fails
+ size_t fileSize = fileStream->FileSize();
if( fileSize < ObjMinSize ) {
- throw DeadlyImportError( "OBJ-file is too small.");
+ throw DeadlyImportError( "OBJ-file is too small.");
+ }
+
+ // Allocate buffer and read file into it
+ TextFileToBuffer( fileStream.get(),m_Buffer);
+
+ // Get the model name
+ std::string modelName, folderName;
+ std::string::size_type pos = file.find_last_of( "\\/" );
+ if ( pos != std::string::npos ) {
+ modelName = file.substr(pos+1, file.size() - pos - 1);
+ folderName = file.substr( 0, pos );
+ if ( !folderName.empty() ) {
+ pIOHandler->PushDirectory( folderName );
+ }
+ } else {
+ modelName = file;
+ }
+
+ // This next stage takes ~ 1/3th of the total readFile task
+ // so should amount for 1/3th of the progress
+ // only update every 100KB or it'll be too slow
+ unsigned int progress = 0;
+ unsigned int progressCounter = 0;
+ const unsigned int updateProgressEveryBytes = 100 * 1024;
+ const unsigned int progressTotal = (3*m_Buffer.size()/updateProgressEveryBytes);
+ // process all '\'
+ std::vector<char> ::iterator iter = m_Buffer.begin();
+ while (iter != m_Buffer.end())
+ {
+ if (*iter == '\\')
+ {
+ // remove '\'
+ iter = m_Buffer.erase(iter);
+ // remove next character
+ while (*iter == '\r' || *iter == '\n')
+ iter = m_Buffer.erase(iter);
+ }
+ else
+ ++iter;
+
+ if (++progressCounter >= updateProgressEveryBytes)
+ {
+ m_progress->UpdateFileRead(++progress, progressTotal);
+ progressCounter = 0;
+ }
}
- // Allocate buffer and read file into it
- TextFileToBuffer(file.get(),m_Buffer);
-
- // Get the model name
- std::string strModelName;
- std::string::size_type pos = pFile.find_last_of( "\\/" );
- if ( pos != std::string::npos )
- {
- strModelName = pFile.substr(pos+1, pFile.size() - pos - 1);
- }
- else
- {
- strModelName = pFile;
- }
-
- // process all '\'
- std::vector<char> ::iterator iter = m_Buffer.begin();
- while (iter != m_Buffer.end())
- {
- if (*iter == '\\')
- {
- // remove '\'
- iter = m_Buffer.erase(iter);
- // remove next character
- while (*iter == '\r' || *iter == '\n')
- iter = m_Buffer.erase(iter);
- }
- else
- ++iter;
- }
-
- // parse the file into a temporary representation
- ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
-
- // And create the proper return structures out of it
- CreateDataFromImport(parser.GetModel(), pScene);
-
- // Clean up allocated storage for the next import
- m_Buffer.clear();
+ // 1/3rd progress
+ m_progress->UpdateFileRead(1, 3);
+
+ // parse the file into a temporary representation
+ ObjFileParser parser(m_Buffer, modelName, pIOHandler, m_progress, file);
+
+ // And create the proper return structures out of it
+ CreateDataFromImport(parser.GetModel(), pScene);
+
+ // Clean up allocated storage for the next import
+ m_Buffer.clear();
+
+ // Pop directory stack
+ if ( pIOHandler->StackSize() > 0 ) {
+ pIOHandler->PopDirectory();
+ }
}
// ------------------------------------------------------------------------------------------------
-// Create the data from parsed obj-file
+// Create the data from parsed obj-file
void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) {
if( 0L == pModel ) {
return;
}
-
- // Create the root node of the scene
- pScene->mRootNode = new aiNode;
- if ( !pModel->m_ModelName.empty() )
- {
- // Set the name of the scene
- pScene->mRootNode->mName.Set(pModel->m_ModelName);
- }
- else
- {
- // This is a fatal error, so break down the application
- ai_assert(false);
- }
-
- // Create nodes for the whole scene
- std::vector<aiMesh*> MeshArray;
- for (size_t index = 0; index < pModel->m_Objects.size(); index++)
- {
- createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
- }
-
- // Create mesh pointer buffer for this scene
- if (pScene->mNumMeshes > 0)
- {
- pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
- for (size_t index =0; index < MeshArray.size(); index++)
- {
- pScene->mMeshes [ index ] = MeshArray[ index ];
- }
- }
-
- // Create all materials
- createMaterials( pModel, pScene );
+
+ // Create the root node of the scene
+ pScene->mRootNode = new aiNode;
+ if ( !pModel->m_ModelName.empty() )
+ {
+ // Set the name of the scene
+ pScene->mRootNode->mName.Set(pModel->m_ModelName);
+ }
+ else
+ {
+ // This is a fatal error, so break down the application
+ ai_assert(false);
+ }
+
+ // Create nodes for the whole scene
+ std::vector<aiMesh*> MeshArray;
+ for (size_t index = 0; index < pModel->m_Objects.size(); index++)
+ {
+ createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
+ }
+
+ // Create mesh pointer buffer for this scene
+ if (pScene->mNumMeshes > 0)
+ {
+ pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
+ for (size_t index =0; index < MeshArray.size(); index++)
+ {
+ pScene->mMeshes[ index ] = MeshArray[ index ];
+ }
+ }
+
+ // Create all materials
+ createMaterials( pModel, pScene );
}
// ------------------------------------------------------------------------------------------------
-// Creates all nodes of the model
-aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject,
- aiNode *pParent, aiScene* pScene,
- std::vector<aiMesh*> &MeshArray )
+// Creates all nodes of the model
+aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject,
+ aiNode *pParent, aiScene* pScene,
+ std::vector<aiMesh*> &MeshArray )
{
- ai_assert( NULL != pModel );
+ ai_assert( NULL != pModel );
if( NULL == pObject ) {
return NULL;
}
-
- // Store older mesh size to be able to computes mesh offsets for new mesh instances
- const size_t oldMeshSize = MeshArray.size();
- aiNode *pNode = new aiNode;
-
- pNode->mName = pObject->m_strObjName;
-
- // If we have a parent node, store it
+
+ // Store older mesh size to be able to computes mesh offsets for new mesh instances
+ const size_t oldMeshSize = MeshArray.size();
+ aiNode *pNode = new aiNode;
+
+ pNode->mName = pObject->m_strObjName;
+
+ // If we have a parent node, store it
if( pParent != NULL ) {
appendChildToParentNode( pParent, pNode );
}
- for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
- {
- unsigned int meshId = pObject->m_Meshes[ i ];
- aiMesh *pMesh = new aiMesh;
- createTopology( pModel, pObject, meshId, pMesh );
- if ( pMesh->mNumVertices > 0 )
- {
- MeshArray.push_back( pMesh );
- }
- else
- {
- delete pMesh;
- }
- }
-
- // Create all nodes from the sub-objects stored in the current object
- if ( !pObject->m_SubObjects.empty() )
- {
- size_t numChilds = pObject->m_SubObjects.size();
- pNode->mNumChildren = static_cast<unsigned int>( numChilds );
- pNode->mChildren = new aiNode*[ numChilds ];
- pNode->mNumMeshes = 1;
- pNode->mMeshes = new unsigned int[ 1 ];
- }
-
- // Set mesh instances into scene- and node-instances
- const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
- if ( meshSizeDiff > 0 )
- {
- pNode->mMeshes = new unsigned int[ meshSizeDiff ];
- pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
- size_t index = 0;
- for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
- {
- pNode->mMeshes[ index ] = pScene->mNumMeshes;
- pScene->mNumMeshes++;
- index++;
- }
- }
-
- return pNode;
+ for ( size_t i=0; i< pObject->m_Meshes.size(); i++ )
+ {
+ unsigned int meshId = pObject->m_Meshes[ i ];
+ aiMesh *pMesh = createTopology( pModel, pObject, meshId );
+ if( pMesh && pMesh->mNumFaces > 0 ) {
+ MeshArray.push_back( pMesh );
+ }
+ }
+
+ // Create all nodes from the sub-objects stored in the current object
+ if ( !pObject->m_SubObjects.empty() )
+ {
+ size_t numChilds = pObject->m_SubObjects.size();
+ pNode->mNumChildren = static_cast<unsigned int>( numChilds );
+ pNode->mChildren = new aiNode*[ numChilds ];
+ pNode->mNumMeshes = 1;
+ pNode->mMeshes = new unsigned int[ 1 ];
+ }
+
+ // Set mesh instances into scene- and node-instances
+ const size_t meshSizeDiff = MeshArray.size()- oldMeshSize;
+ if ( meshSizeDiff > 0 )
+ {
+ pNode->mMeshes = new unsigned int[ meshSizeDiff ];
+ pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff );
+ size_t index = 0;
+ for (size_t i = oldMeshSize; i < MeshArray.size(); i++)
+ {
+ pNode->mMeshes[ index ] = pScene->mNumMeshes;
+ pScene->mNumMeshes++;
+ index++;
+ }
+ }
+
+ return pNode;
}
// ------------------------------------------------------------------------------------------------
-// Create topology data
-void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
- const ObjFile::Object* pData,
- unsigned int uiMeshIndex,
- aiMesh* pMesh )
+// Create topology data
+aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
+ unsigned int meshIndex )
{
- // Checking preconditions
- ai_assert( NULL != pModel );
+ // Checking preconditions
+ ai_assert( NULL != pModel );
+
if( NULL == pData ) {
- return;
+ return NULL;
}
- // Create faces
- ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
- ai_assert( NULL != pObjMesh );
-
- pMesh->mNumFaces = 0;
- for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
- {
- ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
-
- if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
- pMesh->mNumFaces += inp->m_pVertices->size() - 1;
- pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
- }
- else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
- pMesh->mNumFaces += inp->m_pVertices->size();
- pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
- } else {
- ++pMesh->mNumFaces;
- if (inp->m_pVertices->size() > 3) {
- pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- }
- else {
- pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- }
- }
- }
-
- unsigned int uiIdxCount = 0u;
- if ( pMesh->mNumFaces > 0 )
- {
- pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
- if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial )
- {
- pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
- }
-
- unsigned int outIndex = 0;
-
- // Copy all data from all stored meshes
- for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
- {
- ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
- if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
- for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
- aiFace& f = pMesh->mFaces[ outIndex++ ];
- uiIdxCount += f.mNumIndices = 2;
- f.mIndices = new unsigned int[2];
- }
- continue;
- }
- else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
- for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
- aiFace& f = pMesh->mFaces[ outIndex++ ];
- uiIdxCount += f.mNumIndices = 1;
- f.mIndices = new unsigned int[1];
- }
- continue;
- }
-
- aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
- const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
- uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
- if (pFace->mNumIndices > 0) {
- pFace->mIndices = new unsigned int[ uiNumIndices ];
- }
- }
- }
-
- // Create mesh vertices
- createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
+ // Create faces
+ ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ meshIndex ];
+ if( !pObjMesh ) {
+ return NULL;
+ }
+
+ if( pObjMesh->m_Faces.empty() ) {
+ return NULL;
+ }
+
+ aiMesh* pMesh = new aiMesh;
+ if( !pObjMesh->m_name.empty() ) {
+ pMesh->mName.Set( pObjMesh->m_name );
+ }
+
+ for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+ {
+ ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
+ ai_assert( NULL != inp );
+
+ if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+ pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ } else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+ pMesh->mNumFaces += inp->m_pVertices->size();
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ } else {
+ ++pMesh->mNumFaces;
+ if (inp->m_pVertices->size() > 3) {
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ } else {
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ }
+ }
+ }
+
+ unsigned int uiIdxCount( 0u );
+ if ( pMesh->mNumFaces > 0 ) {
+ pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
+ if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial ) {
+ pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
+ }
+
+ unsigned int outIndex( 0 );
+
+ // Copy all data from all stored meshes
+ for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
+ ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+ if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+ for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
+ aiFace& f = pMesh->mFaces[ outIndex++ ];
+ uiIdxCount += f.mNumIndices = 2;
+ f.mIndices = new unsigned int[2];
+ }
+ continue;
+ }
+ else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+ for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
+ aiFace& f = pMesh->mFaces[ outIndex++ ];
+ uiIdxCount += f.mNumIndices = 1;
+ f.mIndices = new unsigned int[1];
+ }
+ continue;
+ }
+
+ aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
+ const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
+ uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
+ if (pFace->mNumIndices > 0) {
+ pFace->mIndices = new unsigned int[ uiNumIndices ];
+ }
+ }
+ }
+
+ // Create mesh vertices
+ createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
+
+ return pMesh;
}
// ------------------------------------------------------------------------------------------------
-// Creates a vertex array
-void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
- const ObjFile::Object* pCurrentObject,
- unsigned int uiMeshIndex,
- aiMesh* pMesh,
- unsigned int uiIdxCount)
+// Creates a vertex array
+void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
+ const ObjFile::Object* pCurrentObject,
+ unsigned int uiMeshIndex,
+ aiMesh* pMesh,
+ unsigned int numIndices)
{
- // Checking preconditions
- ai_assert( NULL != pCurrentObject );
-
- // Break, if no faces are stored in object
- if ( pCurrentObject->m_Meshes.empty() )
- return;
-
- // Get current mesh
- ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
- if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
- return;
-
- // Copy vertices of this mesh instance
- pMesh->mNumVertices = uiIdxCount;
- pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
-
- // Allocate buffer for normal vectors
- if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
- pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
-
- // Allocate buffer for texture coordinates
- if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
- {
- pMesh->mNumUVComponents[ 0 ] = 2;
- pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
- }
-
- // Copy vertices, normals and textures into aiMesh instance
- unsigned int newIndex = 0, outIndex = 0;
- for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
- {
- // Get source face
- ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
-
- // Copy all index arrays
- for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
- {
- const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
- if ( vertex >= pModel->m_Vertices.size() )
- throw DeadlyImportError( "OBJ: vertex index out of range" );
-
- pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
-
- // Copy all normals
- if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
- {
- const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
- if ( normal >= pModel->m_Normals.size() )
- throw DeadlyImportError("OBJ: vertex normal index out of range");
-
- pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
- }
-
- // Copy all texture coordinates
- if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
- {
- const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
- ai_assert( tex < pModel->m_TextureCoord.size() );
-
- if ( tex >= pModel->m_TextureCoord.size() )
- throw DeadlyImportError("OBJ: texture coordinate index out of range");
-
- const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
+ // Checking preconditions
+ ai_assert( NULL != pCurrentObject );
+
+ // Break, if no faces are stored in object
+ if ( pCurrentObject->m_Meshes.empty() )
+ return;
+
+ // Get current mesh
+ ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
+ if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1)
+ return;
+
+ // Copy vertices of this mesh instance
+ pMesh->mNumVertices = numIndices;
+ if (pMesh->mNumVertices == 0) {
+ throw DeadlyImportError( "OBJ: no vertices" );
+ } else if (pMesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
+ throw DeadlyImportError( "OBJ: Too many vertices, would run out of memory" );
+ }
+ pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
+
+ // Allocate buffer for normal vectors
+ if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
+ pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
+
+ // Allocate buffer for vertex-color vectors
+ if ( !pModel->m_VertexColors.empty() )
+ pMesh->mColors[0] = new aiColor4D[ pMesh->mNumVertices ];
+
+ // Allocate buffer for texture coordinates
+ if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
+ {
+ pMesh->mNumUVComponents[ 0 ] = 2;
+ pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
+ }
+
+ // Copy vertices, normals and textures into aiMesh instance
+ unsigned int newIndex = 0, outIndex = 0;
+ for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
+ {
+ // Get source face
+ ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
+
+ // Copy all index arrays
+ for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
+ {
+ const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
+ if ( vertex >= pModel->m_Vertices.size() )
+ throw DeadlyImportError( "OBJ: vertex index out of range" );
+
+ pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
+
+ // Copy all normals
+ if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
+ {
+ const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
+ if ( normal >= pModel->m_Normals.size() )
+ throw DeadlyImportError("OBJ: vertex normal index out of range");
+
+ pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
+ }
+
+ // Copy all vertex colors
+ if ( !pModel->m_VertexColors.empty())
+ {
+ const aiVector3D color = pModel->m_VertexColors[ vertex ];
+ pMesh->mColors[0][ newIndex ] = aiColor4D(color.x, color.y, color.z, 1.0);
+ }
+
+ // Copy all texture coordinates
+ if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
+ {
+ const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
+ ai_assert( tex < pModel->m_TextureCoord.size() );
+
+ if ( tex >= pModel->m_TextureCoord.size() )
+ throw DeadlyImportError("OBJ: texture coordinate index out of range");
+
+ const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
- }
-
- ai_assert( pMesh->mNumVertices > newIndex );
-
- // Get destination face
- aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
-
- const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 );
- if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last)
- {
- pDestFace->mIndices[ outVertexIndex ] = newIndex;
- outVertexIndex++;
- }
-
- if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT)
- {
- outIndex++;
- outVertexIndex = 0;
- }
- else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE)
- {
- outVertexIndex = 0;
-
- if(!last)
- outIndex++;
-
- if (vertexIndex) {
- if(!last) {
- pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
- if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
- pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
- }
- if ( !pModel->m_TextureCoord.empty() ) {
- for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
- pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
- }
- }
- ++newIndex;
- }
-
- pDestFace[-1].mIndices[1] = newIndex;
- }
- }
- else if (last) {
- outIndex++;
- }
- ++newIndex;
- }
- }
+ }
+
+ if ( pMesh->mNumVertices <= newIndex ) {
+ throw DeadlyImportError("OBJ: bad vertex index");
+ }
+
+ // Get destination face
+ aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
+
+ const bool last = ( vertexIndex == pSourceFace->m_pVertices->size() - 1 );
+ if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last)
+ {
+ pDestFace->mIndices[ outVertexIndex ] = newIndex;
+ outVertexIndex++;
+ }
+
+ if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT)
+ {
+ outIndex++;
+ outVertexIndex = 0;
+ }
+ else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE)
+ {
+ outVertexIndex = 0;
+
+ if(!last)
+ outIndex++;
+
+ if (vertexIndex) {
+ if(!last) {
+ pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
+ if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
+ pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
+ }
+ if ( !pModel->m_TextureCoord.empty() ) {
+ for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
+ pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
+ }
+ }
+ ++newIndex;
+ }
+
+ pDestFace[-1].mIndices[1] = newIndex;
+ }
+ }
+ else if (last) {
+ outIndex++;
+ }
+ ++newIndex;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Counts all stored meshes
+// Counts all stored meshes
void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes)
{
- iNumMeshes = 0;
- if ( rObjects.empty() )
- return;
-
- iNumMeshes += static_cast<unsigned int>( rObjects.size() );
- for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
- it != rObjects.end();
- ++it)
- {
- if (!(*it)->m_SubObjects.empty())
- {
- countObjects((*it)->m_SubObjects, iNumMeshes);
- }
- }
+ iNumMeshes = 0;
+ if ( rObjects.empty() )
+ return;
+
+ iNumMeshes += static_cast<unsigned int>( rObjects.size() );
+ for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
+ it != rObjects.end();
+ ++it)
+ {
+ if (!(*it)->m_SubObjects.empty())
+ {
+ countObjects((*it)->m_SubObjects, iNumMeshes);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Add clamp mode property to material if necessary
+// Add clamp mode property to material if necessary
void ObjFileImporter::addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode)
{
- ai_assert( NULL != mat);
- mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
- mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
+ ai_assert( NULL != mat);
+ mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
+ mat->AddProperty<int>(&clampMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
}
// ------------------------------------------------------------------------------------------------
-// Creates the material
+// Creates the material
void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene )
{
- ai_assert( NULL != pScene );
- if ( NULL == pScene )
- return;
-
- const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
- pScene->mNumMaterials = 0;
- if ( pModel->m_MaterialLib.empty() ) {
- DefaultLogger::get()->debug("OBJ: no materials specified");
- return;
- }
-
- pScene->mMaterials = new aiMaterial*[ numMaterials ];
- for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
- {
- // Store material name
- std::map<std::string, ObjFile::Material*>::const_iterator it;
- it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
-
- // No material found, use the default material
- if ( pModel->m_MaterialMap.end() == it )
- continue;
-
- aiMaterial* mat = new aiMaterial;
- ObjFile::Material *pCurrentMaterial = (*it).second;
- mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
-
- // convert illumination model
- int sm = 0;
- switch (pCurrentMaterial->illumination_model)
- {
- case 0:
- sm = aiShadingMode_NoShading;
- break;
- case 1:
- sm = aiShadingMode_Gouraud;
- break;
- case 2:
- sm = aiShadingMode_Phong;
- break;
- default:
- sm = aiShadingMode_Gouraud;
- DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
- }
-
- mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
-
- // multiplying the specular exponent with 2 seems to yield better results
- pCurrentMaterial->shineness *= 4.f;
-
- // Adding material colors
- mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
- mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
- mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
- mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
- mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
- mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
-
- // Adding refraction index
- mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
-
- // Adding textures
- if ( 0 != pCurrentMaterial->texture.length )
- {
- mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureAmbient.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureEmissive.length )
- mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
-
- if ( 0 != pCurrentMaterial->textureSpecular.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureBump.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureNormal.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureDisp.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureOpacity.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
- }
- }
-
- if ( 0 != pCurrentMaterial->textureSpecularity.length )
- {
- mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
- if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
- {
- addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
- }
- }
-
- // Store material property info in material array in scene
- pScene->mMaterials[ pScene->mNumMaterials ] = mat;
- pScene->mNumMaterials++;
- }
-
- // Test number of created materials.
- ai_assert( pScene->mNumMaterials == numMaterials );
+ ai_assert( NULL != pScene );
+ if ( NULL == pScene )
+ return;
+
+ const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size();
+ pScene->mNumMaterials = 0;
+ if ( pModel->m_MaterialLib.empty() ) {
+ DefaultLogger::get()->debug("OBJ: no materials specified");
+ return;
+ }
+
+ pScene->mMaterials = new aiMaterial*[ numMaterials ];
+ for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ )
+ {
+ // Store material name
+ std::map<std::string, ObjFile::Material*>::const_iterator it;
+ it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] );
+
+ // No material found, use the default material
+ if ( pModel->m_MaterialMap.end() == it )
+ continue;
+
+ aiMaterial* mat = new aiMaterial;
+ ObjFile::Material *pCurrentMaterial = (*it).second;
+ mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME );
+
+ // convert illumination model
+ int sm = 0;
+ switch (pCurrentMaterial->illumination_model)
+ {
+ case 0:
+ sm = aiShadingMode_NoShading;
+ break;
+ case 1:
+ sm = aiShadingMode_Gouraud;
+ break;
+ case 2:
+ sm = aiShadingMode_Phong;
+ break;
+ default:
+ sm = aiShadingMode_Gouraud;
+ DefaultLogger::get()->error("OBJ: unexpected illumination model (0-2 recognized)");
+ }
+
+ mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL);
+
+ // multiplying the specular exponent with 2 seems to yield better results
+ pCurrentMaterial->shineness *= 4.f;
+
+ // Adding material colors
+ mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT );
+ mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
+ mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR );
+ mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE );
+ mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS );
+ mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY );
+
+ // Adding refraction index
+ mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI );
+
+ // Adding textures
+ if ( 0 != pCurrentMaterial->texture.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureAmbient.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_AMBIENT);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureEmissive.length )
+ mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0));
+
+ if ( 0 != pCurrentMaterial->textureSpecular.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_SPECULAR);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureBump.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_HEIGHT);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureNormal.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_NORMALS);
+ }
+ }
+
+ if( 0 != pCurrentMaterial->textureReflection[0].length )
+ {
+ ObjFile::Material::TextureType type = 0 != pCurrentMaterial->textureReflection[1].length ?
+ ObjFile::Material::TextureReflectionCubeTopType :
+ ObjFile::Material::TextureReflectionSphereType;
+
+ unsigned count = type == ObjFile::Material::TextureReflectionSphereType ? 1 : 6;
+ for( unsigned i = 0; i < count; i++ )
+ mat->AddProperty(&pCurrentMaterial->textureReflection[i], AI_MATKEY_TEXTURE_REFLECTION(i));
+
+ if(pCurrentMaterial->clamp[type])
+ //TODO addTextureMappingModeProperty should accept an index to handle clamp option for each
+ //texture of a cubemap
+ addTextureMappingModeProperty(mat, aiTextureType_REFLECTION);
+ }
+
+ if ( 0 != pCurrentMaterial->textureDisp.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) );
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureOpacity.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_OPACITY);
+ }
+ }
+
+ if ( 0 != pCurrentMaterial->textureSpecularity.length )
+ {
+ mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0));
+ if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType])
+ {
+ addTextureMappingModeProperty(mat, aiTextureType_SHININESS);
+ }
+ }
+
+ // Store material property info in material array in scene
+ pScene->mMaterials[ pScene->mNumMaterials ] = mat;
+ pScene->mNumMaterials++;
+ }
+
+ // Test number of created materials.
+ ai_assert( pScene->mNumMaterials == numMaterials );
}
// ------------------------------------------------------------------------------------------------
-// Appends this node to the parent node
+// Appends this node to the parent node
void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
{
- // Checking preconditions
- ai_assert( NULL != pParent );
- ai_assert( NULL != pChild );
-
- // Assign parent to child
- pChild->mParent = pParent;
-
- // If already children was assigned to the parent node, store them in a
- std::vector<aiNode*> temp;
- if (pParent->mChildren != NULL)
- {
- ai_assert( 0 != pParent->mNumChildren );
- for (size_t index = 0; index < pParent->mNumChildren; index++)
- {
- temp.push_back(pParent->mChildren [ index ] );
- }
- delete [] pParent->mChildren;
- }
-
- // Copy node instances into parent node
- pParent->mNumChildren++;
- pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
- for (size_t index = 0; index < pParent->mNumChildren-1; index++)
- {
- pParent->mChildren[ index ] = temp [ index ];
- }
- pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
+ // Checking preconditions
+ ai_assert( NULL != pParent );
+ ai_assert( NULL != pChild );
+
+ // Assign parent to child
+ pChild->mParent = pParent;
+
+ // If already children was assigned to the parent node, store them in a
+ std::vector<aiNode*> temp;
+ if (pParent->mChildren != NULL)
+ {
+ ai_assert( 0 != pParent->mNumChildren );
+ for (size_t index = 0; index < pParent->mNumChildren; index++)
+ {
+ temp.push_back(pParent->mChildren [ index ] );
+ }
+ delete [] pParent->mChildren;
+ }
+
+ // Copy node instances into parent node
+ pParent->mNumChildren++;
+ pParent->mChildren = new aiNode*[ pParent->mNumChildren ];
+ for (size_t index = 0; index < pParent->mNumChildren-1; index++)
+ {
+ pParent->mChildren[ index ] = temp [ index ];
+ }
+ pParent->mChildren[ pParent->mNumChildren-1 ] = pChild;
}
// ------------------------------------------------------------------------------------------------
-} // Namespace Assimp
+} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER
diff --git a/src/3rdparty/assimp/code/ObjFileImporter.h b/src/3rdparty/assimp/code/ObjFileImporter.h
index 7799612a4..b03d00b9b 100644
--- a/src/3rdparty/assimp/code/ObjFileImporter.h
+++ b/src/3rdparty/assimp/code/ObjFileImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define OBJ_FILE_IMPORTER_H_INC
#include "BaseImporter.h"
+#include <assimp/material.h>
#include <vector>
struct aiMesh;
@@ -58,63 +59,65 @@ struct Model;
}
// ------------------------------------------------------------------------------------------------
-/// \class ObjFileImporter
-/// \brief Imports a waveform obj file
+/// \class ObjFileImporter
+/// \brief Imports a waveform obj file
// ------------------------------------------------------------------------------------------------
class ObjFileImporter : public BaseImporter
-{
+{
public:
- /// \brief Default constructor
- ObjFileImporter();
+ /// \brief Default constructor
+ ObjFileImporter();
- /// \brief Destructor
- ~ObjFileImporter();
+ /// \brief Destructor
+ ~ObjFileImporter();
public:
- /// \brief Returns whether the class can handle the format of the given file.
- /// \remark See BaseImporter::CanRead() for details.
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+ /// \brief Returns whether the class can handle the format of the given file.
+ /// \remark See BaseImporter::CanRead() for details.
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
private:
- //! \brief Appends the supported extension.
- const aiImporterDesc* GetInfo () const;
-
- //! \brief File import implementation.
- void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-
- //! \brief Create the data from imported content.
- void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
-
- //! \brief Creates all nodes stored in imported content.
- aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
- aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
-
- //! \brief Creates topology data like faces and meshes for the geometry.
- void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData,
- unsigned int uiMeshIndex, aiMesh* pMesh);
-
- //! \brief Creates vertices from model.
- void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
- unsigned int uiMeshIndex, aiMesh* pMesh,unsigned int uiIdxCount);
-
- //! \brief Object counter helper method.
- void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
-
- //! \brief Material creation.
- void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
- void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
-
- //! \brief Appends a child node to a parent node and updates the data structures.
- void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
+ //! \brief Appends the supported extension.
+ const aiImporterDesc* GetInfo () const;
+
+ //! \brief File import implementation.
+ void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+
+ //! \brief Create the data from imported content.
+ void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
+
+ //! \brief Creates all nodes stored in imported content.
+ aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
+ aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
+
+ //! \brief Creates topology data like faces and meshes for the geometry.
+ aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
+ unsigned int uiMeshIndex );
+
+ //! \brief Creates vertices from model.
+ void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
+ unsigned int uiMeshIndex, aiMesh* pMesh, unsigned int numIndices );
+
+ //! \brief Object counter helper method.
+ void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);
+
+ //! \brief Material creation.
+ void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
+
+ /// @brief Adds special property for the used texture mapping mode of the model.
+ void addTextureMappingModeProperty(aiMaterial* mat, aiTextureType type, int clampMode = 1);
+
+ //! \brief Appends a child node to a parent node and updates the data structures.
+ void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
private:
- //! Data buffer
- std::vector<char> m_Buffer;
- //! Pointer to root object instance
- ObjFile::Object *m_pRootObject;
- //! Absolute pathname of model in file system
- std::string m_strAbsPath;
+ //! Data buffer
+ std::vector<char> m_Buffer;
+ //! Pointer to root object instance
+ ObjFile::Object *m_pRootObject;
+ //! Absolute pathname of model in file system
+ std::string m_strAbsPath;
};
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp b/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
index 7affd5139..2b3847bbb 100644
--- a/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
+++ b/src/3rdparty/assimp/code/ObjFileMtlImporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,322 +25,348 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
+#include <stdlib.h>
#include "ObjFileMtlImporter.h"
#include "ObjTools.h"
#include "ObjFileData.h"
#include "fast_atof.h"
+#include "ParsingUtils.h"
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
+
-namespace Assimp {
+namespace Assimp {
// Material specific token
-static const std::string DiffuseTexture = "map_kd";
-static const std::string AmbientTexture = "map_ka";
-static const std::string SpecularTexture = "map_ks";
+static const std::string DiffuseTexture = "map_Kd";
+static const std::string AmbientTexture = "map_Ka";
+static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d";
+static const std::string EmmissiveTexture = "map_emissive";
+static const std::string EmmissiveTexture_1 = "map_Ke";
static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "map_Bump";
static const std::string BumpTexture3 = "bump";
static const std::string NormalTexture = "map_Kn";
+static const std::string ReflectionTexture = "refl";
static const std::string DisplacementTexture = "disp";
static const std::string SpecularityTexture = "map_ns";
// texture option specific token
-static const std::string BlendUOption = "-blendu";
-static const std::string BlendVOption = "-blendv";
-static const std::string BoostOption = "-boost";
-static const std::string ModifyMapOption = "-mm";
-static const std::string OffsetOption = "-o";
-static const std::string ScaleOption = "-s";
-static const std::string TurbulenceOption = "-t";
-static const std::string ResolutionOption = "-texres";
-static const std::string ClampOption = "-clamp";
-static const std::string BumpOption = "-bm";
-static const std::string ChannelOption = "-imfchan";
-static const std::string TypeOption = "-type";
+static const std::string BlendUOption = "-blendu";
+static const std::string BlendVOption = "-blendv";
+static const std::string BoostOption = "-boost";
+static const std::string ModifyMapOption = "-mm";
+static const std::string OffsetOption = "-o";
+static const std::string ScaleOption = "-s";
+static const std::string TurbulenceOption = "-t";
+static const std::string ResolutionOption = "-texres";
+static const std::string ClampOption = "-clamp";
+static const std::string BumpOption = "-bm";
+static const std::string ChannelOption = "-imfchan";
+static const std::string TypeOption = "-type";
// -------------------------------------------------------------------
-// Constructor
-ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer,
- const std::string & /*strAbsPath*/,
- ObjFile::Model *pModel ) :
- m_DataIt( buffer.begin() ),
- m_DataItEnd( buffer.end() ),
- m_pModel( pModel ),
- m_uiLine( 0 )
+// Constructor
+ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer,
+ const std::string &,
+ ObjFile::Model *pModel ) :
+ m_DataIt( buffer.begin() ),
+ m_DataItEnd( buffer.end() ),
+ m_pModel( pModel ),
+ m_uiLine( 0 )
{
- ai_assert( NULL != m_pModel );
- if ( NULL == m_pModel->m_pDefaultMaterial )
- {
- m_pModel->m_pDefaultMaterial = new ObjFile::Material;
- m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" );
- }
- load();
+ ai_assert( NULL != m_pModel );
+ if ( NULL == m_pModel->m_pDefaultMaterial )
+ {
+ m_pModel->m_pDefaultMaterial = new ObjFile::Material;
+ m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" );
+ }
+ load();
}
// -------------------------------------------------------------------
-// Destructor
+// Destructor
ObjFileMtlImporter::~ObjFileMtlImporter()
{
- // empty
+ // empty
}
// -------------------------------------------------------------------
-// Private copy constructor
-ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & /* rOther */ )
+// Private copy constructor
+ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & )
{
- // empty
+ // empty
}
-
+
// -------------------------------------------------------------------
-// Private copy constructor
-ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & /*rOther */ )
+// Private copy constructor
+ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & )
{
- return *this;
+ return *this;
}
// -------------------------------------------------------------------
-// Loads the material description
+// Loads the material description
void ObjFileMtlImporter::load()
{
- if ( m_DataIt == m_DataItEnd )
- return;
-
- while ( m_DataIt != m_DataItEnd )
- {
- switch (*m_DataIt)
- {
- case 'K':
- {
- ++m_DataIt;
- if (*m_DataIt == 'a') // Ambient color
- {
- ++m_DataIt;
- getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient );
- }
- else if (*m_DataIt == 'd') // Diffuse color
- {
- ++m_DataIt;
- getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse );
- }
- else if (*m_DataIt == 's')
- {
- ++m_DataIt;
- getColorRGBA( &m_pModel->m_pCurrentMaterial->specular );
- }
- else if (*m_DataIt == 'e')
- {
- ++m_DataIt;
- getColorRGBA( &m_pModel->m_pCurrentMaterial->emissive );
- }
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
-
- case 'd': // Alpha value
- {
- ++m_DataIt;
- getFloatValue( m_pModel->m_pCurrentMaterial->alpha );
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
-
- case 'N': // Shineness
- {
- ++m_DataIt;
- switch(*m_DataIt)
- {
- case 's':
- ++m_DataIt;
- getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
- break;
- case 'i': //Index Of refraction
- ++m_DataIt;
- getFloatValue(m_pModel->m_pCurrentMaterial->ior);
- break;
- }
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- break;
- }
- break;
-
-
- case 'm': // Texture
- case 'b': // quick'n'dirty - for 'bump' sections
- {
- getTexture();
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
-
- case 'n': // New material name
- {
- createMaterial();
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
-
- case 'i': // Illumination model
- {
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model );
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
-
- default:
- {
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
- }
- }
+ if ( m_DataIt == m_DataItEnd )
+ return;
+
+ while ( m_DataIt != m_DataItEnd )
+ {
+ switch (*m_DataIt)
+ {
+ case 'k':
+ case 'K':
+ {
+ ++m_DataIt;
+ if (*m_DataIt == 'a') // Ambient color
+ {
+ ++m_DataIt;
+ getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient );
+ }
+ else if (*m_DataIt == 'd') // Diffuse color
+ {
+ ++m_DataIt;
+ getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse );
+ }
+ else if (*m_DataIt == 's')
+ {
+ ++m_DataIt;
+ getColorRGBA( &m_pModel->m_pCurrentMaterial->specular );
+ }
+ else if (*m_DataIt == 'e')
+ {
+ ++m_DataIt;
+ getColorRGBA( &m_pModel->m_pCurrentMaterial->emissive );
+ }
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+
+ case 'd':
+ {
+ if( *(m_DataIt+1) == 'i' && *( m_DataIt + 2 ) == 's' && *( m_DataIt + 3 ) == 'p' ) {
+ // A displacement map
+ getTexture();
+ } else {
+ // Alpha value
+ ++m_DataIt;
+ getFloatValue( m_pModel->m_pCurrentMaterial->alpha );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ }
+ break;
+
+ case 'N':
+ case 'n':
+ {
+ ++m_DataIt;
+ switch(*m_DataIt)
+ {
+ case 's': // Specular exponent
+ ++m_DataIt;
+ getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
+ break;
+ case 'i': // Index Of refraction
+ ++m_DataIt;
+ getFloatValue(m_pModel->m_pCurrentMaterial->ior);
+ break;
+ case 'e': // New material
+ createMaterial();
+ break;
+ }
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+
+ case 'm': // Texture
+ case 'b': // quick'n'dirty - for 'bump' sections
+ case 'r': // quick'n'dirty - for 'refl' sections
+ {
+ getTexture();
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+
+ case 'i': // Illumination model
+ {
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+
+ default:
+ {
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+ }
+ }
}
// -------------------------------------------------------------------
-// Loads a color definition
+// Loads a color definition
void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{
- ai_assert( NULL != pColor );
-
- float r, g, b;
- m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
- pColor->r = r;
-
- m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
- pColor->g = g;
-
- m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
- pColor->b = b;
+ ai_assert( NULL != pColor );
+
+ float r( 0.0f ), g( 0.0f ), b( 0.0f );
+ m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
+ pColor->r = r;
+
+ // we have to check if color is default 0 with only one token
+ if( !IsLineEnd( *m_DataIt ) ) {
+ m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
+ m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
+ }
+ pColor->g = g;
+ pColor->b = b;
}
// -------------------------------------------------------------------
-// Loads the kind of illumination model.
+// Loads the kind of illumination model.
void ObjFileMtlImporter::getIlluminationModel( int &illum_model )
{
- m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
- illum_model = atoi(m_buffer);
+ m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
+ illum_model = atoi(m_buffer);
}
// -------------------------------------------------------------------
-// Loads a single float value.
+// Loads a single float value.
void ObjFileMtlImporter::getFloatValue( float &value )
{
- m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
- value = (float) fast_atof(m_buffer);
+ m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE );
+ value = (float) fast_atof(m_buffer);
}
// -------------------------------------------------------------------
-// Creates a material from loaded data.
+// Creates a material from loaded data.
void ObjFileMtlImporter::createMaterial()
-{
- std::string line( "" );
- while ( !isNewLine( *m_DataIt ) ) {
- line += *m_DataIt;
- ++m_DataIt;
- }
-
- std::vector<std::string> token;
- const unsigned int numToken = tokenize<std::string>( line, token, " " );
- std::string name( "" );
- if ( numToken == 1 ) {
- name = AI_DEFAULT_MATERIAL_NAME;
- } else {
- name = token[ 1 ];
- }
-
- std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name );
- if ( m_pModel->m_MaterialMap.end() == it) {
- // New Material created
- m_pModel->m_pCurrentMaterial = new ObjFile::Material();
- m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
- m_pModel->m_MaterialLib.push_back( name );
- m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
- } else {
- // Use older material
- m_pModel->m_pCurrentMaterial = (*it).second;
- }
+{
+ std::string line( "" );
+ while( !IsLineEnd( *m_DataIt ) ) {
+ line += *m_DataIt;
+ ++m_DataIt;
+ }
+
+ std::vector<std::string> token;
+ const unsigned int numToken = tokenize<std::string>( line, token, " \t" );
+ std::string name( "" );
+ if ( numToken == 1 ) {
+ name = AI_DEFAULT_MATERIAL_NAME;
+ } else {
+ // skip newmtl and all following white spaces
+ std::size_t first_ws_pos = line.find_first_of(" \t");
+ std::size_t first_non_ws_pos = line.find_first_not_of(" \t", first_ws_pos);
+ if (first_non_ws_pos != std::string::npos) {
+ name = line.substr(first_non_ws_pos);
+ }
+ }
+
+ name = trim_whitespaces(name);
+
+ std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name );
+ if ( m_pModel->m_MaterialMap.end() == it) {
+ // New Material created
+ m_pModel->m_pCurrentMaterial = new ObjFile::Material();
+ m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
+ m_pModel->m_MaterialLib.push_back( name );
+ m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
+ } else {
+ // Use older material
+ m_pModel->m_pCurrentMaterial = (*it).second;
+ }
}
// -------------------------------------------------------------------
-// Gets a texture name from data.
+// Gets a texture name from data.
void ObjFileMtlImporter::getTexture() {
- aiString *out( NULL );
- int clampIndex = -1;
-
- const char *pPtr( &(*m_DataIt) );
- if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), DiffuseTexture.size() ) ) {
- // Diffuse texture
- out = & m_pModel->m_pCurrentMaterial->texture;
- clampIndex = ObjFile::Material::TextureDiffuseType;
- } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(),AmbientTexture.size() ) ) {
- // Ambient texture
- out = & m_pModel->m_pCurrentMaterial->textureAmbient;
- clampIndex = ObjFile::Material::TextureAmbientType;
- } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), SpecularTexture.size())) {
- // Specular texture
- out = & m_pModel->m_pCurrentMaterial->textureSpecular;
- clampIndex = ObjFile::Material::TextureSpecularType;
- } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), OpacityTexture.size() ) ) {
- // Opacity texture
- out = & m_pModel->m_pCurrentMaterial->textureOpacity;
- clampIndex = ObjFile::Material::TextureOpacityType;
- } else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) {
- // Ambient texture
- out = & m_pModel->m_pCurrentMaterial->textureAmbient;
- clampIndex = ObjFile::Material::TextureAmbientType;
- } else if (!ASSIMP_strincmp(&(*m_DataIt),"map_emissive",6)) {
- // Emissive texture
- out = & m_pModel->m_pCurrentMaterial->textureEmissive;
- clampIndex = ObjFile::Material::TextureEmissiveType;
- } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), BumpTexture1.size() ) ||
- !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), BumpTexture2.size() ) ||
- !ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), BumpTexture3.size() ) ) {
- // Bump texture
- out = & m_pModel->m_pCurrentMaterial->textureBump;
- clampIndex = ObjFile::Material::TextureBumpType;
- } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), NormalTexture.size())) {
- // Normal map
- out = & m_pModel->m_pCurrentMaterial->textureNormal;
- clampIndex = ObjFile::Material::TextureNormalType;
- } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) {
- // Displacement texture
- out = &m_pModel->m_pCurrentMaterial->textureDisp;
- clampIndex = ObjFile::Material::TextureDispType;
- } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(),SpecularityTexture.size() ) ) {
- // Specularity scaling (glossiness)
- out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
- clampIndex = ObjFile::Material::TextureSpecularityType;
- } else {
- DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type");
- return;
- }
-
- bool clamp = false;
- getTextureOption(clamp);
- m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp;
-
- std::string strTexture;
- m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, strTexture );
- out->Set( strTexture );
+ aiString *out( NULL );
+ int clampIndex = -1;
+
+ const char *pPtr( &(*m_DataIt) );
+ if ( !ASSIMP_strincmp( pPtr, DiffuseTexture.c_str(), DiffuseTexture.size() ) ) {
+ // Diffuse texture
+ out = & m_pModel->m_pCurrentMaterial->texture;
+ clampIndex = ObjFile::Material::TextureDiffuseType;
+ } else if ( !ASSIMP_strincmp( pPtr,AmbientTexture.c_str(),AmbientTexture.size() ) ) {
+ // Ambient texture
+ out = & m_pModel->m_pCurrentMaterial->textureAmbient;
+ clampIndex = ObjFile::Material::TextureAmbientType;
+ } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), SpecularTexture.size())) {
+ // Specular texture
+ out = & m_pModel->m_pCurrentMaterial->textureSpecular;
+ clampIndex = ObjFile::Material::TextureSpecularType;
+ } else if ( !ASSIMP_strincmp( pPtr, OpacityTexture.c_str(), OpacityTexture.size() ) ) {
+ // Opacity texture
+ out = & m_pModel->m_pCurrentMaterial->textureOpacity;
+ clampIndex = ObjFile::Material::TextureOpacityType;
+ } else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
+ // Emissive texture
+ out = & m_pModel->m_pCurrentMaterial->textureEmissive;
+ clampIndex = ObjFile::Material::TextureEmissiveType;
+ } else if ( !ASSIMP_strincmp( pPtr, EmmissiveTexture_1.c_str(), EmmissiveTexture_1.size() ) ) {
+ // Emissive texture
+ out = &m_pModel->m_pCurrentMaterial->textureEmissive;
+ clampIndex = ObjFile::Material::TextureEmissiveType;
+ } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), BumpTexture1.size() ) ||
+ !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), BumpTexture2.size() ) ||
+ !ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), BumpTexture3.size() ) ) {
+ // Bump texture
+ out = & m_pModel->m_pCurrentMaterial->textureBump;
+ clampIndex = ObjFile::Material::TextureBumpType;
+ } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), NormalTexture.size())) {
+ // Normal map
+ out = & m_pModel->m_pCurrentMaterial->textureNormal;
+ clampIndex = ObjFile::Material::TextureNormalType;
+ } else if(!ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), ReflectionTexture.size() ) ) {
+ // Reflection texture(s)
+ //Do nothing here
+ return;
+ } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), DisplacementTexture.size() ) ) {
+ // Displacement texture
+ out = &m_pModel->m_pCurrentMaterial->textureDisp;
+ clampIndex = ObjFile::Material::TextureDispType;
+ } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(),SpecularityTexture.size() ) ) {
+ // Specularity scaling (glossiness)
+ out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
+ clampIndex = ObjFile::Material::TextureSpecularityType;
+ } else {
+ DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type");
+ return;
+ }
+
+ bool clamp = false;
+ getTextureOption(clamp, clampIndex, out);
+ m_pModel->m_pCurrentMaterial->clamp[clampIndex] = clamp;
+
+ std::string texture;
+ m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, texture );
+ if ( NULL!=out ) {
+ out->Set( texture );
+ }
}
/* /////////////////////////////////////////////////////////////////////////////
@@ -349,65 +375,106 @@ void ObjFileMtlImporter::getTexture() {
* According to http://en.wikipedia.org/wiki/Wavefront_.obj_file#Texture_options
* Texture map statement can contains various texture option, for example:
*
- * map_Ka -o 1 1 1 some.png
- * map_Kd -clamp on some.png
+ * map_Ka -o 1 1 1 some.png
+ * map_Kd -clamp on some.png
*
- * So we need to parse and skip these options, and leave the last part which is
+ * So we need to parse and skip these options, and leave the last part which is
* the url of image, otherwise we will get a wrong url like "-clamp on some.png".
*
* Because aiMaterial supports clamp option, so we also want to return it
* /////////////////////////////////////////////////////////////////////////////
*/
-void ObjFileMtlImporter::getTextureOption(bool &clamp)
-{
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
-
- //If there is any more texture option
- while (!isEndOfBuffer(m_DataIt, m_DataItEnd) && *m_DataIt == '-')
- {
- const char *pPtr( &(*m_DataIt) );
- //skip option key and value
- int skipToken = 1;
-
- if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), ClampOption.size()))
- {
- DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- char value[3];
- CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value));
- if (!ASSIMP_strincmp(value, "on", 2))
- {
- clamp = true;
- }
-
- skipToken = 2;
- }
- else if ( !ASSIMP_strincmp(pPtr, BlendUOption.c_str(), BlendUOption.size())
- || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), BlendVOption.size())
- || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), BoostOption.size())
- || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), ResolutionOption.size())
- || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), BumpOption.size())
- || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), ChannelOption.size())
- || !ASSIMP_strincmp(pPtr, TypeOption.c_str(), TypeOption.size()) )
- {
- skipToken = 2;
- }
- else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), ModifyMapOption.size()))
- {
- skipToken = 3;
- }
- else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), OffsetOption.size())
- || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), ScaleOption.size())
- || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), TurbulenceOption.size())
- )
- {
- skipToken = 4;
- }
-
- for (int i = 0; i < skipToken; ++i)
- {
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- }
- }
+void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString *&out) {
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+
+ // If there is any more texture option
+ while (!isEndOfBuffer(m_DataIt, m_DataItEnd) && *m_DataIt == '-')
+ {
+ const char *pPtr( &(*m_DataIt) );
+ //skip option key and value
+ int skipToken = 1;
+
+ if (!ASSIMP_strincmp(pPtr, ClampOption.c_str(), ClampOption.size()))
+ {
+ DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ char value[3];
+ CopyNextWord(it, m_DataItEnd, value, sizeof(value) / sizeof(*value));
+ if (!ASSIMP_strincmp(value, "on", 2))
+ {
+ clamp = true;
+ }
+
+ skipToken = 2;
+ }
+ else if( !ASSIMP_strincmp( pPtr, TypeOption.c_str(), TypeOption.size() ) )
+ {
+ DataArrayIt it = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
+ char value[ 12 ];
+ CopyNextWord( it, m_DataItEnd, value, sizeof( value ) / sizeof( *value ) );
+ if( !ASSIMP_strincmp( value, "cube_top", 8 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeTopType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
+ }
+ else if( !ASSIMP_strincmp( value, "cube_bottom", 11 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeBottomType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[1];
+ }
+ else if( !ASSIMP_strincmp( value, "cube_front", 10 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeFrontType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[2];
+ }
+ else if( !ASSIMP_strincmp( value, "cube_back", 9 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeBackType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[3];
+ }
+ else if( !ASSIMP_strincmp( value, "cube_left", 9 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeLeftType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[4];
+ }
+ else if( !ASSIMP_strincmp( value, "cube_right", 10 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionCubeRightType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[5];
+ }
+ else if( !ASSIMP_strincmp( value, "sphere", 6 ) )
+ {
+ clampIndex = ObjFile::Material::TextureReflectionSphereType;
+ out = &m_pModel->m_pCurrentMaterial->textureReflection[0];
+ }
+
+ skipToken = 2;
+ }
+ else if (!ASSIMP_strincmp(pPtr, BlendUOption.c_str(), BlendUOption.size())
+ || !ASSIMP_strincmp(pPtr, BlendVOption.c_str(), BlendVOption.size())
+ || !ASSIMP_strincmp(pPtr, BoostOption.c_str(), BoostOption.size())
+ || !ASSIMP_strincmp(pPtr, ResolutionOption.c_str(), ResolutionOption.size())
+ || !ASSIMP_strincmp(pPtr, BumpOption.c_str(), BumpOption.size())
+ || !ASSIMP_strincmp(pPtr, ChannelOption.c_str(), ChannelOption.size()))
+ {
+ skipToken = 2;
+ }
+ else if (!ASSIMP_strincmp(pPtr, ModifyMapOption.c_str(), ModifyMapOption.size()))
+ {
+ skipToken = 3;
+ }
+ else if ( !ASSIMP_strincmp(pPtr, OffsetOption.c_str(), OffsetOption.size())
+ || !ASSIMP_strincmp(pPtr, ScaleOption.c_str(), ScaleOption.size())
+ || !ASSIMP_strincmp(pPtr, TurbulenceOption.c_str(), TurbulenceOption.size())
+ )
+ {
+ skipToken = 4;
+ }
+
+ for (int i = 0; i < skipToken; ++i)
+ {
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ }
+ }
}
// -------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/ObjFileMtlImporter.h b/src/3rdparty/assimp/code/ObjFileMtlImporter.h
index 207c56063..f2c1ba820 100644
--- a/src/3rdparty/assimp/code/ObjFileMtlImporter.h
+++ b/src/3rdparty/assimp/code/ObjFileMtlImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------*/
@@ -43,70 +43,68 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
struct aiColor3D;
+struct aiString;
-namespace Assimp
-{
-
-namespace ObjFile
-{
-struct Model;
-struct Material;
+namespace Assimp {
+namespace ObjFile {
+ struct Model;
+ struct Material;
}
/**
- * @class ObjFileMtlImporter
- * @brief Loads the material description from a mtl file.
+ * @class ObjFileMtlImporter
+ * @brief Loads the material description from a mtl file.
*/
class ObjFileMtlImporter
{
public:
- static const size_t BUFFERSIZE = 2048;
- typedef std::vector<char> DataArray;
- typedef std::vector<char>::iterator DataArrayIt;
- typedef std::vector<char>::const_iterator ConstDataArrayIt;
+ static const size_t BUFFERSIZE = 2048;
+ typedef std::vector<char> DataArray;
+ typedef std::vector<char>::iterator DataArrayIt;
+ typedef std::vector<char>::const_iterator ConstDataArrayIt;
public:
- //! \brief Default constructor
- ObjFileMtlImporter( std::vector<char> &buffer, const std::string &strAbsPath,
- ObjFile::Model *pModel );
-
- //! \brief DEstructor
- ~ObjFileMtlImporter();
+ //! \brief Default constructor
+ ObjFileMtlImporter( std::vector<char> &buffer, const std::string &strAbsPath,
+ ObjFile::Model *pModel );
+
+ //! \brief DEstructor
+ ~ObjFileMtlImporter();
private:
- /// Copy constructor, empty.
- ObjFileMtlImporter(const ObjFileMtlImporter &rOther);
- /// \brief Assignment operator, returns only a reference of this instance.
- ObjFileMtlImporter &operator = (const ObjFileMtlImporter &rOther);
- /// Load the whole material description
- void load();
- /// Get color data.
- void getColorRGBA( aiColor3D *pColor);
- /// Get illumination model from loaded data
- void getIlluminationModel( int &illum_model );
- /// Gets a float value from data.
- void getFloatValue( float &value );
- /// Creates a new material from loaded data.
- void createMaterial();
- /// Get texture name from loaded data.
- void getTexture();
- void getTextureOption(bool &clamp);
+ /// Copy constructor, empty.
+ ObjFileMtlImporter(const ObjFileMtlImporter &rOther);
+ /// \brief Assignment operator, returns only a reference of this instance.
+ ObjFileMtlImporter &operator = (const ObjFileMtlImporter &rOther);
+ /// Load the whole material description
+ void load();
+ /// Get color data.
+ void getColorRGBA( aiColor3D *pColor);
+ /// Get illumination model from loaded data
+ void getIlluminationModel( int &illum_model );
+ /// Gets a float value from data.
+ void getFloatValue( float &value );
+ /// Creates a new material from loaded data.
+ void createMaterial();
+ /// Get texture name from loaded data.
+ void getTexture();
+ void getTextureOption(bool &clamp, int &clampIndex, aiString *&out);
private:
- //! Absolute pathname
- std::string m_strAbsPath;
- //! Data iterator showing to the current position in data buffer
- DataArrayIt m_DataIt;
- //! Data iterator to end of buffer
- DataArrayIt m_DataItEnd;
- //! USed model instance
- ObjFile::Model *m_pModel;
- //! Current line in file
- unsigned int m_uiLine;
- //! Helper buffer
- char m_buffer[BUFFERSIZE];
+ //! Absolute pathname
+ std::string m_strAbsPath;
+ //! Data iterator showing to the current position in data buffer
+ DataArrayIt m_DataIt;
+ //! Data iterator to end of buffer
+ DataArrayIt m_DataItEnd;
+ //! USed model instance
+ ObjFile::Model *m_pModel;
+ //! Current line in file
+ unsigned int m_uiLine;
+ //! Helper buffer
+ char m_buffer[BUFFERSIZE];
};
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/ObjFileParser.cpp b/src/3rdparty/assimp/code/ObjFileParser.cpp
index 4ffd86a9b..79bc299bc 100644
--- a/src/3rdparty/assimp/code/ObjFileParser.cpp
+++ b/src/3rdparty/assimp/code/ObjFileParser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,21 +25,21 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "ObjFileParser.h"
@@ -47,712 +47,810 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ObjTools.h"
#include "ObjFileData.h"
#include "ParsingUtils.h"
-#include "../include/assimp/types.h"
#include "DefaultIOSystem.h"
+#include "BaseImporter.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/material.h>
+#include <assimp/Importer.hpp>
+#include <cstdlib>
+
namespace Assimp {
-const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
+const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
// -------------------------------------------------------------------
-// Constructor with loaded data and directories.
-ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) :
- m_DataIt(Data.begin()),
- m_DataItEnd(Data.end()),
- m_pModel(NULL),
- m_uiLine(0),
- m_pIO( io )
+// Constructor with loaded data and directories.
+ObjFileParser::ObjFileParser(std::vector<char> &data, const std::string &modelName, IOSystem *io, ProgressHandler* progress, const std::string &originalObjFileName) :
+ m_DataIt(data.begin()),
+ m_DataItEnd(data.end()),
+ m_pModel(NULL),
+ m_uiLine(0),
+ m_pIO( io ),
+ m_progress(progress),
+ m_originalObjFileName(originalObjFileName)
{
- std::fill_n(m_buffer,BUFFERSIZE,0);
+ std::fill_n(m_buffer,Buffersize,0);
+
+ // Create the model instance to store all the data
+ m_pModel = new ObjFile::Model();
+ m_pModel->m_ModelName = modelName;
- // Create the model instance to store all the data
- m_pModel = new ObjFile::Model();
- m_pModel->m_ModelName = strModelName;
-
// create default material and store it
- m_pModel->m_pDefaultMaterial = new ObjFile::Material();
- m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
+ m_pModel->m_pDefaultMaterial = new ObjFile::Material;
+ m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
- m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
-
- // Start parsing the file
- parseFile();
+ m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
+
+ // Start parsing the file
+ parseFile();
}
// -------------------------------------------------------------------
-// Destructor
+// Destructor
ObjFileParser::~ObjFileParser()
{
- delete m_pModel;
- m_pModel = NULL;
+ delete m_pModel;
+ m_pModel = NULL;
}
// -------------------------------------------------------------------
-// Returns a pointer to the model instance.
+// Returns a pointer to the model instance.
ObjFile::Model *ObjFileParser::GetModel() const
{
- return m_pModel;
+ return m_pModel;
}
// -------------------------------------------------------------------
-// File parsing method.
+// File parsing method.
void ObjFileParser::parseFile()
{
- if (m_DataIt == m_DataItEnd)
- return;
-
- while (m_DataIt != m_DataItEnd)
- {
- switch (*m_DataIt)
- {
- case 'v': // Parse a vertex texture coordinate
- {
- ++m_DataIt;
- if (*m_DataIt == ' ' || *m_DataIt == '\t') {
- // read in vertex definition
- getVector3(m_pModel->m_Vertices);
- } else if (*m_DataIt == 't') {
- // read in texture coordinate ( 2D or 3D )
+ if (m_DataIt == m_DataItEnd)
+ return;
+
+ // only update every 100KB or it'll be too slow
+ const unsigned int updateProgressEveryBytes = 100 * 1024;
+ unsigned int progressCounter = 0;
+ const unsigned int bytesToProcess = std::distance(m_DataIt, m_DataItEnd);
+ const unsigned int progressTotal = 3 * bytesToProcess;
+ const unsigned int progressOffset = bytesToProcess;
+ unsigned int processed = 0;
+
+ DataArrayIt lastDataIt = m_DataIt;
+
+ while (m_DataIt != m_DataItEnd)
+ {
+ // Handle progress reporting
+ processed += std::distance(lastDataIt, m_DataIt);
+ lastDataIt = m_DataIt;
+ if (processed > (progressCounter * updateProgressEveryBytes))
+ {
+ progressCounter++;
+ m_progress->UpdateFileRead(progressOffset + processed*2, progressTotal);
+ }
+
+ // parse line
+ switch (*m_DataIt)
+ {
+ case 'v': // Parse a vertex texture coordinate
+ {
+ ++m_DataIt;
+ if (*m_DataIt == ' ' || *m_DataIt == '\t') {
+ size_t numComponents = getNumComponentsInLine();
+ if (numComponents == 3) {
+ // read in vertex definition
+ getVector3(m_pModel->m_Vertices);
+ } else if (numComponents == 6) {
+ // read vertex and vertex-color
+ getTwoVectors3(m_pModel->m_Vertices, m_pModel->m_VertexColors);
+ }
+ } else if (*m_DataIt == 't') {
+ // read in texture coordinate ( 2D or 3D )
+ ++m_DataIt;
+ getVector( m_pModel->m_TextureCoord );
+ } else if (*m_DataIt == 'n') {
+ // Read in normal vector definition
++m_DataIt;
- getVector( m_pModel->m_TextureCoord );
- } else if (*m_DataIt == 'n') {
- // Read in normal vector definition
- ++m_DataIt;
- getVector3( m_pModel->m_Normals );
- }
- }
- break;
-
- case 'p': // Parse a face, line or point statement
- case 'l':
- case 'f':
- {
- getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l'
- ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
- }
- break;
-
- case '#': // Parse a comment
- {
- getComment();
- }
- break;
-
- case 'u': // Parse a material desc. setter
- {
- getMaterialDesc();
- }
- break;
-
- case 'm': // Parse a material library or merging group ('mg')
- {
- if (*(m_DataIt + 1) == 'g')
- getGroupNumberAndResolution();
- else
- getMaterialLib();
- }
- break;
-
- case 'g': // Parse group name
- {
- getGroupName();
- }
- break;
-
- case 's': // Parse group number
- {
- getGroupNumber();
- }
- break;
-
- case 'o': // Parse object name
- {
- getObjectName();
- }
- break;
-
- default:
- {
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- }
- break;
- }
- }
+ getVector3( m_pModel->m_Normals );
+ }
+ }
+ break;
+
+ case 'p': // Parse a face, line or point statement
+ case 'l':
+ case 'f':
+ {
+ getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l'
+ ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
+ }
+ break;
+
+ case '#': // Parse a comment
+ {
+ getComment();
+ }
+ break;
+
+ case 'u': // Parse a material desc. setter
+ {
+ getMaterialDesc();
+ }
+ break;
+
+ case 'm': // Parse a material library or merging group ('mg')
+ {
+ if (*(m_DataIt + 1) == 'g')
+ getGroupNumberAndResolution();
+ else
+ getMaterialLib();
+ }
+ break;
+
+ case 'g': // Parse group name
+ {
+ getGroupName();
+ }
+ break;
+
+ case 's': // Parse group number
+ {
+ getGroupNumber();
+ }
+ break;
+
+ case 'o': // Parse object name
+ {
+ getObjectName();
+ }
+ break;
+
+ default:
+ {
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ }
+ break;
+ }
+ }
}
// -------------------------------------------------------------------
-// Copy the next word in a temporary buffer
+// Copy the next word in a temporary buffer
void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
{
- size_t index = 0;
- m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
- while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
- {
- pBuffer[index] = *m_DataIt;
- index++;
- if (index == length-1)
- break;
- ++m_DataIt;
- }
-
- ai_assert(index < length);
- pBuffer[index] = '\0';
+ size_t index = 0;
+ m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+ while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
+ pBuffer[index] = *m_DataIt;
+ index++;
+ if( index == length - 1 ) {
+ break;
+ }
+ ++m_DataIt;
+ }
+
+ ai_assert(index < length);
+ pBuffer[index] = '\0';
}
// -------------------------------------------------------------------
// Copy the next line into a temporary buffer
void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
{
- size_t index = 0u;
-
- // some OBJ files have line continuations using \ (such as in C++ et al)
- bool continuation = false;
- for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt)
- {
- const char c = *m_DataIt;
- if (c == '\\') {
- continuation = true;
- continue;
- }
-
- if (c == '\n' || c == '\r') {
- if(continuation) {
- pBuffer[ index++ ] = ' ';
- continue;
- }
- break;
- }
-
- continuation = false;
- pBuffer[ index++ ] = c;
- }
- ai_assert(index < length);
- pBuffer[ index ] = '\0';
+ size_t index = 0u;
+
+ // some OBJ files have line continuations using \ (such as in C++ et al)
+ bool continuation = false;
+ for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt)
+ {
+ const char c = *m_DataIt;
+ if (c == '\\') {
+ continuation = true;
+ continue;
+ }
+
+ if (c == '\n' || c == '\r') {
+ if(continuation) {
+ pBuffer[ index++ ] = ' ';
+ continue;
+ }
+ break;
+ }
+
+ continuation = false;
+ pBuffer[ index++ ] = c;
+ }
+ ai_assert(index < length);
+ pBuffer[ index ] = '\0';
}
-// -------------------------------------------------------------------
-void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
+size_t ObjFileParser::getNumComponentsInLine() {
size_t numComponents( 0 );
- DataArrayIt tmp( m_DataIt );
+ const char* tmp( &m_DataIt[0] );
while( !IsLineEnd( *tmp ) ) {
- if( *tmp == ' ' ) {
- ++numComponents;
+ if ( !SkipSpaces( &tmp ) ) {
+ break;
}
- tmp++;
+ SkipToken( tmp );
+ ++numComponents;
}
+ return numComponents;
+}
+
+// -------------------------------------------------------------------
+void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
+ size_t numComponents = getNumComponentsInLine();
float x, y, z;
if( 2 == numComponents ) {
- copyNextWord( m_buffer, BUFFERSIZE );
+ copyNextWord( m_buffer, Buffersize );
x = ( float ) fast_atof( m_buffer );
- copyNextWord( m_buffer, BUFFERSIZE );
+ copyNextWord( m_buffer, Buffersize );
y = ( float ) fast_atof( m_buffer );
z = 0.0;
} else if( 3 == numComponents ) {
- copyNextWord( m_buffer, BUFFERSIZE );
+ copyNextWord( m_buffer, Buffersize );
x = ( float ) fast_atof( m_buffer );
- copyNextWord( m_buffer, BUFFERSIZE );
+ copyNextWord( m_buffer, Buffersize );
y = ( float ) fast_atof( m_buffer );
- copyNextWord( m_buffer, BUFFERSIZE );
+ copyNextWord( m_buffer, Buffersize );
z = ( float ) fast_atof( m_buffer );
} else {
- ai_assert( !"Invalid number of components" );
+ throw DeadlyImportError( "OBJ: Invalid number of components" );
}
point3d_array.push_back( aiVector3D( x, y, z ) );
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Get values for a new 3D vector instance
-void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
- float x, y, z;
- copyNextWord(m_buffer, BUFFERSIZE);
- x = (float) fast_atof(m_buffer);
-
- copyNextWord(m_buffer, BUFFERSIZE);
- y = (float) fast_atof(m_buffer);
-
- copyNextWord( m_buffer, BUFFERSIZE );
+// Get values for a new 3D vector instance
+void ObjFileParser::getVector3( std::vector<aiVector3D> &point3d_array ) {
+ float x, y, z;
+ copyNextWord(m_buffer, Buffersize);
+ x = (float) fast_atof(m_buffer);
+
+ copyNextWord(m_buffer, Buffersize);
+ y = (float) fast_atof(m_buffer);
+
+ copyNextWord( m_buffer, Buffersize );
+ z = ( float ) fast_atof( m_buffer );
+
+ point3d_array.push_back( aiVector3D( x, y, z ) );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+}
+
+// -------------------------------------------------------------------
+// Get values for two 3D vectors on the same line
+void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) {
+ float x, y, z;
+ copyNextWord(m_buffer, Buffersize);
+ x = (float) fast_atof(m_buffer);
+
+ copyNextWord(m_buffer, Buffersize);
+ y = (float) fast_atof(m_buffer);
+
+ copyNextWord( m_buffer, Buffersize );
z = ( float ) fast_atof( m_buffer );
- point3d_array.push_back( aiVector3D( x, y, z ) );
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ point3d_array_a.push_back( aiVector3D( x, y, z ) );
+
+ copyNextWord(m_buffer, Buffersize);
+ x = (float) fast_atof(m_buffer);
+
+ copyNextWord(m_buffer, Buffersize);
+ y = (float) fast_atof(m_buffer);
+
+ copyNextWord( m_buffer, Buffersize );
+ z = ( float ) fast_atof( m_buffer );
+
+ point3d_array_b.push_back( aiVector3D( x, y, z ) );
+
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Get values for a new 2D vector instance
+// Get values for a new 2D vector instance
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
- float x, y;
- copyNextWord(m_buffer, BUFFERSIZE);
- x = (float) fast_atof(m_buffer);
-
- copyNextWord(m_buffer, BUFFERSIZE);
- y = (float) fast_atof(m_buffer);
+ float x, y;
+ copyNextWord(m_buffer, Buffersize);
+ x = (float) fast_atof(m_buffer);
- point2d_array.push_back(aiVector2D(x, y));
+ copyNextWord(m_buffer, Buffersize);
+ y = (float) fast_atof(m_buffer);
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ point2d_array.push_back(aiVector2D(x, y));
+
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
+static const std::string DefaultObjName = "defaultobject";
+
// -------------------------------------------------------------------
-// Get values for a new face instance
-void ObjFileParser::getFace(aiPrimitiveType type)
-{
- copyNextLine(m_buffer, BUFFERSIZE);
- if (m_DataIt == m_DataItEnd)
- return;
-
- char *pPtr = m_buffer;
- char *pEnd = &pPtr[BUFFERSIZE];
- pPtr = getNextToken<char*>(pPtr, pEnd);
- if (pPtr == pEnd || *pPtr == '\0')
- return;
-
- std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
- std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
- std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
- bool hasNormal = false;
-
- const int vSize = m_pModel->m_Vertices.size();
- const int vtSize = m_pModel->m_TextureCoord.size();
- const int vnSize = m_pModel->m_Normals.size();
-
- const bool vt = (!m_pModel->m_TextureCoord.empty());
- const bool vn = (!m_pModel->m_Normals.empty());
- int iStep = 0, iPos = 0;
- while (pPtr != pEnd)
- {
- iStep = 1;
-
- if (IsLineEnd(*pPtr))
- break;
-
- if (*pPtr=='/' )
- {
- if (type == aiPrimitiveType_POINT) {
- DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
- }
- if (iPos == 0)
- {
- //if there are no texture coordinates in the file, but normals
- if (!vt && vn) {
- iPos = 1;
- iStep++;
- }
- }
- iPos++;
- }
- else if ( isSeparator(*pPtr) )
- {
- iPos = 0;
- }
- else
- {
- //OBJ USES 1 Base ARRAYS!!!!
- const int iVal = atoi( pPtr );
-
- // increment iStep position based off of the sign and # of digits
- int tmp = iVal;
- if (iVal < 0)
- ++iStep;
- while ( ( tmp = tmp / 10 )!=0 )
- ++iStep;
-
- if ( iVal > 0 )
- {
- // Store parsed index
- if ( 0 == iPos )
- {
- pIndices->push_back( iVal-1 );
- }
- else if ( 1 == iPos )
- {
- pTexID->push_back( iVal-1 );
- }
- else if ( 2 == iPos )
- {
- pNormalID->push_back( iVal-1 );
- hasNormal = true;
- }
- else
- {
- reportErrorTokenInFace();
- }
- }
- else if ( iVal < 0 )
- {
- // Store relatively index
- if ( 0 == iPos )
- {
- pIndices->push_back( vSize + iVal );
- }
- else if ( 1 == iPos )
- {
- pTexID->push_back( vtSize + iVal );
- }
- else if ( 2 == iPos )
- {
- pNormalID->push_back( vnSize + iVal );
- hasNormal = true;
- }
- else
- {
- reportErrorTokenInFace();
- }
- }
- }
- pPtr += iStep;
- }
-
- if ( pIndices->empty() )
- {
- DefaultLogger::get()->error("Obj: Ignoring empty face");
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- return;
- }
-
- ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
-
- // Set active material, if one set
- if (NULL != m_pModel->m_pCurrentMaterial)
- face->m_pMaterial = m_pModel->m_pCurrentMaterial;
- else
- face->m_pMaterial = m_pModel->m_pDefaultMaterial;
-
- // Create a default object, if nothing is there
- if ( NULL == m_pModel->m_pCurrent )
- createObject( "defaultobject" );
-
- // Assign face to mesh
- if ( NULL == m_pModel->m_pCurrentMesh )
- {
- createMesh();
- }
-
- // Store the face
- m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
- m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
- m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size();
- if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal )
- {
- m_pModel->m_pCurrentMesh->m_hasNormals = true;
- }
- // Skip the rest of the line
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+// Get values for a new face instance
+void ObjFileParser::getFace(aiPrimitiveType type) {
+ copyNextLine(m_buffer, Buffersize);
+ char *pPtr = m_buffer;
+ char *pEnd = &pPtr[Buffersize];
+ pPtr = getNextToken<char*>(pPtr, pEnd);
+ if ( pPtr == pEnd || *pPtr == '\0' ) {
+ return;
+ }
+
+ std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
+ std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
+ std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
+ bool hasNormal = false;
+
+ const int vSize = m_pModel->m_Vertices.size();
+ const int vtSize = m_pModel->m_TextureCoord.size();
+ const int vnSize = m_pModel->m_Normals.size();
+
+ const bool vt = (!m_pModel->m_TextureCoord.empty());
+ const bool vn = (!m_pModel->m_Normals.empty());
+ int iStep = 0, iPos = 0;
+ while (pPtr != pEnd) {
+ iStep = 1;
+
+ if ( IsLineEnd( *pPtr ) ) {
+ break;
+ }
+
+ if (*pPtr=='/' ) {
+ if (type == aiPrimitiveType_POINT) {
+ DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
+ }
+ if (iPos == 0) {
+ //if there are no texture coordinates in the file, but normals
+ if (!vt && vn) {
+ iPos = 1;
+ iStep++;
+ }
+ }
+ iPos++;
+ } else if( IsSpaceOrNewLine( *pPtr ) ) {
+ iPos = 0;
+ } else {
+ //OBJ USES 1 Base ARRAYS!!!!
+ const int iVal( ::atoi( pPtr ) );
+
+ // increment iStep position based off of the sign and # of digits
+ int tmp = iVal;
+ if ( iVal < 0 ) {
+ ++iStep;
+ }
+ while ( ( tmp = tmp / 10 ) != 0 ) {
+ ++iStep;
+ }
+
+ if ( iVal > 0 )
+ {
+ // Store parsed index
+ if ( 0 == iPos )
+ {
+ pIndices->push_back( iVal-1 );
+ }
+ else if ( 1 == iPos )
+ {
+ pTexID->push_back( iVal-1 );
+ }
+ else if ( 2 == iPos )
+ {
+ pNormalID->push_back( iVal-1 );
+ hasNormal = true;
+ }
+ else
+ {
+ reportErrorTokenInFace();
+ }
+ }
+ else if ( iVal < 0 )
+ {
+ // Store relatively index
+ if ( 0 == iPos )
+ {
+ pIndices->push_back( vSize + iVal );
+ }
+ else if ( 1 == iPos )
+ {
+ pTexID->push_back( vtSize + iVal );
+ }
+ else if ( 2 == iPos )
+ {
+ pNormalID->push_back( vnSize + iVal );
+ hasNormal = true;
+ }
+ else
+ {
+ reportErrorTokenInFace();
+ }
+ }
+ }
+ pPtr += iStep;
+ }
+
+ if ( pIndices->empty() ) {
+ DefaultLogger::get()->error("Obj: Ignoring empty face");
+ // skip line and clean up
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ delete pNormalID;
+ delete pTexID;
+ delete pIndices;
+
+ return;
+ }
+
+ ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
+
+ // Set active material, if one set
+ if( NULL != m_pModel->m_pCurrentMaterial ) {
+ face->m_pMaterial = m_pModel->m_pCurrentMaterial;
+ } else {
+ face->m_pMaterial = m_pModel->m_pDefaultMaterial;
+ }
+
+ // Create a default object, if nothing is there
+ if( NULL == m_pModel->m_pCurrent ) {
+ createObject( DefaultObjName );
+ }
+
+ // Assign face to mesh
+ if ( NULL == m_pModel->m_pCurrentMesh ) {
+ createMesh( DefaultObjName );
+ }
+
+ // Store the face
+ m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
+ m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
+ m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size();
+ if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) {
+ m_pModel->m_pCurrentMesh->m_hasNormals = true;
+ }
+ // Skip the rest of the line
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Get values for a new material description
+// Get values for a new material description
void ObjFileParser::getMaterialDesc()
{
- // Each material request a new object.
- // Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
- // So, we create a new object only if the current on is already initialized !
- if (m_pModel->m_pCurrent != NULL &&
- ( m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
- (m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0) )
- )
- m_pModel->m_pCurrent = NULL;
-
- // Get next data for material data
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- if (m_DataIt == m_DataItEnd)
- return;
-
- char *pStart = &(*m_DataIt);
- while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
- ++m_DataIt;
-
- // Get name
- std::string strName(pStart, &(*m_DataIt));
- if ( strName.empty())
- return;
-
- // Search for material
- std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
- if ( it == m_pModel->m_MaterialMap.end() )
- {
- // Not found, use default material
- m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
- DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
- }
- else
- {
- // Found, using detected material
- m_pModel->m_pCurrentMaterial = (*it).second;
- if ( needsNewMesh( strName ))
- {
- createMesh();
- }
- m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
- }
-
- // Skip rest of line
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ // Get next data for material data
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ if (m_DataIt == m_DataItEnd) {
+ return;
+ }
+
+ char *pStart = &(*m_DataIt);
+ while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
+ ++m_DataIt;
+ }
+
+ // In some cases we should ignore this 'usemtl' command, this variable helps us to do so
+ bool skip = false;
+
+ // Get name
+ std::string strName(pStart, &(*m_DataIt));
+ strName = trim_whitespaces(strName);
+ if (strName.empty())
+ skip = true;
+
+ // If the current mesh has the same material, we simply ignore that 'usemtl' command
+ // There is no need to create another object or even mesh here
+ if (m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString(strName))
+ skip = true;
+
+ if (!skip)
+ {
+ // Search for material
+ std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
+ if (it == m_pModel->m_MaterialMap.end())
+ {
+ // Not found, use default material
+ m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
+ DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
+ strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str();
+ }
+ else
+ {
+ // Found, using detected material
+ m_pModel->m_pCurrentMaterial = (*it).second;
+ }
+
+ if (needsNewMesh(strName))
+ createMesh(strName);
+
+ m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
+ }
+
+ // Skip rest of line
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Get a comment, values will be skipped
+// Get a comment, values will be skipped
void ObjFileParser::getComment()
{
- while (m_DataIt != m_DataItEnd)
- {
- if ( '\n' == (*m_DataIt))
- {
- ++m_DataIt;
- break;
- }
- else
- {
- ++m_DataIt;
- }
- }
+ while (m_DataIt != m_DataItEnd)
+ {
+ if ( '\n' == (*m_DataIt))
+ {
+ ++m_DataIt;
+ break;
+ }
+ else
+ {
+ ++m_DataIt;
+ }
+ }
}
// -------------------------------------------------------------------
-// Get material library from file.
+// Get material library from file.
void ObjFileParser::getMaterialLib()
{
- // Translate tuple
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- if (m_DataIt == m_DataItEnd)
- return;
-
- char *pStart = &(*m_DataIt);
- while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
- m_DataIt++;
-
- // Check for existence
- const std::string strMatName(pStart, &(*m_DataIt));
- IOStream *pFile = m_pIO->Open(strMatName);
-
- if (!pFile )
- {
- DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- return;
- }
-
- // Import material library data from file
- std::vector<char> buffer;
- BaseImporter::TextFileToBuffer(pFile,buffer);
- m_pIO->Close( pFile );
-
- // Importing the material library
- ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );
+ // Translate tuple
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ if( m_DataIt == m_DataItEnd ) {
+ return;
+ }
+
+ char *pStart = &(*m_DataIt);
+ while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
+ ++m_DataIt;
+ }
+
+ // Check for existence
+ const std::string strMatName(pStart, &(*m_DataIt));
+ std::string absName;
+ if ( m_pIO->StackSize() > 0 ) {
+ std::string path = m_pIO->CurrentDirectory();
+ if ( '/' != *path.rbegin() ) {
+ path += '/';
+ }
+ absName = path + strMatName;
+ } else {
+ absName = strMatName;
+ }
+ IOStream *pFile = m_pIO->Open( absName );
+
+ if (!pFile ) {
+ DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
+ std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl";
+ DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName);
+ pFile = m_pIO->Open(strMatFallbackName);
+ if (!pFile) {
+ DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatName);
+ m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
+ return;
+ }
+ }
+
+ // Import material library data from file.
+ // Some exporters (e.g. Silo) will happily write out empty
+ // material files if the model doesn't use any materials, so we
+ // allow that.
+ std::vector<char> buffer;
+ BaseImporter::TextFileToBuffer( pFile, buffer, BaseImporter::ALLOW_EMPTY );
+ m_pIO->Close( pFile );
+
+ // Importing the material library
+ ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );
}
// -------------------------------------------------------------------
-// Set a new material definition as the current material.
+// Set a new material definition as the current material.
void ObjFileParser::getNewMaterial()
{
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
- if ( m_DataIt == m_DataItEnd )
- return;
-
- char *pStart = &(*m_DataIt);
- std::string strMat( pStart, *m_DataIt );
- while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
- m_DataIt++;
- std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
- if ( it == m_pModel->m_MaterialMap.end() )
- {
- // Show a warning, if material was not found
- DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
- m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
- }
- else
- {
- // Set new material
- if ( needsNewMesh( strMat ) )
- {
- createMesh();
- }
- m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
- }
-
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
+ if( m_DataIt == m_DataItEnd ) {
+ return;
+ }
+
+ char *pStart = &(*m_DataIt);
+ std::string strMat( pStart, *m_DataIt );
+ while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
+ ++m_DataIt;
+ }
+ std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
+ if ( it == m_pModel->m_MaterialMap.end() )
+ {
+ // Show a warning, if material was not found
+ DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat);
+ m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
+ }
+ else
+ {
+ // Set new material
+ if ( needsNewMesh( strMat ) )
+ {
+ createMesh( strMat );
+ }
+ m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat );
+ }
+
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
{
- int mat_index = -1;
- if ( strMaterialName.empty() )
- return mat_index;
- for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
- {
- if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
- {
- mat_index = (int)index;
- break;
- }
- }
- return mat_index;
+ int mat_index = -1;
+ if( strMaterialName.empty() ) {
+ return mat_index;
+ }
+ for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
+ {
+ if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
+ {
+ mat_index = (int)index;
+ break;
+ }
+ }
+ return mat_index;
}
// -------------------------------------------------------------------
-// Getter for a group name.
+// Getter for a group name.
void ObjFileParser::getGroupName()
{
- std::string strGroupName;
-
- m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
- if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
- return;
-
- // Change active group, if necessary
- if ( m_pModel->m_strActiveGroup != strGroupName )
- {
- // Search for already existing entry
- ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
-
- // We are mapping groups into the object structure
- createObject( strGroupName );
-
- // New group name, creating a new entry
- if (it == m_pModel->m_Groups.end())
- {
- std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
- m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
- m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
- }
- else
- {
- m_pModel->m_pGroupFaceIDs = (*it).second;
- }
- m_pModel->m_strActiveGroup = strGroupName;
- }
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ std::string strGroupName;
+
+ m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
+ if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
+ return;
+ }
+
+ // Change active group, if necessary
+ if ( m_pModel->m_strActiveGroup != strGroupName )
+ {
+ // Search for already existing entry
+ ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
+
+ // We are mapping groups into the object structure
+ createObject( strGroupName );
+
+ // New group name, creating a new entry
+ if (it == m_pModel->m_Groups.end())
+ {
+ std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
+ m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
+ m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
+ }
+ else
+ {
+ m_pModel->m_pGroupFaceIDs = (*it).second;
+ }
+ m_pModel->m_strActiveGroup = strGroupName;
+ }
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Not supported
+// Not supported
void ObjFileParser::getGroupNumber()
{
- // Not used
+ // Not used
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Not supported
+// Not supported
void ObjFileParser::getGroupNumberAndResolution()
{
- // Not used
+ // Not used
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Stores values for a new object instance, name will be used to
-// identify it.
+// Stores values for a new object instance, name will be used to
+// identify it.
void ObjFileParser::getObjectName()
{
- m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
- if (m_DataIt == m_DataItEnd)
- return;
- char *pStart = &(*m_DataIt);
- while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
- ++m_DataIt;
-
- std::string strObjectName(pStart, &(*m_DataIt));
- if (!strObjectName.empty())
- {
- // Reset current object
- m_pModel->m_pCurrent = NULL;
-
- // Search for actual object
- for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
- it != m_pModel->m_Objects.end();
- ++it)
- {
- if ((*it)->m_strObjName == strObjectName)
- {
- m_pModel->m_pCurrent = *it;
- break;
- }
- }
-
- // Allocate a new object, if current one was not found before
- if ( NULL == m_pModel->m_pCurrent )
- createObject(strObjectName);
- }
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
+ if( m_DataIt == m_DataItEnd ) {
+ return;
+ }
+ char *pStart = &(*m_DataIt);
+ while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
+ ++m_DataIt;
+ }
+
+ std::string strObjectName(pStart, &(*m_DataIt));
+ if (!strObjectName.empty())
+ {
+ // Reset current object
+ m_pModel->m_pCurrent = NULL;
+
+ // Search for actual object
+ for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin();
+ it != m_pModel->m_Objects.end();
+ ++it)
+ {
+ if ((*it)->m_strObjName == strObjectName)
+ {
+ m_pModel->m_pCurrent = *it;
+ break;
+ }
+ }
+
+ // Allocate a new object, if current one was not found before
+ if( NULL == m_pModel->m_pCurrent ) {
+ createObject( strObjectName );
+ }
+ }
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
// -------------------------------------------------------------------
-// Creates a new object instance
-void ObjFileParser::createObject(const std::string &strObjectName)
+// Creates a new object instance
+void ObjFileParser::createObject(const std::string &objName)
{
- ai_assert( NULL != m_pModel );
- //ai_assert( !strObjectName.empty() );
-
- m_pModel->m_pCurrent = new ObjFile::Object;
- m_pModel->m_pCurrent->m_strObjName = strObjectName;
- m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
-
-
- createMesh();
-
- if( m_pModel->m_pCurrentMaterial )
- {
- m_pModel->m_pCurrentMesh->m_uiMaterialIndex =
- getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
- m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
- }
+ ai_assert( NULL != m_pModel );
+
+ m_pModel->m_pCurrent = new ObjFile::Object;
+ m_pModel->m_pCurrent->m_strObjName = objName;
+ m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
+
+ createMesh( objName );
+
+ if( m_pModel->m_pCurrentMaterial )
+ {
+ m_pModel->m_pCurrentMesh->m_uiMaterialIndex =
+ getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data );
+ m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial;
+ }
}
// -------------------------------------------------------------------
-// Creates a new mesh
-void ObjFileParser::createMesh()
+// Creates a new mesh
+void ObjFileParser::createMesh( const std::string &meshName )
{
- ai_assert( NULL != m_pModel );
- m_pModel->m_pCurrentMesh = new ObjFile::Mesh;
- m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
- unsigned int meshId = m_pModel->m_Meshes.size()-1;
- if ( NULL != m_pModel->m_pCurrent )
- {
- m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
- }
- else
- {
- DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
- }
+ ai_assert( NULL != m_pModel );
+ m_pModel->m_pCurrentMesh = new ObjFile::Mesh( meshName );
+ m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh );
+ unsigned int meshId = m_pModel->m_Meshes.size()-1;
+ if ( NULL != m_pModel->m_pCurrent )
+ {
+ m_pModel->m_pCurrent->m_Meshes.push_back( meshId );
+ }
+ else
+ {
+ DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance.");
+ }
}
// -------------------------------------------------------------------
-// Returns true, if a new mesh must be created.
-bool ObjFileParser::needsNewMesh( const std::string &rMaterialName )
+// Returns true, if a new mesh must be created.
+bool ObjFileParser::needsNewMesh( const std::string &materialName )
{
- if(m_pModel->m_pCurrentMesh == 0)
- {
- // No mesh data yet
- return true;
- }
- bool newMat = false;
- int matIdx = getMaterialIndex( rMaterialName );
- int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
- if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) || curMatIdx != matIdx )
- {
- // New material -> only one material per mesh, so we need to create a new
- // material
- newMat = true;
- }
- return newMat;
+ // If no mesh data yet
+ if(m_pModel->m_pCurrentMesh == 0)
+ {
+ return true;
+ }
+ bool newMat = false;
+ int matIdx = getMaterialIndex( materialName );
+ int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex;
+ if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx )
+ {
+ // New material -> only one material per mesh, so we need to create a new
+ // material
+ newMat = true;
+ }
+ return newMat;
}
// -------------------------------------------------------------------
-// Shows an error in parsing process.
+// Shows an error in parsing process.
void ObjFileParser::reportErrorTokenInFace()
-{
- m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
- DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
+{
+ m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+ DefaultLogger::get()->error("OBJ: Not supported token in face description detected");
}
// -------------------------------------------------------------------
-} // Namespace Assimp
+} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER
diff --git a/src/3rdparty/assimp/code/ObjFileParser.h b/src/3rdparty/assimp/code/ObjFileParser.h
index f6473a11e..f1be764f0 100644
--- a/src/3rdparty/assimp/code/ObjFileParser.h
+++ b/src/3rdparty/assimp/code/ObjFileParser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,98 +43,114 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <string>
#include <map>
-
-namespace Assimp
-{
-
-namespace ObjFile
-{
-struct Model;
-struct Object;
-struct Material;
-struct Point3;
-struct Point2;
+#include <assimp/vector2.h>
+#include <assimp/vector3.h>
+#include <assimp/mesh.h>
+
+namespace Assimp {
+
+namespace ObjFile {
+ struct Model;
+ struct Object;
+ struct Material;
+ struct Point3;
+ struct Point2;
}
+
class ObjFileImporter;
class IOSystem;
+class ProgressHandler;
-/// \class ObjFileParser
-/// \brief Parser for a obj waveform file
-class ObjFileParser
-{
+/// \class ObjFileParser
+/// \brief Parser for a obj waveform file
+class ObjFileParser {
public:
- static const size_t BUFFERSIZE = 4096;
- typedef std::vector<char> DataArray;
- typedef std::vector<char>::iterator DataArrayIt;
- typedef std::vector<char>::const_iterator ConstDataArrayIt;
+ static const size_t Buffersize = 4096;
+ typedef std::vector<char> DataArray;
+ typedef std::vector<char>::iterator DataArrayIt;
+ typedef std::vector<char>::const_iterator ConstDataArrayIt;
public:
- /// \brief Constructor with data array.
- ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io);
- /// \brief Destructor
- ~ObjFileParser();
- /// \brief Model getter.
- ObjFile::Model *GetModel() const;
+ /// \brief Constructor with data array.
+ ObjFileParser(std::vector<char> &Data, const std::string &strModelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName);
+ /// \brief Destructor
+ ~ObjFileParser();
+ /// \brief Model getter.
+ ObjFile::Model *GetModel() const;
private:
- /// Parse the loaded file
- void parseFile();
- /// Method to copy the new delimited word in the current line.
- void copyNextWord(char *pBuffer, size_t length);
- /// Method to copy the new line.
- void copyNextLine(char *pBuffer, size_t length);
- /// Stores the vector
+ /// Parse the loaded file
+ void parseFile();
+ /// Method to copy the new delimited word in the current line.
+ void copyNextWord(char *pBuffer, size_t length);
+ /// Method to copy the new line.
+ void copyNextLine(char *pBuffer, size_t length);
+ /// Stores the vector
void getVector( std::vector<aiVector3D> &point3d_array );
- /// Stores the following 3d vector.
- void getVector3( std::vector<aiVector3D> &point3d_array );
- /// Stores the following 3d vector.
- void getVector2(std::vector<aiVector2D> &point2d_array);
- /// Stores the following face.
- void getFace(aiPrimitiveType type);
- /// Reads the material description.
+ /// Stores the following 3d vector.
+ void getVector3( std::vector<aiVector3D> &point3d_array );
+ /// Stores the following two 3d vectors on the line.
+ void getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b );
+ /// Stores the following 3d vector.
+ void getVector2(std::vector<aiVector2D> &point2d_array);
+ /// Stores the following face.
+ void getFace(aiPrimitiveType type);
+ /// Reads the material description.
void getMaterialDesc();
- /// Gets a comment.
- void getComment();
- /// Gets a a material library.
- void getMaterialLib();
- /// Creates a new material.
- void getNewMaterial();
- /// Gets the group name from file.
- void getGroupName();
- /// Gets the group number from file.
- void getGroupNumber();
- /// Gets the group number and resolution from file.
- void getGroupNumberAndResolution();
- /// Returns the index of the material. Is -1 if not material was found.
- int getMaterialIndex( const std::string &strMaterialName );
- /// Parse object name
- void getObjectName();
- /// Creates a new object.
- void createObject(const std::string &strObjectName);
- /// Creates a new mesh.
- void createMesh();
- /// Returns true, if a new mesh instance must be created.
- bool needsNewMesh( const std::string &rMaterialName );
- /// Error report in token
- void reportErrorTokenInFace();
+ /// Gets a comment.
+ void getComment();
+ /// Gets a a material library.
+ void getMaterialLib();
+ /// Creates a new material.
+ void getNewMaterial();
+ /// Gets the group name from file.
+ void getGroupName();
+ /// Gets the group number from file.
+ void getGroupNumber();
+ /// Gets the group number and resolution from file.
+ void getGroupNumberAndResolution();
+ /// Returns the index of the material. Is -1 if not material was found.
+ int getMaterialIndex( const std::string &strMaterialName );
+ /// Parse object name
+ void getObjectName();
+ /// Creates a new object.
+ void createObject( const std::string &strObjectName );
+ /// Creates a new mesh.
+ void createMesh( const std::string &meshName );
+ /// Returns true, if a new mesh instance must be created.
+ bool needsNewMesh( const std::string &rMaterialName );
+ /// Error report in token
+ void reportErrorTokenInFace();
+ /// Get the number of components in a line.
+ size_t getNumComponentsInLine();
private:
- /// Default material name
- static const std::string DEFAULT_MATERIAL;
- //! Iterator to current position in buffer
- DataArrayIt m_DataIt;
- //! Iterator to end position of buffer
- DataArrayIt m_DataItEnd;
- //! Pointer to model instance
- ObjFile::Model *m_pModel;
- //! Current line (for debugging)
- unsigned int m_uiLine;
- //! Helper buffer
- char m_buffer[BUFFERSIZE];
- /// Pointer to IO system instance.
- IOSystem *m_pIO;
+ // Copy and assignment constructor should be private
+ // because the class contains pointer to allocated memory
+ ObjFileParser(const ObjFileParser& rhs);
+ ObjFileParser& operator=(const ObjFileParser& rhs);
+
+ /// Default material name
+ static const std::string DEFAULT_MATERIAL;
+ //! Iterator to current position in buffer
+ DataArrayIt m_DataIt;
+ //! Iterator to end position of buffer
+ DataArrayIt m_DataItEnd;
+ //! Pointer to model instance
+ ObjFile::Model *m_pModel;
+ //! Current line (for debugging)
+ unsigned int m_uiLine;
+ //! Helper buffer
+ char m_buffer[Buffersize];
+ /// Pointer to IO system instance.
+ IOSystem *m_pIO;
+ //! Pointer to progress handler
+ ProgressHandler* m_progress;
+ /// Path to the current model
+ // name of the obj file where the buffer comes from
+ const std::string& m_originalObjFileName;
};
-} // Namespace Assimp
+} // Namespace Assimp
#endif
diff --git a/src/3rdparty/assimp/code/ObjTools.h b/src/3rdparty/assimp/code/ObjTools.h
index 30c59db4c..311965ce3 100644
--- a/src/3rdparty/assimp/code/ObjTools.h
+++ b/src/3rdparty/assimp/code/ObjTools.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,240 +23,229 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file ObjTools.h
- * @brief Some helpful templates for text parsing
+/** @file ObjTools.h
+ * @brief Some helpful templates for text parsing
*/
#ifndef OBJ_TOOLS_H_INC
#define OBJ_TOOLS_H_INC
#include "fast_atof.h"
+#include "ParsingUtils.h"
+#include <vector>
namespace Assimp
{
-/** @brief Returns true, if the last entry of the buffer is reached.
- * @param it Iterator of current position.
- * @param end Iterator with end of buffer.
- * @return true, if the end of the buffer is reached.
+/** @brief Returns true, if the last entry of the buffer is reached.
+ * @param it Iterator of current position.
+ * @param end Iterator with end of buffer.
+ * @return true, if the end of the buffer is reached.
*/
template<class char_t>
inline bool isEndOfBuffer( char_t it, char_t end )
{
- if ( it == end )
- {
- return true;
- }
- else
- {
- end--;
- }
- return ( it == end );
+ if ( it == end )
+ {
+ return true;
+ }
+ else
+ {
+ end--;
+ }
+ return ( it == end );
}
-/** @brief Returns true, if token is a space on any supported platform
-* @param token Token to search in
-* @return true, if token is a space
-*/
-inline bool isSeparator( char token )
-{
- return ( token == ' ' ||
- token == '\n' ||
- token == '\f' ||
- token == '\r' ||
- token == '\t' );
-}
-
-/** @brief Returns true, fi token id a new line marking token.
- * @param token Token to search in
- * @return true, if token is a newline token.
- */
-inline bool isNewLine( char token )
-{
- return ( token == '\n' || token == '\f' || token == '\r' );
-}
-
-/** @brief Returns next word separated by a space
- * @param pBuffer Pointer to data buffer
- * @param pEnd Pointer to end of buffer
- * @return Pointer to next space
+/** @brief Returns next word separated by a space
+ * @param pBuffer Pointer to data buffer
+ * @param pEnd Pointer to end of buffer
+ * @return Pointer to next space
*/
template<class Char_T>
inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
{
- while ( !isEndOfBuffer( pBuffer, pEnd ) )
- {
- if ( !isSeparator( *pBuffer ) || isNewLine( *pBuffer ) )
- break;
- pBuffer++;
- }
- return pBuffer;
+ while ( !isEndOfBuffer( pBuffer, pEnd ) )
+ {
+ if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) )
+ break;
+ pBuffer++;
+ }
+ return pBuffer;
}
-/** @brief Returns pointer a next token
- * @param pBuffer Pointer to data buffer
- * @param pEnd Pointer to end of buffer
- * @return Pointer to next token
+/** @brief Returns pointer a next token
+ * @param pBuffer Pointer to data buffer
+ * @param pEnd Pointer to end of buffer
+ * @return Pointer to next token
*/
template<class Char_T>
inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
{
- while ( !isEndOfBuffer( pBuffer, pEnd ) )
- {
- if ( isSeparator( *pBuffer ) )
- break;
- pBuffer++;
- }
- return getNextWord( pBuffer, pEnd );
+ while ( !isEndOfBuffer( pBuffer, pEnd ) )
+ {
+ if( IsSpaceOrNewLine( *pBuffer ) )
+ break;
+ pBuffer++;
+ }
+ return getNextWord( pBuffer, pEnd );
}
-/** @brief Skips a line
- * @param it Iterator set to current position
- * @param end Iterator set to end of scratch buffer for readout
- * @param uiLine Current linenumber in format
- * @return Current-iterator with new position
+/** @brief Skips a line
+ * @param it Iterator set to current position
+ * @param end Iterator set to end of scratch buffer for readout
+ * @param uiLine Current line number in format
+ * @return Current-iterator with new position
*/
template<class char_t>
-inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine )
-{
- while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) )
- ++it;
- if ( it != end )
- {
- ++it;
- ++uiLine;
- }
- // fix .. from time to time there are spaces at the beginning of a material line
- while ( it != end && (*it == '\t' || *it == ' ') )
- ++it;
- return it;
+inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
+ while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
+ ++it;
+ }
+ if ( it != end )
+ {
+ ++it;
+ ++uiLine;
+ }
+ // fix .. from time to time there are spaces at the beginning of a material line
+ while ( it != end && (*it == '\t' || *it == ' ') )
+ ++it;
+ return it;
}
-/** @brief Get a name from the current line. Preserve space in the middle,
+/** @brief Get a name from the current line. Preserve space in the middle,
* but trim it at the end.
- * @param it set to current position
- * @param end set to end of scratch buffer for readout
- * @param name Separated name
- * @return Current-iterator with new position
+ * @param it set to current position
+ * @param end set to end of scratch buffer for readout
+ * @param name Separated name
+ * @return Current-iterator with new position
*/
template<class char_t>
inline char_t getName( char_t it, char_t end, std::string &name )
{
- name = "";
- if ( isEndOfBuffer( it, end ) )
- return end;
-
- char *pStart = &( *it );
- while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) {
- ++it;
- }
-
- while(isEndOfBuffer( it, end ) || isNewLine( *it ) || isSeparator(*it)) {
- --it;
- }
- ++it;
-
- // Get name
- // if there is no name, and the previous char is a separator, come back to start
- while (&(*it) < pStart) {
- ++it;
- }
- std::string strName( pStart, &(*it) );
- if ( strName.empty() )
- return it;
- else
- name = strName;
-
- return it;
+ name = "";
+ if( isEndOfBuffer( it, end ) ) {
+ return end;
+ }
+
+ char *pStart = &( *it );
+ while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
+ ++it;
+ }
+
+ while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *it ) ) {
+ --it;
+ }
+ ++it;
+
+ // Get name
+ // if there is no name, and the previous char is a separator, come back to start
+ while (&(*it) < pStart) {
+ ++it;
+ }
+ std::string strName( pStart, &(*it) );
+ if ( strName.empty() )
+ return it;
+ else
+ name = strName;
+
+ return it;
}
-/** @brief Get next word from given line
- * @param it set to current position
- * @param end set to end of scratch buffer for readout
- * @param pBuffer Buffer for next word
- * @param length Buffer length
- * @return Current-iterator with new position
+/** @brief Get next word from given line
+ * @param it set to current position
+ * @param end set to end of scratch buffer for readout
+ * @param pBuffer Buffer for next word
+ * @param length Buffer length
+ * @return Current-iterator with new position
*/
template<class char_t>
inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length )
{
- size_t index = 0;
- it = getNextWord<char_t>( it, end );
- while ( !isSeparator( *it ) && !isEndOfBuffer( it, end ) )
- {
- pBuffer[index] = *it ;
- index++;
- if (index == length-1)
- break;
- ++it;
- }
- pBuffer[ index ] = '\0';
- return it;
+ size_t index = 0;
+ it = getNextWord<char_t>( it, end );
+ while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
+ {
+ pBuffer[index] = *it ;
+ index++;
+ if (index == length-1)
+ break;
+ ++it;
+ }
+ pBuffer[ index ] = '\0';
+ return it;
}
-/** @brief Get next float from given line
- * @param it set to current position
- * @param end set to end of scratch buffer for readout
- * @param value Separated float value.
- * @return Current-iterator with new position
+/** @brief Get next float from given line
+ * @param it set to current position
+ * @param end set to end of scratch buffer for readout
+ * @param value Separated float value.
+ * @return Current-iterator with new position
*/
template<class char_t>
inline char_t getFloat( char_t it, char_t end, float &value )
{
- static const size_t BUFFERSIZE = 1024;
- char buffer[ BUFFERSIZE ];
- it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE );
- value = (float) fast_atof( buffer );
+ static const size_t BUFFERSIZE = 1024;
+ char buffer[ BUFFERSIZE ];
+ it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE );
+ value = (float) fast_atof( buffer );
- return it;
+ return it;
}
-/** @brief Will perform a simple tokenize.
- * @param str String to tokenize.
- * @param tokens Array with tokens, will be empty if no token was found.
- * @param delimiters Delimiter for tokenize.
- * @return Number of found token.
+/** @brief Will perform a simple tokenize.
+ * @param str String to tokenize.
+ * @param tokens Array with tokens, will be empty if no token was found.
+ * @param delimiters Delimiter for tokenize.
+ * @return Number of found token.
*/
template<class string_type>
-unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
- const string_type& delimiters )
+unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
+ const string_type& delimiters )
{
- // Skip delimiters at beginning.
- typename string_type::size_type lastPos = str.find_first_not_of( delimiters, 0 );
-
- // Find first "non-delimiter".
- typename string_type::size_type pos = str.find_first_of( delimiters, lastPos );
- while ( string_type::npos != pos || string_type::npos != lastPos )
- {
- // Found a token, add it to the vector.
- string_type tmp = str.substr(lastPos, pos - lastPos);
- if ( !tmp.empty() && ' ' != tmp[ 0 ] )
- tokens.push_back( tmp );
-
- // Skip delimiters. Note the "not_of"
- lastPos = str.find_first_not_of( delimiters, pos );
-
- // Find next "non-delimiter"
- pos = str.find_first_of( delimiters, lastPos );
- }
+ // Skip delimiters at beginning.
+ typename string_type::size_type lastPos = str.find_first_not_of( delimiters, 0 );
+
+ // Find first "non-delimiter".
+ typename string_type::size_type pos = str.find_first_of( delimiters, lastPos );
+ while ( string_type::npos != pos || string_type::npos != lastPos )
+ {
+ // Found a token, add it to the vector.
+ string_type tmp = str.substr(lastPos, pos - lastPos);
+ if ( !tmp.empty() && ' ' != tmp[ 0 ] )
+ tokens.push_back( tmp );
+
+ // Skip delimiters. Note the "not_of"
+ lastPos = str.find_first_not_of( delimiters, pos );
+
+ // Find next "non-delimiter"
+ pos = str.find_first_of( delimiters, lastPos );
+ }
+
+ return static_cast<unsigned int>( tokens.size() );
+}
- return static_cast<unsigned int>( tokens.size() );
+template <class string_type>
+string_type trim_whitespaces(string_type str)
+{
+ while (!str.empty() && IsSpace(str[0])) str.erase(0);
+ while (!str.empty() && IsSpace(str[str.length() - 1])) str.erase(str.length() - 1);
+ return str;
}
} // Namespace Assimp
-#endif
+#endif // OBJ_TOOLS_H_INC
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
index 6674f4cee..ce17cea6a 100644
--- a/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OgreParsingUtils.h"
#include "TinyFormatter.h"
+#include <assimp/DefaultLogger.hpp>
+
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
@@ -64,1044 +66,1041 @@ const long MSTREAM_OVERHEAD_SIZE = sizeof(uint16_t) +
const long MSTREAM_BONE_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) + (sizeof(float) * 7);
const long MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + (sizeof(float) * 8);
-template<>
+template<>
inline bool OgreBinarySerializer::Read<bool>()
{
- return (m_reader->GetU1() > 0);
+ return (m_reader->GetU1() > 0);
}
-template<>
+template<>
inline char OgreBinarySerializer::Read<char>()
{
- return static_cast<char>(m_reader->GetU1());
+ return static_cast<char>(m_reader->GetU1());
}
-template<>
+template<>
inline uint8_t OgreBinarySerializer::Read<uint8_t>()
{
- return m_reader->GetU1();
+ return m_reader->GetU1();
}
-template<>
+template<>
inline uint16_t OgreBinarySerializer::Read<uint16_t>()
{
- return m_reader->GetU2();
+ return m_reader->GetU2();
}
-template<>
+template<>
inline uint32_t OgreBinarySerializer::Read<uint32_t>()
{
- return m_reader->GetU4();
+ return m_reader->GetU4();
}
-template<>
+template<>
inline float OgreBinarySerializer::Read<float>()
{
- return m_reader->GetF4();
+ return m_reader->GetF4();
}
void OgreBinarySerializer::ReadBytes(char *dest, size_t numBytes)
{
- ReadBytes(static_cast<void*>(dest), numBytes);
+ ReadBytes(static_cast<void*>(dest), numBytes);
}
void OgreBinarySerializer::ReadBytes(uint8_t *dest, size_t numBytes)
{
- ReadBytes(static_cast<void*>(dest), numBytes);
+ ReadBytes(static_cast<void*>(dest), numBytes);
}
void OgreBinarySerializer::ReadBytes(void *dest, size_t numBytes)
{
- m_reader->CopyAndAdvance(dest, numBytes);
+ m_reader->CopyAndAdvance(dest, numBytes);
}
uint8_t *OgreBinarySerializer::ReadBytes(size_t numBytes)
{
- uint8_t *bytes = new uint8_t[numBytes];
- ReadBytes(bytes, numBytes);
- return bytes;
+ uint8_t *bytes = new uint8_t[numBytes];
+ ReadBytes(bytes, numBytes);
+ return bytes;
}
void OgreBinarySerializer::ReadVector(aiVector3D &vec)
{
- m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3);
+ m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3);
}
void OgreBinarySerializer::ReadQuaternion(aiQuaternion &quat)
{
- float temp[4];
- m_reader->CopyAndAdvance(temp, sizeof(float)*4);
- quat.x = temp[0];
- quat.y = temp[1];
- quat.z = temp[2];
- quat.w = temp[3];
+ float temp[4];
+ m_reader->CopyAndAdvance(temp, sizeof(float)*4);
+ quat.x = temp[0];
+ quat.y = temp[1];
+ quat.z = temp[2];
+ quat.w = temp[3];
}
bool OgreBinarySerializer::AtEnd() const
{
- return (m_reader->GetRemainingSize() == 0);
+ return (m_reader->GetRemainingSize() == 0);
}
std::string OgreBinarySerializer::ReadString(size_t len)
{
- std::string str;
- str.resize(len);
- ReadBytes(&str[0], len);
- return str;
+ std::string str;
+ str.resize(len);
+ ReadBytes(&str[0], len);
+ return str;
}
std::string OgreBinarySerializer::ReadLine()
{
- std::string str;
- while(!AtEnd())
- {
- char c = Read<char>();
- if (c == '\n')
- break;
- str += c;
- }
- return str;
+ std::string str;
+ while(!AtEnd())
+ {
+ char c = Read<char>();
+ if (c == '\n')
+ break;
+ str += c;
+ }
+ return str;
}
uint16_t OgreBinarySerializer::ReadHeader(bool readLen)
{
- uint16_t id = Read<uint16_t>();
- if (readLen)
- m_currentLen = Read<uint32_t>();
+ uint16_t id = Read<uint16_t>();
+ if (readLen)
+ m_currentLen = Read<uint32_t>();
#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
- if (id != HEADER_CHUNK_ID)
- {
- DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh
- ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id))));
- }
+ if (id != HEADER_CHUNK_ID)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh
+ ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id))));
+ }
#endif
- return id;
+ return id;
}
void OgreBinarySerializer::RollbackHeader()
{
- m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE);
+ m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE);
}
void OgreBinarySerializer::SkipBytes(size_t numBytes)
{
#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
- DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes");
+ DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes");
#endif
- m_reader->IncPtr(numBytes);
+ m_reader->IncPtr(numBytes);
}
// Mesh
Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream)
{
- OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh);
-
- uint16_t id = serializer.ReadHeader(false);
- if (id != HEADER_CHUNK_ID) {
- throw DeadlyExportError("Invalid Ogre Mesh file header.");
- }
-
- /// @todo Check what we can actually support.
- std::string version = serializer.ReadLine();
- if (version != MESH_VERSION_1_8)
- {
- throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again."
- << " Supported versions: " << MESH_VERSION_1_8);
- }
-
- Mesh *mesh = new Mesh();
- while (!serializer.AtEnd())
- {
- id = serializer.ReadHeader();
- switch(id)
- {
- case M_MESH:
- {
- serializer.ReadMesh(mesh);
- break;
- }
- }
- }
- return mesh;
+ OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh);
+
+ uint16_t id = serializer.ReadHeader(false);
+ if (id != HEADER_CHUNK_ID) {
+ throw DeadlyExportError("Invalid Ogre Mesh file header.");
+ }
+
+ /// @todo Check what we can actually support.
+ std::string version = serializer.ReadLine();
+ if (version != MESH_VERSION_1_8)
+ {
+ throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again."
+ << " Supported versions: " << MESH_VERSION_1_8);
+ }
+
+ Mesh *mesh = new Mesh();
+ while (!serializer.AtEnd())
+ {
+ id = serializer.ReadHeader();
+ switch(id)
+ {
+ case M_MESH:
+ {
+ serializer.ReadMesh(mesh);
+ break;
+ }
+ }
+ }
+ return mesh;
}
void OgreBinarySerializer::ReadMesh(Mesh *mesh)
{
- mesh->hasSkeletalAnimations = Read<bool>();
-
- DefaultLogger::get()->debug("Reading Mesh");
- DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false"));
-
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() &&
- (id == M_GEOMETRY ||
- id == M_SUBMESH ||
- id == M_MESH_SKELETON_LINK ||
- id == M_MESH_BONE_ASSIGNMENT ||
- id == M_MESH_LOD ||
- id == M_MESH_BOUNDS ||
- id == M_SUBMESH_NAME_TABLE ||
- id == M_EDGE_LISTS ||
- id == M_POSES ||
- id == M_ANIMATIONS ||
- id == M_TABLE_EXTREMES))
- {
- switch(id)
- {
- case M_GEOMETRY:
- {
- mesh->sharedVertexData = new VertexData();
- ReadGeometry(mesh->sharedVertexData);
- break;
- }
- case M_SUBMESH:
- {
- ReadSubMesh(mesh);
- break;
- }
- case M_MESH_SKELETON_LINK:
- {
- ReadMeshSkeletonLink(mesh);
- break;
- }
- case M_MESH_BONE_ASSIGNMENT:
- {
- ReadBoneAssignment(mesh->sharedVertexData);
- break;
- }
- case M_MESH_LOD:
- {
- ReadMeshLodInfo(mesh);
- break;
- }
- case M_MESH_BOUNDS:
- {
- ReadMeshBounds(mesh);
- break;
- }
- case M_SUBMESH_NAME_TABLE:
- {
- ReadSubMeshNames(mesh);
- break;
- }
- case M_EDGE_LISTS:
- {
- ReadEdgeList(mesh);
- break;
- }
- case M_POSES:
- {
- ReadPoses(mesh);
- break;
- }
- case M_ANIMATIONS:
- {
- ReadAnimations(mesh);
- break;
- }
- case M_TABLE_EXTREMES:
- {
- ReadMeshExtremes(mesh);
- break;
- }
- }
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
-
- NormalizeBoneWeights(mesh->sharedVertexData);
+ mesh->hasSkeletalAnimations = Read<bool>();
+
+ DefaultLogger::get()->debug("Reading Mesh");
+ DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false"));
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_GEOMETRY ||
+ id == M_SUBMESH ||
+ id == M_MESH_SKELETON_LINK ||
+ id == M_MESH_BONE_ASSIGNMENT ||
+ id == M_MESH_LOD ||
+ id == M_MESH_BOUNDS ||
+ id == M_SUBMESH_NAME_TABLE ||
+ id == M_EDGE_LISTS ||
+ id == M_POSES ||
+ id == M_ANIMATIONS ||
+ id == M_TABLE_EXTREMES))
+ {
+ switch(id)
+ {
+ case M_GEOMETRY:
+ {
+ mesh->sharedVertexData = new VertexData();
+ ReadGeometry(mesh->sharedVertexData);
+ break;
+ }
+ case M_SUBMESH:
+ {
+ ReadSubMesh(mesh);
+ break;
+ }
+ case M_MESH_SKELETON_LINK:
+ {
+ ReadMeshSkeletonLink(mesh);
+ break;
+ }
+ case M_MESH_BONE_ASSIGNMENT:
+ {
+ ReadBoneAssignment(mesh->sharedVertexData);
+ break;
+ }
+ case M_MESH_LOD:
+ {
+ ReadMeshLodInfo(mesh);
+ break;
+ }
+ case M_MESH_BOUNDS:
+ {
+ ReadMeshBounds(mesh);
+ break;
+ }
+ case M_SUBMESH_NAME_TABLE:
+ {
+ ReadSubMeshNames(mesh);
+ break;
+ }
+ case M_EDGE_LISTS:
+ {
+ ReadEdgeList(mesh);
+ break;
+ }
+ case M_POSES:
+ {
+ ReadPoses(mesh);
+ break;
+ }
+ case M_ANIMATIONS:
+ {
+ ReadAnimations(mesh);
+ break;
+ }
+ case M_TABLE_EXTREMES:
+ {
+ ReadMeshExtremes(mesh);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ NormalizeBoneWeights(mesh->sharedVertexData);
}
void OgreBinarySerializer::ReadMeshLodInfo(Mesh *mesh)
{
- // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
- // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information.
- ReadLine(); // strategy name
- uint16_t numLods = Read<uint16_t>();
- bool manual = Read<bool>();
-
- /// @note Main mesh is considered as LOD 0, start from index 1.
- for (size_t i=1; i<numLods; ++i)
- {
- uint16_t id = ReadHeader();
- if (id != M_MESH_LOD_USAGE) {
- throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level");
- }
-
- m_reader->IncPtr(sizeof(float)); // user value
-
- if (manual)
- {
- id = ReadHeader();
- if (id != M_MESH_LOD_MANUAL) {
- throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL");
- }
-
- ReadLine(); // manual mesh name (ref to another mesh)
- }
- else
- {
- for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si)
- {
- id = ReadHeader();
- if (id != M_MESH_LOD_GENERATED) {
- throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED");
- }
-
- uint32_t indexCount = Read<uint32_t>();
- bool is32bit = Read<bool>();
-
- if (indexCount > 0)
- {
- uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
- m_reader->IncPtr(len);
- }
- }
- }
- }
+ // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
+ // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information.
+ ReadLine(); // strategy name
+ uint16_t numLods = Read<uint16_t>();
+ bool manual = Read<bool>();
+
+ /// @note Main mesh is considered as LOD 0, start from index 1.
+ for (size_t i=1; i<numLods; ++i)
+ {
+ uint16_t id = ReadHeader();
+ if (id != M_MESH_LOD_USAGE) {
+ throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level");
+ }
+
+ m_reader->IncPtr(sizeof(float)); // user value
+
+ if (manual)
+ {
+ id = ReadHeader();
+ if (id != M_MESH_LOD_MANUAL) {
+ throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL");
+ }
+
+ ReadLine(); // manual mesh name (ref to another mesh)
+ }
+ else
+ {
+ for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si)
+ {
+ id = ReadHeader();
+ if (id != M_MESH_LOD_GENERATED) {
+ throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED");
+ }
+
+ uint32_t indexCount = Read<uint32_t>();
+ bool is32bit = Read<bool>();
+
+ if (indexCount > 0)
+ {
+ uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+ m_reader->IncPtr(len);
+ }
+ }
+ }
+ }
}
void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
{
- mesh->skeletonRef = ReadLine();
+ mesh->skeletonRef = ReadLine();
}
-void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
{
- // Skip bounds, not compatible with Assimp.
- // 2x float vec3 + 1x float sphere radius
- SkipBytes(sizeof(float) * 7);
+ // Skip bounds, not compatible with Assimp.
+ // 2x float vec3 + 1x float sphere radius
+ SkipBytes(sizeof(float) * 7);
}
-void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
+void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
{
- // Skip extremes, not compatible with Assimp.
- size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
- SkipBytes(numBytes);
+ // Skip extremes, not compatible with Assimp.
+ size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
+ SkipBytes(numBytes);
}
void OgreBinarySerializer::ReadBoneAssignment(VertexData *dest)
{
- if (!dest) {
- throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
- }
-
- VertexBoneAssignment ba;
- ba.vertexIndex = Read<uint32_t>();
- ba.boneIndex = Read<uint16_t>();
- ba.weight = Read<float>();
-
- dest->boneAssignments.push_back(ba);
+ if (!dest) {
+ throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
+ }
+
+ VertexBoneAssignment ba;
+ ba.vertexIndex = Read<uint32_t>();
+ ba.boneIndex = Read<uint16_t>();
+ ba.weight = Read<float>();
+
+ dest->boneAssignments.push_back(ba);
}
void OgreBinarySerializer::ReadSubMesh(Mesh *mesh)
{
- uint16_t id = 0;
-
- SubMesh *submesh = new SubMesh();
- submesh->materialRef = ReadLine();
- submesh->usesSharedVertexData = Read<bool>();
-
- submesh->indexData->count = Read<uint32_t>();
- submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3);
- submesh->indexData->is32bit = Read<bool>();
-
- DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
- DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
- DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
-
- // Index buffer
- if (submesh->indexData->count > 0)
- {
- uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
- uint8_t *indexBuffer = ReadBytes(numBytes);
- submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true));
-
- DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount
- << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit")
- << " indexes of " << numBytes << " bytes");
- }
-
- // Vertex buffer if not referencing the shared geometry
- if (!submesh->usesSharedVertexData)
- {
- id = ReadHeader();
- if (id != M_GEOMETRY) {
- throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false");
- }
-
- submesh->vertexData = new VertexData();
- ReadGeometry(submesh->vertexData);
- }
-
- // Bone assignment, submesh operation and texture aliases
- if (!AtEnd())
- {
- id = ReadHeader();
- while (!AtEnd() &&
- (id == M_SUBMESH_OPERATION ||
- id == M_SUBMESH_BONE_ASSIGNMENT ||
- id == M_SUBMESH_TEXTURE_ALIAS))
- {
- switch(id)
- {
- case M_SUBMESH_OPERATION:
- {
- ReadSubMeshOperation(submesh);
- break;
- }
- case M_SUBMESH_BONE_ASSIGNMENT:
- {
- ReadBoneAssignment(submesh->vertexData);
- break;
- }
- case M_SUBMESH_TEXTURE_ALIAS:
- {
- ReadSubMeshTextureAlias(submesh);
- break;
- }
- }
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
-
- NormalizeBoneWeights(submesh->vertexData);
-
- submesh->index = mesh->subMeshes.size();
- mesh->subMeshes.push_back(submesh);
+ uint16_t id = 0;
+
+ SubMesh *submesh = new SubMesh();
+ submesh->materialRef = ReadLine();
+ submesh->usesSharedVertexData = Read<bool>();
+
+ submesh->indexData->count = Read<uint32_t>();
+ submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3);
+ submesh->indexData->is32bit = Read<bool>();
+
+ DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
+ DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
+ DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
+
+ // Index buffer
+ if (submesh->indexData->count > 0)
+ {
+ uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+ uint8_t *indexBuffer = ReadBytes(numBytes);
+ submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true));
+
+ DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount
+ << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit")
+ << " indexes of " << numBytes << " bytes");
+ }
+
+ // Vertex buffer if not referencing the shared geometry
+ if (!submesh->usesSharedVertexData)
+ {
+ id = ReadHeader();
+ if (id != M_GEOMETRY) {
+ throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false");
+ }
+
+ submesh->vertexData = new VertexData();
+ ReadGeometry(submesh->vertexData);
+ }
+
+ // Bone assignment, submesh operation and texture aliases
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_SUBMESH_OPERATION ||
+ id == M_SUBMESH_BONE_ASSIGNMENT ||
+ id == M_SUBMESH_TEXTURE_ALIAS))
+ {
+ switch(id)
+ {
+ case M_SUBMESH_OPERATION:
+ {
+ ReadSubMeshOperation(submesh);
+ break;
+ }
+ case M_SUBMESH_BONE_ASSIGNMENT:
+ {
+ ReadBoneAssignment(submesh->vertexData);
+ break;
+ }
+ case M_SUBMESH_TEXTURE_ALIAS:
+ {
+ ReadSubMeshTextureAlias(submesh);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ NormalizeBoneWeights(submesh->vertexData);
+
+ submesh->index = mesh->subMeshes.size();
+ mesh->subMeshes.push_back(submesh);
}
void OgreBinarySerializer::NormalizeBoneWeights(VertexData *vertexData) const
{
- if (!vertexData || vertexData->boneAssignments.empty())
- return;
-
- std::set<uint32_t> influencedVertices;
- for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) {
- influencedVertices.insert(baIter->vertexIndex);
- }
-
- /** Normalize bone weights.
- Some exporters wont care if the sum of all bone weights
- for a single vertex equals 1 or not, so validate here. */
- const float epsilon = 0.05f;
- for(std::set<uint32_t>::const_iterator iter=influencedVertices.begin(), end=influencedVertices.end(); iter != end; ++iter)
- {
- const uint32_t vertexIndex = (*iter);
-
- float sum = 0.0f;
- for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
- {
- if (baIter->vertexIndex == vertexIndex)
- sum += baIter->weight;
- }
- if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
- {
- for (VertexBoneAssignmentList::iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
- {
- if (baIter->vertexIndex == vertexIndex)
- baIter->weight /= sum;
- }
- }
- }
+ if (!vertexData || vertexData->boneAssignments.empty())
+ return;
+
+ std::set<uint32_t> influencedVertices;
+ for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) {
+ influencedVertices.insert(baIter->vertexIndex);
+ }
+
+ /** Normalize bone weights.
+ Some exporters wont care if the sum of all bone weights
+ for a single vertex equals 1 or not, so validate here. */
+ const float epsilon = 0.05f;
+ for (const uint32_t vertexIndex : influencedVertices)
+ {
+ float sum = 0.0f;
+ for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ sum += baIter->weight;
+ }
+ if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
+ {
+ for (auto &boneAssign : vertexData->boneAssignments)
+ {
+ if (boneAssign.vertexIndex == vertexIndex)
+ boneAssign.weight /= sum;
+ }
+ }
+ }
}
void OgreBinarySerializer::ReadSubMeshOperation(SubMesh *submesh)
{
- submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>());
+ submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>());
}
void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
{
- submesh->textureAliasName = ReadLine();
- submesh->textureAliasRef = ReadLine();
+ submesh->textureAliasName = ReadLine();
+ submesh->textureAliasRef = ReadLine();
}
void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
{
- uint16_t id = 0;
- uint16_t submeshIndex = 0;
-
- if (!AtEnd())
- {
- id = ReadHeader();
- while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT)
- {
- uint16_t submeshIndex = Read<uint16_t>();
- SubMesh *submesh = mesh->GetSubMesh(submeshIndex);
- if (!submesh) {
- throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file.");
- }
-
- submesh->name = ReadLine();
- DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'");
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ uint16_t id = 0;
+
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT)
+ {
+ uint16_t submeshIndex = Read<uint16_t>();
+ SubMesh *submesh = mesh->GetSubMesh(submeshIndex);
+ if (!submesh) {
+ throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file.");
+ }
+
+ submesh->name = ReadLine();
+ DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'");
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadGeometry(VertexData *dest)
{
- dest->count = Read<uint32_t>();
-
- DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
-
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() &&
- (id == M_GEOMETRY_VERTEX_DECLARATION ||
- id == M_GEOMETRY_VERTEX_BUFFER))
- {
- switch(id)
- {
- case M_GEOMETRY_VERTEX_DECLARATION:
- {
- ReadGeometryVertexDeclaration(dest);
- break;
- }
- case M_GEOMETRY_VERTEX_BUFFER:
- {
- ReadGeometryVertexBuffer(dest);
- break;
- }
- }
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ dest->count = Read<uint32_t>();
+
+ DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_GEOMETRY_VERTEX_DECLARATION ||
+ id == M_GEOMETRY_VERTEX_BUFFER))
+ {
+ switch(id)
+ {
+ case M_GEOMETRY_VERTEX_DECLARATION:
+ {
+ ReadGeometryVertexDeclaration(dest);
+ break;
+ }
+ case M_GEOMETRY_VERTEX_BUFFER:
+ {
+ ReadGeometryVertexBuffer(dest);
+ break;
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadGeometryVertexDeclaration(VertexData *dest)
{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT)
- {
- ReadGeometryVertexElement(dest);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT)
+ {
+ ReadGeometryVertexElement(dest);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest)
{
- VertexElement element;
- element.source = Read<uint16_t>();
- element.type = static_cast<VertexElement::Type>(Read<uint16_t>());
- element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>());
- element.offset = Read<uint16_t>();
- element.index = Read<uint16_t>();
+ VertexElement element;
+ element.source = Read<uint16_t>();
+ element.type = static_cast<VertexElement::Type>(Read<uint16_t>());
+ element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>());
+ element.offset = Read<uint16_t>();
+ element.index = Read<uint16_t>();
- DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type "
- << element.TypeToString() << " index=" << element.index << " source=" << element.source);
+ DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type "
+ << element.TypeToString() << " index=" << element.index << " source=" << element.source);
- dest->vertexElements.push_back(element);
+ dest->vertexElements.push_back(element);
}
void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
{
- uint16_t bindIndex = Read<uint16_t>();
- uint16_t vertexSize = Read<uint16_t>();
-
- uint16_t id = ReadHeader();
- if (id != M_GEOMETRY_VERTEX_BUFFER_DATA)
- throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER");
-
- if (dest->VertexSize(bindIndex) != vertexSize)
- throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER");
-
- size_t numBytes = dest->count * vertexSize;
- uint8_t *vertexBuffer = ReadBytes(numBytes);
- dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true));
-
- DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
+ uint16_t bindIndex = Read<uint16_t>();
+ uint16_t vertexSize = Read<uint16_t>();
+
+ uint16_t id = ReadHeader();
+ if (id != M_GEOMETRY_VERTEX_BUFFER_DATA)
+ throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER");
+
+ if (dest->VertexSize(bindIndex) != vertexSize)
+ throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER");
+
+ size_t numBytes = dest->count * vertexSize;
+ uint8_t *vertexBuffer = ReadBytes(numBytes);
+ dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true));
+
+ DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
}
-void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
+void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
{
- // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
-
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == M_EDGE_LIST_LOD)
- {
- m_reader->IncPtr(sizeof(uint16_t)); // lod index
- bool manual = Read<bool>();
-
- if (!manual)
- {
- m_reader->IncPtr(sizeof(uint8_t));
- uint32_t numTriangles = Read<uint32_t>();
- uint32_t numEdgeGroups = Read<uint32_t>();
-
- size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles;
- m_reader->IncPtr(skipBytes);
-
- for (size_t i=0; i<numEdgeGroups; ++i)
- {
- uint16_t id = ReadHeader();
- if (id != M_EDGE_GROUP)
- throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");
-
- m_reader->IncPtr(sizeof(uint32_t) * 3);
- uint32_t numEdges = Read<uint32_t>();
- for (size_t j=0; j<numEdges; ++j)
- {
- m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t));
- }
- }
- }
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_EDGE_LIST_LOD)
+ {
+ m_reader->IncPtr(sizeof(uint16_t)); // lod index
+ bool manual = Read<bool>();
+
+ if (!manual)
+ {
+ m_reader->IncPtr(sizeof(uint8_t));
+ uint32_t numTriangles = Read<uint32_t>();
+ uint32_t numEdgeGroups = Read<uint32_t>();
+
+ size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles;
+ m_reader->IncPtr(skipBytes);
+
+ for (size_t i=0; i<numEdgeGroups; ++i)
+ {
+ uint16_t id = ReadHeader();
+ if (id != M_EDGE_GROUP)
+ throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");
+
+ m_reader->IncPtr(sizeof(uint32_t) * 3);
+ uint32_t numEdges = Read<uint32_t>();
+ for (size_t j=0; j<numEdges; ++j)
+ {
+ m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t));
+ }
+ }
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadPoses(Mesh *mesh)
{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == M_POSE)
- {
- Pose *pose = new Pose();
- pose->name = ReadLine();
- pose->target = Read<uint16_t>();
- pose->hasNormals = Read<bool>();
-
- ReadPoseVertices(pose);
-
- mesh->poses.push_back(pose);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_POSE)
+ {
+ Pose *pose = new Pose();
+ pose->name = ReadLine();
+ pose->target = Read<uint16_t>();
+ pose->hasNormals = Read<bool>();
+
+ ReadPoseVertices(pose);
+
+ mesh->poses.push_back(pose);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadPoseVertices(Pose *pose)
{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == M_POSE_VERTEX)
- {
- Pose::Vertex v;
- v.index = Read<uint32_t>();
- ReadVector(v.offset);
- if (pose->hasNormals)
- ReadVector(v.normal);
-
- pose->vertices[v.index] = v;
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_POSE_VERTEX)
+ {
+ Pose::Vertex v;
+ v.index = Read<uint32_t>();
+ ReadVector(v.offset);
+ if (pose->hasNormals)
+ ReadVector(v.normal);
+
+ pose->vertices[v.index] = v;
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadAnimations(Mesh *mesh)
{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == M_ANIMATION)
- {
- Animation *anim = new Animation(mesh);
- anim->name = ReadLine();
- anim->length = Read<float>();
-
- ReadAnimation(anim);
-
- mesh->animations.push_back(anim);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == M_ANIMATION)
+ {
+ Animation *anim = new Animation(mesh);
+ anim->name = ReadLine();
+ anim->length = Read<float>();
+
+ ReadAnimation(anim);
+
+ mesh->animations.push_back(anim);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadAnimation(Animation *anim)
-{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- if (id == M_ANIMATION_BASEINFO)
- {
- anim->baseName = ReadLine();
- anim->baseTime = Read<float>();
-
- // Advance to first track
- id = ReadHeader();
- }
-
- while (!AtEnd() && id == M_ANIMATION_TRACK)
- {
- VertexAnimationTrack track;
- track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>());
- track.target = Read<uint16_t>();
-
- ReadAnimationKeyFrames(anim, &track);
-
- anim->tracks.push_back(track);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+{
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ if (id == M_ANIMATION_BASEINFO)
+ {
+ anim->baseName = ReadLine();
+ anim->baseTime = Read<float>();
+
+ // Advance to first track
+ id = ReadHeader();
+ }
+
+ while (!AtEnd() && id == M_ANIMATION_TRACK)
+ {
+ VertexAnimationTrack track;
+ track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>());
+ track.target = Read<uint16_t>();
+
+ ReadAnimationKeyFrames(anim, &track);
+
+ anim->tracks.push_back(track);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
void OgreBinarySerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track)
{
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- while (!AtEnd() &&
- (id == M_ANIMATION_MORPH_KEYFRAME ||
- id == M_ANIMATION_POSE_KEYFRAME))
- {
- if (id == M_ANIMATION_MORPH_KEYFRAME)
- {
- MorphKeyFrame kf;
- kf.timePos = Read<float>();
- bool hasNormals = Read<bool>();
-
- size_t vertexCount = anim->AssociatedVertexData(track)->count;
- size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3);
- size_t numBytes = vertexCount * vertexSize;
-
- uint8_t *morphBuffer = ReadBytes(numBytes);
- kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true));
-
- track->morphKeyFrames.push_back(kf);
- }
- else if (id == M_ANIMATION_POSE_KEYFRAME)
- {
- PoseKeyFrame kf;
- kf.timePos = Read<float>();
-
- if (!AtEnd())
- {
- id = ReadHeader();
- while (!AtEnd() && id == M_ANIMATION_POSE_REF)
- {
- PoseRef pr;
- pr.index = Read<uint16_t>();
- pr.influence = Read<float>();
- kf.references.push_back(pr);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
-
- track->poseKeyFrames.push_back(kf);
- }
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ while (!AtEnd() &&
+ (id == M_ANIMATION_MORPH_KEYFRAME ||
+ id == M_ANIMATION_POSE_KEYFRAME))
+ {
+ if (id == M_ANIMATION_MORPH_KEYFRAME)
+ {
+ MorphKeyFrame kf;
+ kf.timePos = Read<float>();
+ bool hasNormals = Read<bool>();
+
+ size_t vertexCount = anim->AssociatedVertexData(track)->count;
+ size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3);
+ size_t numBytes = vertexCount * vertexSize;
+
+ uint8_t *morphBuffer = ReadBytes(numBytes);
+ kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true));
+
+ track->morphKeyFrames.push_back(kf);
+ }
+ else if (id == M_ANIMATION_POSE_KEYFRAME)
+ {
+ PoseKeyFrame kf;
+ kf.timePos = Read<float>();
+
+ if (!AtEnd())
+ {
+ id = ReadHeader();
+ while (!AtEnd() && id == M_ANIMATION_POSE_REF)
+ {
+ PoseRef pr;
+ pr.index = Read<uint16_t>();
+ pr.influence = Read<float>();
+ kf.references.push_back(pr);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ track->poseKeyFrames.push_back(kf);
+ }
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
}
// Skeleton
bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
{
- if (!mesh || mesh->skeletonRef.empty())
- return false;
-
- // Highly unusual to see in read world cases but support
- // binary mesh referencing a XML skeleton file.
- if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false))
- {
- OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
- return false;
- }
-
- MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
-
- Skeleton *skeleton = new Skeleton();
- OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
- serializer.ReadSkeleton(skeleton);
- mesh->skeleton = skeleton;
- return true;
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ // Highly unusual to see in read world cases but support
+ // binary mesh referencing a XML skeleton file.
+ if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false))
+ {
+ OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
+ return false;
+ }
+
+ MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+
+ Skeleton *skeleton = new Skeleton();
+ OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
}
bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
{
- if (!mesh || mesh->skeletonRef.empty())
- return false;
-
- MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
- if (!reader.get())
- return false;
-
- Skeleton *skeleton = new Skeleton();
- OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
- serializer.ReadSkeleton(skeleton);
- mesh->skeleton = skeleton;
- return true;
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
}
MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
{
- if (!EndsWith(filename, ".skeleton", false))
- {
- DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
- return MemoryStreamReaderPtr();
- }
-
- if (!pIOHandler->Exists(filename))
- {
- DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
- return MemoryStreamReaderPtr();
- }
-
- IOStream *f = pIOHandler->Open(filename, "rb");
- if (!f) {
- throw DeadlyImportError("Failed to open skeleton file " + filename);
- }
-
- return MemoryStreamReaderPtr(new MemoryStreamReader(f));
+ if (!EndsWith(filename, ".skeleton", false))
+ {
+ DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
+ return MemoryStreamReaderPtr();
+ }
+
+ if (!pIOHandler->Exists(filename))
+ {
+ DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
+ return MemoryStreamReaderPtr();
+ }
+
+ IOStream *f = pIOHandler->Open(filename, "rb");
+ if (!f) {
+ throw DeadlyImportError("Failed to open skeleton file " + filename);
+ }
+
+ return MemoryStreamReaderPtr(new MemoryStreamReader(f));
}
void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton)
{
- uint16_t id = ReadHeader(false);
- if (id != HEADER_CHUNK_ID) {
- throw DeadlyExportError("Invalid Ogre Skeleton file header.");
- }
-
- // This deserialization supports both versions of the skeleton spec
- std::string version = ReadLine();
- if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1)
- {
- throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer."
- << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1);
- }
-
- DefaultLogger::get()->debug("Reading Skeleton");
-
- bool firstBone = true;
- bool firstAnim = true;
-
- while (!AtEnd())
- {
- id = ReadHeader();
- switch(id)
- {
- case SKELETON_BLENDMODE:
- {
- skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>());
- break;
- }
- case SKELETON_BONE:
- {
- if (firstBone)
- {
- DefaultLogger::get()->debug(" - Bones");
- firstBone = false;
- }
-
- ReadBone(skeleton);
- break;
- }
- case SKELETON_BONE_PARENT:
- {
- ReadBoneParent(skeleton);
- break;
- }
- case SKELETON_ANIMATION:
- {
- if (firstAnim)
- {
- DefaultLogger::get()->debug(" - Animations");
- firstAnim = false;
- }
-
- ReadSkeletonAnimation(skeleton);
- break;
- }
- case SKELETON_ANIMATION_LINK:
- {
- ReadSkeletonAnimationLink(skeleton);
- break;
- }
- }
- }
-
- // Calculate bone matrices for root bones. Recursively calculates their children.
- for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
- {
- Bone *bone = skeleton->bones[i];
- if (!bone->IsParented())
- bone->CalculateWorldMatrixAndDefaultPose(skeleton);
- }
+ uint16_t id = ReadHeader(false);
+ if (id != HEADER_CHUNK_ID) {
+ throw DeadlyExportError("Invalid Ogre Skeleton file header.");
+ }
+
+ // This deserialization supports both versions of the skeleton spec
+ std::string version = ReadLine();
+ if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1)
+ {
+ throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer."
+ << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1);
+ }
+
+ DefaultLogger::get()->debug("Reading Skeleton");
+
+ bool firstBone = true;
+ bool firstAnim = true;
+
+ while (!AtEnd())
+ {
+ id = ReadHeader();
+ switch(id)
+ {
+ case SKELETON_BLENDMODE:
+ {
+ skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>());
+ break;
+ }
+ case SKELETON_BONE:
+ {
+ if (firstBone)
+ {
+ DefaultLogger::get()->debug(" - Bones");
+ firstBone = false;
+ }
+
+ ReadBone(skeleton);
+ break;
+ }
+ case SKELETON_BONE_PARENT:
+ {
+ ReadBoneParent(skeleton);
+ break;
+ }
+ case SKELETON_ANIMATION:
+ {
+ if (firstAnim)
+ {
+ DefaultLogger::get()->debug(" - Animations");
+ firstAnim = false;
+ }
+
+ ReadSkeletonAnimation(skeleton);
+ break;
+ }
+ case SKELETON_ANIMATION_LINK:
+ {
+ ReadSkeletonAnimationLink(skeleton);
+ break;
+ }
+ }
+ }
+
+ // Calculate bone matrices for root bones. Recursively calculates their children.
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *bone = skeleton->bones[i];
+ if (!bone->IsParented())
+ bone->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
}
void OgreBinarySerializer::ReadBone(Skeleton *skeleton)
{
- Bone *bone = new Bone();
- bone->name = ReadLine();
- bone->id = Read<uint16_t>();
+ Bone *bone = new Bone();
+ bone->name = ReadLine();
+ bone->id = Read<uint16_t>();
- // Pos and rot
- ReadVector(bone->position);
- ReadQuaternion(bone->rotation);
+ // Pos and rot
+ ReadVector(bone->position);
+ ReadQuaternion(bone->rotation);
- // Scale (optional)
- if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE)
- ReadVector(bone->scale);
+ // Scale (optional)
+ if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE)
+ ReadVector(bone->scale);
- // Bone indexes need to start from 0 and be contiguous
- if (bone->id != skeleton->bones.size()) {
- throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id);
- }
+ // Bone indexes need to start from 0 and be contiguous
+ if (bone->id != skeleton->bones.size()) {
+ throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id);
+ }
- DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name);
+ DefaultLogger::get()->debug(Formatter::format() << " " << bone->id << " " << bone->name);
- skeleton->bones.push_back(bone);
+ skeleton->bones.push_back(bone);
}
void OgreBinarySerializer::ReadBoneParent(Skeleton *skeleton)
{
- uint16_t childId = Read<uint16_t>();
- uint16_t parentId = Read<uint16_t>();
-
- Bone *child = skeleton->BoneById(childId);
- Bone *parent = skeleton->BoneById(parentId);
-
- if (child && parent)
- parent->AddChild(child);
- else
- throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId);
+ uint16_t childId = Read<uint16_t>();
+ uint16_t parentId = Read<uint16_t>();
+
+ Bone *child = skeleton->BoneById(childId);
+ Bone *parent = skeleton->BoneById(parentId);
+
+ if (child && parent)
+ parent->AddChild(child);
+ else
+ throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId);
}
void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
{
- Animation *anim = new Animation(skeleton);
- anim->name = ReadLine();
- anim->length = Read<float>();
-
- if (!AtEnd())
- {
- uint16_t id = ReadHeader();
- if (id == SKELETON_ANIMATION_BASEINFO)
- {
- anim->baseName = ReadLine();
- anim->baseTime = Read<float>();
-
- // Advance to first track
- id = ReadHeader();
- }
-
- while (!AtEnd() && id == SKELETON_ANIMATION_TRACK)
- {
- ReadSkeletonAnimationTrack(skeleton, anim);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
- }
-
- skeleton->animations.push_back(anim);
-
- DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
+ Animation *anim = new Animation(skeleton);
+ anim->name = ReadLine();
+ anim->length = Read<float>();
+
+ if (!AtEnd())
+ {
+ uint16_t id = ReadHeader();
+ if (id == SKELETON_ANIMATION_BASEINFO)
+ {
+ anim->baseName = ReadLine();
+ anim->baseTime = Read<float>();
+
+ // Advance to first track
+ id = ReadHeader();
+ }
+
+ while (!AtEnd() && id == SKELETON_ANIMATION_TRACK)
+ {
+ ReadSkeletonAnimationTrack(skeleton, anim);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+ }
+
+ skeleton->animations.push_back(anim);
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
}
-void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest)
+void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
{
- uint16_t boneId = Read<uint16_t>();
- Bone *bone = dest->parentSkeleton->BoneById(boneId);
- if (!bone) {
- throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton");
- }
-
- VertexAnimationTrack track;
- track.type = VertexAnimationTrack::VAT_TRANSFORM;
- track.boneName = bone->name;
-
- uint16_t id = ReadHeader();
- while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME)
- {
- ReadSkeletonAnimationKeyFrame(&track);
-
- if (!AtEnd())
- id = ReadHeader();
- }
- if (!AtEnd())
- RollbackHeader();
-
- dest->tracks.push_back(track);
+ uint16_t boneId = Read<uint16_t>();
+ Bone *bone = dest->parentSkeleton->BoneById(boneId);
+ if (!bone) {
+ throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton");
+ }
+
+ VertexAnimationTrack track;
+ track.type = VertexAnimationTrack::VAT_TRANSFORM;
+ track.boneName = bone->name;
+
+ uint16_t id = ReadHeader();
+ while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME)
+ {
+ ReadSkeletonAnimationKeyFrame(&track);
+
+ if (!AtEnd())
+ id = ReadHeader();
+ }
+ if (!AtEnd())
+ RollbackHeader();
+
+ dest->tracks.push_back(track);
}
void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest)
{
- TransformKeyFrame keyframe;
- keyframe.timePos = Read<float>();
-
- // Rot and pos
- ReadQuaternion(keyframe.rotation);
- ReadVector(keyframe.position);
-
- // Scale (optional)
- if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE)
- ReadVector(keyframe.scale);
-
- dest->transformKeyFrames.push_back(keyframe);
+ TransformKeyFrame keyframe;
+ keyframe.timePos = Read<float>();
+
+ // Rot and pos
+ ReadQuaternion(keyframe.rotation);
+ ReadVector(keyframe.position);
+
+ // Scale (optional)
+ if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE)
+ ReadVector(keyframe.scale);
+
+ dest->transformKeyFrames.push_back(keyframe);
}
-void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
+void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
{
- // Skip bounds, not compatible with Assimp.
- ReadLine(); // skeleton name
- SkipBytes(sizeof(float) * 3); // scale
+ // Skip bounds, not compatible with Assimp.
+ ReadLine(); // skeleton name
+ SkipBytes(sizeof(float) * 3); // scale
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreBinarySerializer.h b/src/3rdparty/assimp/code/OgreBinarySerializer.h
index 69db4b722..067e36a63 100644
--- a/src/3rdparty/assimp/code/OgreBinarySerializer.h
+++ b/src/3rdparty/assimp/code/OgreBinarySerializer.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreStructs.h"
+#include "StreamReader.h"
namespace Assimp
{
@@ -51,364 +52,368 @@ namespace Ogre
{
typedef Assimp::StreamReaderLE MemoryStreamReader;
-typedef boost::shared_ptr<MemoryStreamReader> MemoryStreamReaderPtr;
+typedef std::shared_ptr<MemoryStreamReader> MemoryStreamReaderPtr;
class OgreBinarySerializer
{
public:
- /// Imports mesh and returns the result.
- /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
- static Mesh *ImportMesh(MemoryStreamReader *reader);
+ /// Imports mesh and returns the result.
+ /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
+ static Mesh *ImportMesh(MemoryStreamReader *reader);
- /// Imports skeleton to @c mesh into Mesh::skeleton.
- /** If mesh does not have a skeleton reference or the skeleton file
- cannot be found it is not a fatal DeadlyImportError.
- @return If skeleton import was successful. */
- static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
- static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
+ /// Imports skeleton to @c mesh into Mesh::skeleton.
+ /** If mesh does not have a skeleton reference or the skeleton file
+ cannot be found it is not a fatal DeadlyImportError.
+ @return If skeleton import was successful. */
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
private:
- enum AssetMode
- {
- AM_Mesh,
- AM_Skeleton
- };
-
- OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
- m_reader(reader),
- m_currentLen(0),
- assetMode(mode)
- {
- }
-
- static MemoryStreamReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
-
- // Header
-
- uint16_t ReadHeader(bool readLen = true);
- void RollbackHeader();
-
- // Mesh
-
- void ReadMesh(Mesh *mesh);
- void ReadMeshLodInfo(Mesh *mesh);
- void ReadMeshSkeletonLink(Mesh *mesh);
- void ReadMeshBounds(Mesh *mesh);
- void ReadMeshExtremes(Mesh *mesh);
-
- void ReadSubMesh(Mesh *mesh);
- void ReadSubMeshNames(Mesh *mesh);
- void ReadSubMeshOperation(SubMesh *submesh);
- void ReadSubMeshTextureAlias(SubMesh *submesh);
-
- void ReadBoneAssignment(VertexData *dest);
-
- void ReadGeometry(VertexData *dest);
- void ReadGeometryVertexDeclaration(VertexData *dest);
- void ReadGeometryVertexElement(VertexData *dest);
- void ReadGeometryVertexBuffer(VertexData *dest);
-
- void ReadEdgeList(Mesh *mesh);
- void ReadPoses(Mesh *mesh);
- void ReadPoseVertices(Pose *pose);
-
- void ReadAnimations(Mesh *mesh);
- void ReadAnimation(Animation *anim);
- void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track);
-
- void NormalizeBoneWeights(VertexData *vertexData) const;
-
- // Skeleton
-
- void ReadSkeleton(Skeleton *skeleton);
-
- void ReadBone(Skeleton *skeleton);
- void ReadBoneParent(Skeleton *skeleton);
-
- void ReadSkeletonAnimation(Skeleton *skeleton);
- void ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest);
- void ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest);
- void ReadSkeletonAnimationLink(Skeleton *skeleton);
-
- // Reader utils
- bool AtEnd() const;
-
- template<typename T>
- inline T Read();
-
- void ReadBytes(char *dest, size_t numBytes);
- void ReadBytes(uint8_t *dest, size_t numBytes);
- void ReadBytes(void *dest, size_t numBytes);
- uint8_t *ReadBytes(size_t numBytes);
-
- void ReadVector(aiVector3D &vec);
- void ReadQuaternion(aiQuaternion &quat);
-
- std::string ReadString(size_t len);
- std::string ReadLine();
-
- void SkipBytes(size_t numBytes);
-
- uint32_t m_currentLen;
- MemoryStreamReader *m_reader;
-
- AssetMode assetMode;
+ enum AssetMode
+ {
+ AM_Mesh,
+ AM_Skeleton
+ };
+
+ OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
+ m_currentLen(0),
+ m_reader(reader),
+ assetMode(mode)
+ {
+ }
+
+ static MemoryStreamReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
+
+ // Header
+
+ uint16_t ReadHeader(bool readLen = true);
+ void RollbackHeader();
+
+ // Mesh
+
+ void ReadMesh(Mesh *mesh);
+ void ReadMeshLodInfo(Mesh *mesh);
+ void ReadMeshSkeletonLink(Mesh *mesh);
+ void ReadMeshBounds(Mesh *mesh);
+ void ReadMeshExtremes(Mesh *mesh);
+
+ void ReadSubMesh(Mesh *mesh);
+ void ReadSubMeshNames(Mesh *mesh);
+ void ReadSubMeshOperation(SubMesh *submesh);
+ void ReadSubMeshTextureAlias(SubMesh *submesh);
+
+ void ReadBoneAssignment(VertexData *dest);
+
+ void ReadGeometry(VertexData *dest);
+ void ReadGeometryVertexDeclaration(VertexData *dest);
+ void ReadGeometryVertexElement(VertexData *dest);
+ void ReadGeometryVertexBuffer(VertexData *dest);
+
+ void ReadEdgeList(Mesh *mesh);
+ void ReadPoses(Mesh *mesh);
+ void ReadPoseVertices(Pose *pose);
+
+ void ReadAnimations(Mesh *mesh);
+ void ReadAnimation(Animation *anim);
+ void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track);
+
+ void NormalizeBoneWeights(VertexData *vertexData) const;
+
+ // Skeleton
+
+ void ReadSkeleton(Skeleton *skeleton);
+
+ void ReadBone(Skeleton *skeleton);
+ void ReadBoneParent(Skeleton *skeleton);
+
+ void ReadSkeletonAnimation(Skeleton *skeleton);
+ void ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest);
+ void ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest);
+ void ReadSkeletonAnimationLink(Skeleton *skeleton);
+
+ // Reader utils
+ bool AtEnd() const;
+
+ template<typename T>
+ inline T Read();
+
+ void ReadBytes(char *dest, size_t numBytes);
+ void ReadBytes(uint8_t *dest, size_t numBytes);
+ void ReadBytes(void *dest, size_t numBytes);
+ uint8_t *ReadBytes(size_t numBytes);
+
+ void ReadVector(aiVector3D &vec);
+ void ReadQuaternion(aiQuaternion &quat);
+
+ std::string ReadString(size_t len);
+ std::string ReadLine();
+
+ void SkipBytes(size_t numBytes);
+
+ uint32_t m_currentLen;
+ MemoryStreamReader *m_reader;
+
+ AssetMode assetMode;
};
enum MeshChunkId
{
- M_HEADER = 0x1000,
- // char* version : Version number check
- M_MESH = 0x3000,
- // bool skeletallyAnimated // important flag which affects h/w buffer policies
- // Optional M_GEOMETRY chunk
- M_SUBMESH = 0x4000,
- // char* materialName
- // bool useSharedVertices
- // unsigned int indexCount
- // bool indexes32Bit
- // unsigned int* faceVertexIndices (indexCount)
- // OR
- // unsigned short* faceVertexIndices (indexCount)
- // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
- M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing
- // unsigned short operationType
- M_SUBMESH_BONE_ASSIGNMENT = 0x4100,
- // Optional bone weights (repeating section)
- // unsigned int vertexIndex;
- // unsigned short boneIndex;
- // float weight;
- // Optional chunk that matches a texture name to an alias
- // a texture alias is sent to the submesh material to use this texture name
- // instead of the one in the texture unit with a matching alias name
- M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section
- // char* aliasName;
- // char* textureName;
-
- M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH
- // unsigned int vertexCount
- M_GEOMETRY_VERTEX_DECLARATION = 0x5100,
- M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section
- // unsigned short source; // buffer bind source
- // unsigned short type; // VertexElementType
- // unsigned short semantic; // VertexElementSemantic
- // unsigned short offset; // start offset in buffer in bytes
- // unsigned short index; // index of the semantic (for colours and texture coords)
- M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section
- // unsigned short bindIndex; // Index to bind this buffer to
- // unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index
- M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210,
- // raw buffer data
- M_MESH_SKELETON_LINK = 0x6000,
- // Optional link to skeleton
- // char* skeletonName : name of .skeleton to use
- M_MESH_BONE_ASSIGNMENT = 0x7000,
- // Optional bone weights (repeating section)
- // unsigned int vertexIndex;
- // unsigned short boneIndex;
- // float weight;
- M_MESH_LOD = 0x8000,
- // Optional LOD information
- // string strategyName;
- // unsigned short numLevels;
- // bool manual; (true for manual alternate meshes, false for generated)
- M_MESH_LOD_USAGE = 0x8100,
- // Repeating section, ordered in increasing depth
- // NB LOD 0 (full detail from 0 depth) is omitted
- // LOD value - this is a distance, a pixel count etc, based on strategy
- // float lodValue;
- M_MESH_LOD_MANUAL = 0x8110,
- // Required if M_MESH_LOD section manual = true
- // String manualMeshName;
- M_MESH_LOD_GENERATED = 0x8120,
- // Required if M_MESH_LOD section manual = false
- // Repeating section (1 per submesh)
- // unsigned int indexCount;
- // bool indexes32Bit
- // unsigned short* faceIndexes; (indexCount)
- // OR
- // unsigned int* faceIndexes; (indexCount)
- M_MESH_BOUNDS = 0x9000,
- // float minx, miny, minz
- // float maxx, maxy, maxz
- // float radius
-
- // Added By DrEvil
- // optional chunk that contains a table of submesh indexes and the names of
- // the sub-meshes.
- M_SUBMESH_NAME_TABLE = 0xA000,
- // Subchunks of the name table. Each chunk contains an index & string
- M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100,
- // short index
- // char* name
- // Optional chunk which stores precomputed edge data
- M_EDGE_LISTS = 0xB000,
- // Each LOD has a separate edge list
- M_EDGE_LIST_LOD = 0xB100,
- // unsigned short lodIndex
- // bool isManual // If manual, no edge data here, loaded from manual mesh
- // bool isClosed
- // unsigned long numTriangles
- // unsigned long numEdgeGroups
- // Triangle* triangleList
- // unsigned long indexSet
- // unsigned long vertexSet
- // unsigned long vertIndex[3]
- // unsigned long sharedVertIndex[3]
- // float normal[4]
-
- M_EDGE_GROUP = 0xB110,
- // unsigned long vertexSet
- // unsigned long triStart
- // unsigned long triCount
- // unsigned long numEdges
- // Edge* edgeList
- // unsigned long triIndex[2]
- // unsigned long vertIndex[2]
- // unsigned long sharedVertIndex[2]
- // bool degenerate
- // Optional poses section, referred to by pose keyframes
- M_POSES = 0xC000,
- M_POSE = 0xC100,
- // char* name (may be blank)
- // unsigned short target // 0 for shared geometry,
- // 1+ for submesh index + 1
- // bool includesNormals [1.8+]
- M_POSE_VERTEX = 0xC111,
- // unsigned long vertexIndex
- // float xoffset, yoffset, zoffset
- // float xnormal, ynormal, znormal (optional, 1.8+)
- // Optional vertex animation chunk
- M_ANIMATIONS = 0xD000,
- M_ANIMATION = 0xD100,
- // char* name
- // float length
- M_ANIMATION_BASEINFO = 0xD105,
- // [Optional] base keyframe information (pose animation only)
- // char* baseAnimationName (blank for self)
- // float baseKeyFrameTime
- M_ANIMATION_TRACK = 0xD110,
- // unsigned short type // 1 == morph, 2 == pose
- // unsigned short target // 0 for shared geometry,
- // 1+ for submesh index + 1
- M_ANIMATION_MORPH_KEYFRAME = 0xD111,
- // float time
- // bool includesNormals [1.8+]
- // float x,y,z // repeat by number of vertices in original geometry
- M_ANIMATION_POSE_KEYFRAME = 0xD112,
- // float time
- M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses
- // unsigned short poseIndex
- // float influence
- // Optional submesh extreme vertex list chink
- M_TABLE_EXTREMES = 0xE000,
- // unsigned short submesh_index;
- // float extremes [n_extremes][3];
+ M_HEADER = 0x1000,
+ // char* version : Version number check
+ M_MESH = 0x3000,
+ // bool skeletallyAnimated // important flag which affects h/w buffer policies
+ // Optional M_GEOMETRY chunk
+ M_SUBMESH = 0x4000,
+ // char* materialName
+ // bool useSharedVertices
+ // unsigned int indexCount
+ // bool indexes32Bit
+ // unsigned int* faceVertexIndices (indexCount)
+ // OR
+ // unsigned short* faceVertexIndices (indexCount)
+ // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
+ M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing
+ // unsigned short operationType
+ M_SUBMESH_BONE_ASSIGNMENT = 0x4100,
+ // Optional bone weights (repeating section)
+ // unsigned int vertexIndex;
+ // unsigned short boneIndex;
+ // float weight;
+ // Optional chunk that matches a texture name to an alias
+ // a texture alias is sent to the submesh material to use this texture name
+ // instead of the one in the texture unit with a matching alias name
+ M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section
+ // char* aliasName;
+ // char* textureName;
+
+ M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH
+ // unsigned int vertexCount
+ M_GEOMETRY_VERTEX_DECLARATION = 0x5100,
+ M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section
+ // unsigned short source; // buffer bind source
+ // unsigned short type; // VertexElementType
+ // unsigned short semantic; // VertexElementSemantic
+ // unsigned short offset; // start offset in buffer in bytes
+ // unsigned short index; // index of the semantic (for colours and texture coords)
+ M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section
+ // unsigned short bindIndex; // Index to bind this buffer to
+ // unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index
+ M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210,
+ // raw buffer data
+ M_MESH_SKELETON_LINK = 0x6000,
+ // Optional link to skeleton
+ // char* skeletonName : name of .skeleton to use
+ M_MESH_BONE_ASSIGNMENT = 0x7000,
+ // Optional bone weights (repeating section)
+ // unsigned int vertexIndex;
+ // unsigned short boneIndex;
+ // float weight;
+ M_MESH_LOD = 0x8000,
+ // Optional LOD information
+ // string strategyName;
+ // unsigned short numLevels;
+ // bool manual; (true for manual alternate meshes, false for generated)
+ M_MESH_LOD_USAGE = 0x8100,
+ // Repeating section, ordered in increasing depth
+ // NB LOD 0 (full detail from 0 depth) is omitted
+ // LOD value - this is a distance, a pixel count etc, based on strategy
+ // float lodValue;
+ M_MESH_LOD_MANUAL = 0x8110,
+ // Required if M_MESH_LOD section manual = true
+ // String manualMeshName;
+ M_MESH_LOD_GENERATED = 0x8120,
+ // Required if M_MESH_LOD section manual = false
+ // Repeating section (1 per submesh)
+ // unsigned int indexCount;
+ // bool indexes32Bit
+ // unsigned short* faceIndexes; (indexCount)
+ // OR
+ // unsigned int* faceIndexes; (indexCount)
+ M_MESH_BOUNDS = 0x9000,
+ // float minx, miny, minz
+ // float maxx, maxy, maxz
+ // float radius
+
+ // Added By DrEvil
+ // optional chunk that contains a table of submesh indexes and the names of
+ // the sub-meshes.
+ M_SUBMESH_NAME_TABLE = 0xA000,
+ // Subchunks of the name table. Each chunk contains an index & string
+ M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100,
+ // short index
+ // char* name
+ // Optional chunk which stores precomputed edge data
+ M_EDGE_LISTS = 0xB000,
+ // Each LOD has a separate edge list
+ M_EDGE_LIST_LOD = 0xB100,
+ // unsigned short lodIndex
+ // bool isManual // If manual, no edge data here, loaded from manual mesh
+ // bool isClosed
+ // unsigned long numTriangles
+ // unsigned long numEdgeGroups
+ // Triangle* triangleList
+ // unsigned long indexSet
+ // unsigned long vertexSet
+ // unsigned long vertIndex[3]
+ // unsigned long sharedVertIndex[3]
+ // float normal[4]
+
+ M_EDGE_GROUP = 0xB110,
+ // unsigned long vertexSet
+ // unsigned long triStart
+ // unsigned long triCount
+ // unsigned long numEdges
+ // Edge* edgeList
+ // unsigned long triIndex[2]
+ // unsigned long vertIndex[2]
+ // unsigned long sharedVertIndex[2]
+ // bool degenerate
+ // Optional poses section, referred to by pose keyframes
+ M_POSES = 0xC000,
+ M_POSE = 0xC100,
+ // char* name (may be blank)
+ // unsigned short target // 0 for shared geometry,
+ // 1+ for submesh index + 1
+ // bool includesNormals [1.8+]
+ M_POSE_VERTEX = 0xC111,
+ // unsigned long vertexIndex
+ // float xoffset, yoffset, zoffset
+ // float xnormal, ynormal, znormal (optional, 1.8+)
+ // Optional vertex animation chunk
+ M_ANIMATIONS = 0xD000,
+ M_ANIMATION = 0xD100,
+ // char* name
+ // float length
+ M_ANIMATION_BASEINFO = 0xD105,
+ // [Optional] base keyframe information (pose animation only)
+ // char* baseAnimationName (blank for self)
+ // float baseKeyFrameTime
+ M_ANIMATION_TRACK = 0xD110,
+ // unsigned short type // 1 == morph, 2 == pose
+ // unsigned short target // 0 for shared geometry,
+ // 1+ for submesh index + 1
+ M_ANIMATION_MORPH_KEYFRAME = 0xD111,
+ // float time
+ // bool includesNormals [1.8+]
+ // float x,y,z // repeat by number of vertices in original geometry
+ M_ANIMATION_POSE_KEYFRAME = 0xD112,
+ // float time
+ M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses
+ // unsigned short poseIndex
+ // float influence
+ // Optional submesh extreme vertex list chink
+ M_TABLE_EXTREMES = 0xE000
+ // unsigned short submesh_index;
+ // float extremes [n_extremes][3];
};
+/*
static std::string MeshHeaderToString(MeshChunkId id)
{
- switch(id)
- {
- case M_HEADER: return "HEADER";
- case M_MESH: return "MESH";
- case M_SUBMESH: return "SUBMESH";
- case M_SUBMESH_OPERATION: return "SUBMESH_OPERATION";
- case M_SUBMESH_BONE_ASSIGNMENT: return "SUBMESH_BONE_ASSIGNMENT";
- case M_SUBMESH_TEXTURE_ALIAS: return "SUBMESH_TEXTURE_ALIAS";
- case M_GEOMETRY: return "GEOMETRY";
- case M_GEOMETRY_VERTEX_DECLARATION: return "GEOMETRY_VERTEX_DECLARATION";
- case M_GEOMETRY_VERTEX_ELEMENT: return "GEOMETRY_VERTEX_ELEMENT";
- case M_GEOMETRY_VERTEX_BUFFER: return "GEOMETRY_VERTEX_BUFFER";
- case M_GEOMETRY_VERTEX_BUFFER_DATA: return "GEOMETRY_VERTEX_BUFFER_DATA";
- case M_MESH_SKELETON_LINK: return "MESH_SKELETON_LINK";
- case M_MESH_BONE_ASSIGNMENT: return "MESH_BONE_ASSIGNMENT";
- case M_MESH_LOD: return "MESH_LOD";
- case M_MESH_LOD_USAGE: return "MESH_LOD_USAGE";
- case M_MESH_LOD_MANUAL: return "MESH_LOD_MANUAL";
- case M_MESH_LOD_GENERATED: return "MESH_LOD_GENERATED";
- case M_MESH_BOUNDS: return "MESH_BOUNDS";
- case M_SUBMESH_NAME_TABLE: return "SUBMESH_NAME_TABLE";
- case M_SUBMESH_NAME_TABLE_ELEMENT: return "SUBMESH_NAME_TABLE_ELEMENT";
- case M_EDGE_LISTS: return "EDGE_LISTS";
- case M_EDGE_LIST_LOD: return "EDGE_LIST_LOD";
- case M_EDGE_GROUP: return "EDGE_GROUP";
- case M_POSES: return "POSES";
- case M_POSE: return "POSE";
- case M_POSE_VERTEX: return "POSE_VERTEX";
- case M_ANIMATIONS: return "ANIMATIONS";
- case M_ANIMATION: return "ANIMATION";
- case M_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
- case M_ANIMATION_TRACK: return "ANIMATION_TRACK";
- case M_ANIMATION_MORPH_KEYFRAME: return "ANIMATION_MORPH_KEYFRAME";
- case M_ANIMATION_POSE_KEYFRAME: return "ANIMATION_POSE_KEYFRAME";
- case M_ANIMATION_POSE_REF: return "ANIMATION_POSE_REF";
- case M_TABLE_EXTREMES: return "TABLE_EXTREMES";
- }
- return "Unknown_MeshChunkId";
+ switch(id)
+ {
+ case M_HEADER: return "HEADER";
+ case M_MESH: return "MESH";
+ case M_SUBMESH: return "SUBMESH";
+ case M_SUBMESH_OPERATION: return "SUBMESH_OPERATION";
+ case M_SUBMESH_BONE_ASSIGNMENT: return "SUBMESH_BONE_ASSIGNMENT";
+ case M_SUBMESH_TEXTURE_ALIAS: return "SUBMESH_TEXTURE_ALIAS";
+ case M_GEOMETRY: return "GEOMETRY";
+ case M_GEOMETRY_VERTEX_DECLARATION: return "GEOMETRY_VERTEX_DECLARATION";
+ case M_GEOMETRY_VERTEX_ELEMENT: return "GEOMETRY_VERTEX_ELEMENT";
+ case M_GEOMETRY_VERTEX_BUFFER: return "GEOMETRY_VERTEX_BUFFER";
+ case M_GEOMETRY_VERTEX_BUFFER_DATA: return "GEOMETRY_VERTEX_BUFFER_DATA";
+ case M_MESH_SKELETON_LINK: return "MESH_SKELETON_LINK";
+ case M_MESH_BONE_ASSIGNMENT: return "MESH_BONE_ASSIGNMENT";
+ case M_MESH_LOD: return "MESH_LOD";
+ case M_MESH_LOD_USAGE: return "MESH_LOD_USAGE";
+ case M_MESH_LOD_MANUAL: return "MESH_LOD_MANUAL";
+ case M_MESH_LOD_GENERATED: return "MESH_LOD_GENERATED";
+ case M_MESH_BOUNDS: return "MESH_BOUNDS";
+ case M_SUBMESH_NAME_TABLE: return "SUBMESH_NAME_TABLE";
+ case M_SUBMESH_NAME_TABLE_ELEMENT: return "SUBMESH_NAME_TABLE_ELEMENT";
+ case M_EDGE_LISTS: return "EDGE_LISTS";
+ case M_EDGE_LIST_LOD: return "EDGE_LIST_LOD";
+ case M_EDGE_GROUP: return "EDGE_GROUP";
+ case M_POSES: return "POSES";
+ case M_POSE: return "POSE";
+ case M_POSE_VERTEX: return "POSE_VERTEX";
+ case M_ANIMATIONS: return "ANIMATIONS";
+ case M_ANIMATION: return "ANIMATION";
+ case M_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
+ case M_ANIMATION_TRACK: return "ANIMATION_TRACK";
+ case M_ANIMATION_MORPH_KEYFRAME: return "ANIMATION_MORPH_KEYFRAME";
+ case M_ANIMATION_POSE_KEYFRAME: return "ANIMATION_POSE_KEYFRAME";
+ case M_ANIMATION_POSE_REF: return "ANIMATION_POSE_REF";
+ case M_TABLE_EXTREMES: return "TABLE_EXTREMES";
+ }
+ return "Unknown_MeshChunkId";
}
+*/
enum SkeletonChunkId
{
- SKELETON_HEADER = 0x1000,
- // char* version : Version number check
- SKELETON_BLENDMODE = 0x1010, // optional
- // unsigned short blendmode : SkeletonAnimationBlendMode
- SKELETON_BONE = 0x2000,
- // Repeating section defining each bone in the system.
- // Bones are assigned indexes automatically based on their order of declaration
- // starting with 0.
- // char* name : name of the bone
- // unsigned short handle : handle of the bone, should be contiguous & start at 0
- // Vector3 position : position of this bone relative to parent
- // Quaternion orientation : orientation of this bone relative to parent
- // Vector3 scale : scale of this bone relative to parent
- SKELETON_BONE_PARENT = 0x3000,
- // Record of the parent of a single bone, used to build the node tree
- // Repeating section, listed in Bone Index order, one per Bone
- // unsigned short handle : child bone
- // unsigned short parentHandle : parent bone
- SKELETON_ANIMATION = 0x4000,
- // A single animation for this skeleton
- // char* name : Name of the animation
- // float length : Length of the animation in seconds
- SKELETON_ANIMATION_BASEINFO = 0x4010,
- // [Optional] base keyframe information
- // char* baseAnimationName (blank for self)
- // float baseKeyFrameTime
- SKELETON_ANIMATION_TRACK = 0x4100,
- // A single animation track (relates to a single bone)
- // Repeating section (within SKELETON_ANIMATION)
- // unsigned short boneIndex : Index of bone to apply to
- SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
- // A single keyframe within the track
- // Repeating section
- // float time : The time position (seconds)
- // Quaternion rotate : Rotation to apply at this keyframe
- // Vector3 translate : Translation to apply at this keyframe
- // Vector3 scale : Scale to apply at this keyframe
- SKELETON_ANIMATION_LINK = 0x5000
- // Link to another skeleton, to re-use its animations
- // char* skeletonName : name of skeleton to get animations from
- // float scale : scale to apply to trans/scale keys
+ SKELETON_HEADER = 0x1000,
+ // char* version : Version number check
+ SKELETON_BLENDMODE = 0x1010, // optional
+ // unsigned short blendmode : SkeletonAnimationBlendMode
+ SKELETON_BONE = 0x2000,
+ // Repeating section defining each bone in the system.
+ // Bones are assigned indexes automatically based on their order of declaration
+ // starting with 0.
+ // char* name : name of the bone
+ // unsigned short handle : handle of the bone, should be contiguous & start at 0
+ // Vector3 position : position of this bone relative to parent
+ // Quaternion orientation : orientation of this bone relative to parent
+ // Vector3 scale : scale of this bone relative to parent
+ SKELETON_BONE_PARENT = 0x3000,
+ // Record of the parent of a single bone, used to build the node tree
+ // Repeating section, listed in Bone Index order, one per Bone
+ // unsigned short handle : child bone
+ // unsigned short parentHandle : parent bone
+ SKELETON_ANIMATION = 0x4000,
+ // A single animation for this skeleton
+ // char* name : Name of the animation
+ // float length : Length of the animation in seconds
+ SKELETON_ANIMATION_BASEINFO = 0x4010,
+ // [Optional] base keyframe information
+ // char* baseAnimationName (blank for self)
+ // float baseKeyFrameTime
+ SKELETON_ANIMATION_TRACK = 0x4100,
+ // A single animation track (relates to a single bone)
+ // Repeating section (within SKELETON_ANIMATION)
+ // unsigned short boneIndex : Index of bone to apply to
+ SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
+ // A single keyframe within the track
+ // Repeating section
+ // float time : The time position (seconds)
+ // Quaternion rotate : Rotation to apply at this keyframe
+ // Vector3 translate : Translation to apply at this keyframe
+ // Vector3 scale : Scale to apply at this keyframe
+ SKELETON_ANIMATION_LINK = 0x5000
+ // Link to another skeleton, to re-use its animations
+ // char* skeletonName : name of skeleton to get animations from
+ // float scale : scale to apply to trans/scale keys
};
+/*
static std::string SkeletonHeaderToString(SkeletonChunkId id)
{
- switch(id)
- {
- case SKELETON_HEADER: return "HEADER";
- case SKELETON_BLENDMODE: return "BLENDMODE";
- case SKELETON_BONE: return "BONE";
- case SKELETON_BONE_PARENT: return "BONE_PARENT";
- case SKELETON_ANIMATION: return "ANIMATION";
- case SKELETON_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
- case SKELETON_ANIMATION_TRACK: return "ANIMATION_TRACK";
- case SKELETON_ANIMATION_TRACK_KEYFRAME: return "ANIMATION_TRACK_KEYFRAME";
- case SKELETON_ANIMATION_LINK: return "ANIMATION_LINK";
- }
- return "Unknown_SkeletonChunkId";
+ switch(id)
+ {
+ case SKELETON_HEADER: return "HEADER";
+ case SKELETON_BLENDMODE: return "BLENDMODE";
+ case SKELETON_BONE: return "BONE";
+ case SKELETON_BONE_PARENT: return "BONE_PARENT";
+ case SKELETON_ANIMATION: return "ANIMATION";
+ case SKELETON_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
+ case SKELETON_ANIMATION_TRACK: return "ANIMATION_TRACK";
+ case SKELETON_ANIMATION_TRACK_KEYFRAME: return "ANIMATION_TRACK_KEYFRAME";
+ case SKELETON_ANIMATION_LINK: return "ANIMATION_LINK";
+ }
+ return "Unknown_SkeletonChunkId";
}
+*/
} // Ogre
} // Assimp
diff --git a/src/3rdparty/assimp/code/OgreImporter.cpp b/src/3rdparty/assimp/code/OgreImporter.cpp
index 1760fceea..504f6a96f 100644
--- a/src/3rdparty/assimp/code/OgreImporter.cpp
+++ b/src/3rdparty/assimp/code/OgreImporter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,23 +40,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-#include "AssimpPCH.h"
+
#include "OgreImporter.h"
#include "OgreBinarySerializer.h"
#include "OgreXmlSerializer.h"
+#include <assimp/Importer.hpp>
+#include <memory>
static const aiImporterDesc desc = {
- "Ogre3D Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "mesh mesh.xml"
+ "Ogre3D Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "mesh mesh.xml"
};
namespace Assimp
@@ -66,79 +68,79 @@ namespace Ogre
const aiImporterDesc* OgreImporter::GetInfo() const
{
- return &desc;
+ return &desc;
}
void OgreImporter::SetupProperties(const Importer* pImp)
{
- m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
- m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
+ m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
+ m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
}
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
{
- if (!checkSig) {
- return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
- }
-
- if (EndsWith(pFile, ".mesh.xml", false))
- {
- const char* tokens[] = { "<mesh>" };
- return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
- }
- else
- {
- /// @todo Read and validate first header chunk?
- return EndsWith(pFile, ".mesh", false);
- }
+ if (!checkSig) {
+ return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
+ }
+
+ if (EndsWith(pFile, ".mesh.xml", false))
+ {
+ const char* tokens[] = { "<mesh>" };
+ return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
+ }
+ else
+ {
+ /// @todo Read and validate first header chunk?
+ return EndsWith(pFile, ".mesh", false);
+ }
}
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
{
- // Open source file
- IOStream *f = pIOHandler->Open(pFile, "rb");
- if (!f) {
- throw DeadlyImportError("Failed to open file " + pFile);
- }
-
- // Binary .mesh import
- if (EndsWith(pFile, ".mesh", false))
- {
- /// @note MemoryStreamReader takes ownership of f.
- MemoryStreamReader reader(f);
-
- // Import mesh
- boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
-
- // Import skeleton
- OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
-
- // Import mesh referenced materials
- ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
-
- // Convert to Assimp
- mesh->ConvertToAssimpScene(pScene);
- }
- // XML .mesh.xml import
- else
- {
- /// @note XmlReader does not take ownership of f, hence the scoped ptr.
- boost::scoped_ptr<IOStream> scopedFile(f);
- boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(scopedFile.get()));
- boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
-
- // Import mesh
- boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
-
- // Import skeleton
- OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
-
- // Import mesh referenced materials
- ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
-
- // Convert to Assimp
- mesh->ConvertToAssimpScene(pScene);
- }
+ // Open source file
+ IOStream *f = pIOHandler->Open(pFile, "rb");
+ if (!f) {
+ throw DeadlyImportError("Failed to open file " + pFile);
+ }
+
+ // Binary .mesh import
+ if (EndsWith(pFile, ".mesh", false))
+ {
+ /// @note MemoryStreamReader takes ownership of f.
+ MemoryStreamReader reader(f);
+
+ // Import mesh
+ std::unique_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
+
+ // Import skeleton
+ OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
+
+ // Import mesh referenced materials
+ ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
+
+ // Convert to Assimp
+ mesh->ConvertToAssimpScene(pScene);
+ }
+ // XML .mesh.xml import
+ else
+ {
+ /// @note XmlReader does not take ownership of f, hence the scoped ptr.
+ std::unique_ptr<IOStream> scopedFile(f);
+ std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(scopedFile.get()));
+ std::unique_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
+
+ // Import mesh
+ std::unique_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
+
+ // Import skeleton
+ OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
+
+ // Import mesh referenced materials
+ ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
+
+ // Convert to Assimp
+ mesh->ConvertToAssimpScene(pScene);
+ }
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreImporter.h b/src/3rdparty/assimp/code/OgreImporter.h
index 2d9cf971e..8b2179502 100644
--- a/src/3rdparty/assimp/code/OgreImporter.h
+++ b/src/3rdparty/assimp/code/OgreImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,48 +48,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OgreStructs.h"
#include "OgreParsingUtils.h"
+#include <assimp/material.h>
+
namespace Assimp
{
namespace Ogre
{
-/** Importer for Ogre mesh, skeleton and material formats.
- @todo Support vertex colors.
- @todo Support poses/animations from the mesh file.
- Currently only skeleton file animations are supported. */
+/** Importer for Ogre mesh, skeleton and material formats.
+ @todo Support vertex colors.
+ @todo Support poses/animations from the mesh file.
+ Currently only skeleton file animations are supported. */
class OgreImporter : public BaseImporter
{
public:
- /// BaseImporter override.
- virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
-
- /// BaseImporter override.
- virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
-
- /// BaseImporter override.
- virtual const aiImporterDesc *GetInfo() const;
-
- /// BaseImporter override.
- virtual void SetupProperties(const Importer *pImp);
+ /// BaseImporter override.
+ virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
+
+ /// BaseImporter override.
+ virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
+
+ /// BaseImporter override.
+ virtual const aiImporterDesc *GetInfo() const;
+
+ /// BaseImporter override.
+ virtual void SetupProperties(const Importer *pImp);
private:
- /// Read materials referenced by the @c mesh to @c pScene.
- void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
- void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
- void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
-
- /// Reads material
- aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
-
- // These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
- bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
- bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);
- bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
-
- std::string m_userDefinedMaterialLibFile;
- bool m_detectTextureTypeFromFilename;
-
- std::map<aiTextureType, unsigned int> m_textures;
+ /// Read materials referenced by the @c mesh to @c pScene.
+ void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
+ void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
+ void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
+
+ /// Reads material
+ aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &MaterialName);
+
+ // These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
+ bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
+ bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);
+ bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
+
+ std::string m_userDefinedMaterialLibFile;
+ bool m_detectTextureTypeFromFilename;
+
+ std::map<aiTextureType, unsigned int> m_textures;
};
} // Ogre
} // Assimp
diff --git a/src/3rdparty/assimp/code/OgreMaterial.cpp b/src/3rdparty/assimp/code/OgreMaterial.cpp
index a85741f18..f9da9d584 100644
--- a/src/3rdparty/assimp/code/OgreMaterial.cpp
+++ b/src/3rdparty/assimp/code/OgreMaterial.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,32 +23,35 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreImporter.h"
#include "TinyFormatter.h"
-
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
#include "fast_atof.h"
#include <vector>
#include <sstream>
+#include <memory>
using namespace std;
@@ -63,527 +66,527 @@ static const string partBlockEnd = "}";
void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh)
{
- std::vector<aiMaterial*> materials;
-
- // Create materials that can be found and parsed via the IOSystem.
- for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
- {
- SubMesh *submesh = mesh->GetSubMesh(i);
- if (submesh && !submesh->materialRef.empty())
- {
- aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
- if (material)
- {
- submesh->materialIndex = materials.size();
- materials.push_back(material);
- }
- }
- }
-
- AssignMaterials(pScene, materials);
+ std::vector<aiMaterial*> materials;
+
+ // Create materials that can be found and parsed via the IOSystem.
+ for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
+ {
+ SubMesh *submesh = mesh->GetSubMesh(i);
+ if (submesh && !submesh->materialRef.empty())
+ {
+ aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
+ if (material)
+ {
+ submesh->materialIndex = materials.size();
+ materials.push_back(material);
+ }
+ }
+ }
+
+ AssignMaterials(pScene, materials);
}
void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh)
{
- std::vector<aiMaterial*> materials;
-
- // Create materials that can be found and parsed via the IOSystem.
- for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
- {
- SubMeshXml *submesh = mesh->GetSubMesh(i);
- if (submesh && !submesh->materialRef.empty())
- {
- aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
- if (material)
- {
- submesh->materialIndex = materials.size();
- materials.push_back(material);
- }
- }
- }
-
- AssignMaterials(pScene, materials);
+ std::vector<aiMaterial*> materials;
+
+ // Create materials that can be found and parsed via the IOSystem.
+ for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
+ {
+ SubMeshXml *submesh = mesh->GetSubMesh(i);
+ if (submesh && !submesh->materialRef.empty())
+ {
+ aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
+ if (material)
+ {
+ submesh->materialIndex = materials.size();
+ materials.push_back(material);
+ }
+ }
+ }
+
+ AssignMaterials(pScene, materials);
}
void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials)
{
- pScene->mNumMaterials = materials.size();
- if (pScene->mNumMaterials > 0)
- {
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for(size_t i=0;i<pScene->mNumMaterials; ++i) {
- pScene->mMaterials[i] = materials[i];
- }
- }
+ pScene->mNumMaterials = materials.size();
+ if (pScene->mNumMaterials > 0)
+ {
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for(size_t i=0;i<pScene->mNumMaterials; ++i) {
+ pScene->mMaterials[i] = materials[i];
+ }
+ }
}
-aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName)
+aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &materialName)
{
- if (materialName.empty()) {
- return 0;
- }
-
- // Full reference and examples of Ogre Material Script
- // can be found from http://www.ogre3d.org/docs/manual/manual_14.html
-
- /*and here is another one:
-
- import * from abstract_base_passes_depth.material
- import * from abstract_base.material
- import * from mat_shadow_caster.material
- import * from mat_character_singlepass.material
-
- material hero/hair/caster : mat_shadow_caster_skin_areject
- {
- set $diffuse_map "hero_hair_alpha_c.dds"
- }
-
- material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights
- {
- set $diffuse_map "hero_hair_alpha_c.dds"
- set $specular_map "hero_hair_alpha_s.dds"
- set $normal_map "hero_hair_alpha_n.dds"
- set $light_map "black_lightmap.dds"
-
- set $shadow_caster_material "hero/hair/caster"
- }
- */
-
- stringstream ss;
-
- // Scope for scopre_ptr auto release
- {
- /* There are three .material options in priority order:
- 1) File with the material name (materialName)
- 2) File with the mesh files base name (pFile)
- 3) Optional user defined material library file (m_userDefinedMaterialLibFile) */
- std::vector<string> potentialFiles;
- potentialFiles.push_back(materialName + ".material");
- potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material");
- if (!m_userDefinedMaterialLibFile.empty())
- potentialFiles.push_back(m_userDefinedMaterialLibFile);
-
- IOStream *materialFile = 0;
- for(size_t i=0; i<potentialFiles.size(); ++i)
- {
- materialFile = pIOHandler->Open(potentialFiles[i]);
- if (materialFile) {
- break;
- }
- DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist");
- }
- if (!materialFile)
- {
- DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'");
- return 0;
- }
-
- boost::scoped_ptr<IOStream> stream(materialFile);
- if (stream->FileSize() == 0)
- {
- DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)");
- return 0;
- }
-
- // Read bytes
- vector<char> data(stream->FileSize());
- stream->Read(&data[0], stream->FileSize(), 1);
-
- // Convert to UTF-8 and terminate the string for ss
- BaseImporter::ConvertToUTF8(data);
- data.push_back('\0');
-
- ss << &data[0];
- }
-
- DefaultLogger::get()->debug("Reading material '" + materialName + "'");
-
- aiMaterial *material = new aiMaterial();
- m_textures.clear();
-
- aiString ts(materialName);
- material->AddProperty(&ts, AI_MATKEY_NAME);
-
- // The stringstream will push words from a line until newline.
- // It will also trim whitespace from line start and between words.
- string linePart;
- ss >> linePart;
-
- const string partMaterial = "material";
- const string partTechnique = "technique";
-
- while(!ss.eof())
- {
- // Skip commented lines
- if (linePart == partComment)
- {
- NextAfterNewLine(ss, linePart);
- continue;
- }
- if (linePart != partMaterial)
- {
- ss >> linePart;
- continue;
- }
-
- ss >> linePart;
- if (linePart != materialName)
- {
- //DefaultLogger::get()->debug(Formatter::format() << "Found material '" << linePart << "' that does not match at index " << ss.tellg());
- ss >> linePart;
- continue;
- }
-
- NextAfterNewLine(ss, linePart);
- if (linePart != partBlockStart)
- {
- DefaultLogger::get()->error(Formatter::format() << "Invalid material: block start missing near index " << ss.tellg());
- return material;
- }
-
- DefaultLogger::get()->debug("material '" + materialName + "'");
-
- while(linePart != partBlockEnd)
- {
- // Proceed to the first technique
- ss >> linePart;
-
- if (linePart == partTechnique)
- {
- string techniqueName = SkipLine(ss);
- ReadTechnique(Trim(techniqueName), ss, material);
- }
-
- // Read informations from a custom material
- /** @todo This "set $x y" does not seem to be a official Ogre material system feature.
- Materials can inherit other materials and override texture units by using the (unique)
- parent texture unit name in your cloned material.
- This is not yet supported and below code is probably some hack from the original
- author of this Ogre importer. Should be removed? */
- if (linePart=="set")
- {
- ss >> linePart;
- if (linePart=="$specular")//todo load this values:
- {
- }
- else if (linePart=="$diffuse")
- {
- }
- else if (linePart=="$ambient")
- {
- }
- else if (linePart=="$colormap")
- {
- ss >> linePart;
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
- }
- else if (linePart=="$normalmap")
- {
- ss >> linePart;
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
- }
- else if (linePart=="$shininess_strength")
- {
- ss >> linePart;
- float Shininess = fast_atof(linePart.c_str());
- material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
- }
- else if (linePart=="$shininess_exponent")
- {
- ss >> linePart;
- float Shininess = fast_atof(linePart.c_str());
- material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
- }
- //Properties from Venetica:
- else if (linePart=="$diffuse_map")
- {
- ss >> linePart;
- if (linePart[0] == '"')// "file" -> file
- linePart = linePart.substr(1, linePart.size()-2);
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
- }
- else if (linePart=="$specular_map")
- {
- ss >> linePart;
- if (linePart[0] == '"')// "file" -> file
- linePart = linePart.substr(1, linePart.size()-2);
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
- }
- else if (linePart=="$normal_map")
- {
- ss >> linePart;
- if (linePart[0]=='"')// "file" -> file
- linePart = linePart.substr(1, linePart.size()-2);
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
- }
- else if (linePart=="$light_map")
- {
- ss >> linePart;
- if (linePart[0]=='"') {
- linePart = linePart.substr(1, linePart.size() - 2);
- }
- aiString ts(linePart);
- material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
- }
- }
- }
- ss >> linePart;
- }
-
- return material;
+ if (materialName.empty()) {
+ return 0;
+ }
+
+ // Full reference and examples of Ogre Material Script
+ // can be found from http://www.ogre3d.org/docs/manual/manual_14.html
+
+ /*and here is another one:
+
+ import * from abstract_base_passes_depth.material
+ import * from abstract_base.material
+ import * from mat_shadow_caster.material
+ import * from mat_character_singlepass.material
+
+ material hero/hair/caster : mat_shadow_caster_skin_areject
+ {
+ set $diffuse_map "hero_hair_alpha_c.dds"
+ }
+
+ material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights
+ {
+ set $diffuse_map "hero_hair_alpha_c.dds"
+ set $specular_map "hero_hair_alpha_s.dds"
+ set $normal_map "hero_hair_alpha_n.dds"
+ set $light_map "black_lightmap.dds"
+
+ set $shadow_caster_material "hero/hair/caster"
+ }
+ */
+
+ stringstream ss;
+
+ // Scope for scopre_ptr auto release
+ {
+ /* There are three .material options in priority order:
+ 1) File with the material name (materialName)
+ 2) File with the mesh files base name (pFile)
+ 3) Optional user defined material library file (m_userDefinedMaterialLibFile) */
+ std::vector<string> potentialFiles;
+ potentialFiles.push_back(materialName + ".material");
+ potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material");
+ if (!m_userDefinedMaterialLibFile.empty())
+ potentialFiles.push_back(m_userDefinedMaterialLibFile);
+
+ IOStream *materialFile = 0;
+ for(size_t i=0; i<potentialFiles.size(); ++i)
+ {
+ materialFile = pIOHandler->Open(potentialFiles[i]);
+ if (materialFile) {
+ break;
+ }
+ DefaultLogger::get()->debug(Formatter::format() << "Source file for material '" << materialName << "' " << potentialFiles[i] << " does not exist");
+ }
+ if (!materialFile)
+ {
+ DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'");
+ return 0;
+ }
+
+ std::unique_ptr<IOStream> stream(materialFile);
+ if (stream->FileSize() == 0)
+ {
+ DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)");
+ return 0;
+ }
+
+ // Read bytes
+ vector<char> data(stream->FileSize());
+ stream->Read(&data[0], stream->FileSize(), 1);
+
+ // Convert to UTF-8 and terminate the string for ss
+ BaseImporter::ConvertToUTF8(data);
+ data.push_back('\0');
+
+ ss << &data[0];
+ }
+
+ DefaultLogger::get()->debug("Reading material '" + materialName + "'");
+
+ aiMaterial *material = new aiMaterial();
+ m_textures.clear();
+
+ aiString ts(materialName);
+ material->AddProperty(&ts, AI_MATKEY_NAME);
+
+ // The stringstream will push words from a line until newline.
+ // It will also trim whitespace from line start and between words.
+ string linePart;
+ ss >> linePart;
+
+ const string partMaterial = "material";
+ const string partTechnique = "technique";
+
+ while(!ss.eof())
+ {
+ // Skip commented lines
+ if (linePart == partComment)
+ {
+ NextAfterNewLine(ss, linePart);
+ continue;
+ }
+ if (linePart != partMaterial)
+ {
+ ss >> linePart;
+ continue;
+ }
+
+ ss >> linePart;
+ if (linePart != materialName)
+ {
+ //DefaultLogger::get()->debug(Formatter::format() << "Found material '" << linePart << "' that does not match at index " << ss.tellg());
+ ss >> linePart;
+ continue;
+ }
+
+ NextAfterNewLine(ss, linePart);
+ if (linePart != partBlockStart)
+ {
+ DefaultLogger::get()->error(Formatter::format() << "Invalid material: block start missing near index " << ss.tellg());
+ return material;
+ }
+
+ DefaultLogger::get()->debug("material '" + materialName + "'");
+
+ while(linePart != partBlockEnd)
+ {
+ // Proceed to the first technique
+ ss >> linePart;
+
+ if (linePart == partTechnique)
+ {
+ string techniqueName = SkipLine(ss);
+ ReadTechnique(Trim(techniqueName), ss, material);
+ }
+
+ // Read informations from a custom material
+ /** @todo This "set $x y" does not seem to be a official Ogre material system feature.
+ Materials can inherit other materials and override texture units by using the (unique)
+ parent texture unit name in your cloned material.
+ This is not yet supported and below code is probably some hack from the original
+ author of this Ogre importer. Should be removed? */
+ if (linePart=="set")
+ {
+ ss >> linePart;
+ if (linePart=="$specular")//todo load this values:
+ {
+ }
+ else if (linePart=="$diffuse")
+ {
+ }
+ else if (linePart=="$ambient")
+ {
+ }
+ else if (linePart=="$colormap")
+ {
+ ss >> linePart;
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+ }
+ else if (linePart=="$normalmap")
+ {
+ ss >> linePart;
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
+ }
+ else if (linePart=="$shininess_strength")
+ {
+ ss >> linePart;
+ float Shininess = fast_atof(linePart.c_str());
+ material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
+ }
+ else if (linePart=="$shininess_exponent")
+ {
+ ss >> linePart;
+ float Shininess = fast_atof(linePart.c_str());
+ material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
+ }
+ //Properties from Venetica:
+ else if (linePart=="$diffuse_map")
+ {
+ ss >> linePart;
+ if (linePart[0] == '"')// "file" -> file
+ linePart = linePart.substr(1, linePart.size()-2);
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+ }
+ else if (linePart=="$specular_map")
+ {
+ ss >> linePart;
+ if (linePart[0] == '"')// "file" -> file
+ linePart = linePart.substr(1, linePart.size()-2);
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
+ }
+ else if (linePart=="$normal_map")
+ {
+ ss >> linePart;
+ if (linePart[0]=='"')// "file" -> file
+ linePart = linePart.substr(1, linePart.size()-2);
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
+ }
+ else if (linePart=="$light_map")
+ {
+ ss >> linePart;
+ if (linePart[0]=='"') {
+ linePart = linePart.substr(1, linePart.size() - 2);
+ }
+ aiString ts(linePart);
+ material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
+ }
+ }
+ }
+ ss >> linePart;
+ }
+
+ return material;
}
bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material)
{
- string linePart;
- ss >> linePart;
-
- if (linePart != partBlockStart)
- {
- DefaultLogger::get()->error(Formatter::format() << "Invalid material: Technique block start missing near index " << ss.tellg());
- return false;
- }
-
- DefaultLogger::get()->debug(" technique '" + techniqueName + "'");
-
- const string partPass = "pass";
-
- while(linePart != partBlockEnd)
- {
- ss >> linePart;
-
- // Skip commented lines
- if (linePart == partComment)
- {
- SkipLine(ss);
- continue;
- }
-
- /// @todo Techniques have other attributes than just passes.
- if (linePart == partPass)
- {
- string passName = SkipLine(ss);
- ReadPass(Trim(passName), ss, material);
- }
- }
- return true;
+ string linePart;
+ ss >> linePart;
+
+ if (linePart != partBlockStart)
+ {
+ DefaultLogger::get()->error(Formatter::format() << "Invalid material: Technique block start missing near index " << ss.tellg());
+ return false;
+ }
+
+ DefaultLogger::get()->debug(" technique '" + techniqueName + "'");
+
+ const string partPass = "pass";
+
+ while(linePart != partBlockEnd)
+ {
+ ss >> linePart;
+
+ // Skip commented lines
+ if (linePart == partComment)
+ {
+ SkipLine(ss);
+ continue;
+ }
+
+ /// @todo Techniques have other attributes than just passes.
+ if (linePart == partPass)
+ {
+ string passName = SkipLine(ss);
+ ReadPass(Trim(passName), ss, material);
+ }
+ }
+ return true;
}
bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material)
{
- string linePart;
- ss >> linePart;
-
- if (linePart != partBlockStart)
- {
- DefaultLogger::get()->error(Formatter::format() << "Invalid material: Pass block start missing near index " << ss.tellg());
- return false;
- }
-
- DefaultLogger::get()->debug(" pass '" + passName + "'");
-
- const string partAmbient = "ambient";
- const string partDiffuse = "diffuse";
- const string partSpecular = "specular";
- const string partEmissive = "emissive";
- const string partTextureUnit = "texture_unit";
-
- while(linePart != partBlockEnd)
- {
- ss >> linePart;
-
- // Skip commented lines
- if (linePart == partComment)
- {
- SkipLine(ss);
- continue;
- }
-
- // Colors
- /// @todo Support alpha via aiColor4D.
- if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive)
- {
- float r, g, b;
- ss >> r >> g >> b;
- const aiColor3D color(r, g, b);
-
- DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b);
-
- if (linePart == partAmbient)
- {
- material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
- }
- else if (linePart == partDiffuse)
- {
- material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
- }
- else if (linePart == partSpecular)
- {
- material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
- }
- else if (linePart == partEmissive)
- {
- material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
- }
- }
- else if (linePart == partTextureUnit)
- {
- string textureUnitName = SkipLine(ss);
- ReadTextureUnit(Trim(textureUnitName), ss, material);
- }
- }
- return true;
+ string linePart;
+ ss >> linePart;
+
+ if (linePart != partBlockStart)
+ {
+ DefaultLogger::get()->error(Formatter::format() << "Invalid material: Pass block start missing near index " << ss.tellg());
+ return false;
+ }
+
+ DefaultLogger::get()->debug(" pass '" + passName + "'");
+
+ const string partAmbient = "ambient";
+ const string partDiffuse = "diffuse";
+ const string partSpecular = "specular";
+ const string partEmissive = "emissive";
+ const string partTextureUnit = "texture_unit";
+
+ while(linePart != partBlockEnd)
+ {
+ ss >> linePart;
+
+ // Skip commented lines
+ if (linePart == partComment)
+ {
+ SkipLine(ss);
+ continue;
+ }
+
+ // Colors
+ /// @todo Support alpha via aiColor4D.
+ if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive)
+ {
+ float r, g, b;
+ ss >> r >> g >> b;
+ const aiColor3D color(r, g, b);
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << linePart << " " << r << " " << g << " " << b);
+
+ if (linePart == partAmbient)
+ {
+ material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
+ }
+ else if (linePart == partDiffuse)
+ {
+ material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
+ }
+ else if (linePart == partSpecular)
+ {
+ material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
+ }
+ else if (linePart == partEmissive)
+ {
+ material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
+ }
+ }
+ else if (linePart == partTextureUnit)
+ {
+ string textureUnitName = SkipLine(ss);
+ ReadTextureUnit(Trim(textureUnitName), ss, material);
+ }
+ }
+ return true;
}
bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material)
{
- string linePart;
- ss >> linePart;
-
- if (linePart != partBlockStart)
- {
- DefaultLogger::get()->error(Formatter::format() << "Invalid material: Texture unit block start missing near index " << ss.tellg());
- return false;
- }
-
- DefaultLogger::get()->debug(" texture_unit '" + textureUnitName + "'");
-
- const string partTexture = "texture";
- const string partTextCoordSet = "tex_coord_set";
- const string partColorOp = "colour_op";
-
- aiTextureType textureType = aiTextureType_NONE;
- std::string textureRef;
- int uvCoord = 0;
-
- while(linePart != partBlockEnd)
- {
- ss >> linePart;
-
- // Skip commented lines
- if (linePart == partComment)
- {
- SkipLine(ss);
- continue;
- }
-
- if (linePart == partTexture)
- {
- ss >> linePart;
- textureRef = linePart;
-
- // User defined Assimp config property to detect texture type from filename.
- if (m_detectTextureTypeFromFilename)
- {
- size_t posSuffix = textureRef.find_last_of(".");
- size_t posUnderscore = textureRef.find_last_of("_");
-
- if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore)
- {
- string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
- DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'");
-
- if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
- {
- textureType = aiTextureType_NORMALS;
- }
- else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
- {
- textureType = aiTextureType_SPECULAR;
- }
- else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
- {
- textureType = aiTextureType_LIGHTMAP;
- }
- else if (identifier == "_disp" || identifier == "_displacement")
- {
- textureType = aiTextureType_DISPLACEMENT;
- }
- else
- {
- textureType = aiTextureType_DIFFUSE;
- }
- }
- else
- {
- textureType = aiTextureType_DIFFUSE;
- }
- }
- // Detect from texture unit name. This cannot be too broad as
- // authors might give names like "LightSaber" or "NormalNinja".
- else
- {
- string unitNameLower = Ogre::ToLower(textureUnitName);
- if (unitNameLower.find("normalmap") != string::npos)
- {
- textureType = aiTextureType_NORMALS;
- }
- else if (unitNameLower.find("specularmap") != string::npos)
- {
- textureType = aiTextureType_SPECULAR;
- }
- else if (unitNameLower.find("lightmap") != string::npos)
- {
- textureType = aiTextureType_LIGHTMAP;
- }
- else if (unitNameLower.find("displacementmap") != string::npos)
- {
- textureType = aiTextureType_DISPLACEMENT;
- }
- else
- {
- textureType = aiTextureType_DIFFUSE;
- }
- }
- }
- else if (linePart == partTextCoordSet)
- {
- ss >> uvCoord;
- }
- /// @todo Implement
- else if(linePart == partColorOp)
- {
- /*
- ss >> linePart;
- if("replace"==linePart)//I don't think, assimp has something for this...
- {
- }
- else if("modulate"==linePart)
- {
- //TODO: set value
- //material->AddProperty(aiTextureOp_Multiply)
- }
- */
- }
- }
-
- if (textureRef.empty())
- {
- DefaultLogger::get()->warn("Texture reference is empty, ignoring texture_unit.");
- return false;
- }
- if (textureType == aiTextureType_NONE)
- {
- DefaultLogger::get()->warn("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit.");
- return false;
- }
-
- unsigned int textureTypeIndex = m_textures[textureType];
- m_textures[textureType]++;
-
- DefaultLogger::get()->debug(Formatter::format() << " texture '" << textureRef << "' type " << textureType
- << " index " << textureTypeIndex << " UV " << uvCoord);
-
- aiString assimpTextureRef(textureRef);
- material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex));
- material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex));
-
- return true;
+ string linePart;
+ ss >> linePart;
+
+ if (linePart != partBlockStart)
+ {
+ DefaultLogger::get()->error(Formatter::format() << "Invalid material: Texture unit block start missing near index " << ss.tellg());
+ return false;
+ }
+
+ DefaultLogger::get()->debug(" texture_unit '" + textureUnitName + "'");
+
+ const string partTexture = "texture";
+ const string partTextCoordSet = "tex_coord_set";
+ const string partColorOp = "colour_op";
+
+ aiTextureType textureType = aiTextureType_NONE;
+ std::string textureRef;
+ int uvCoord = 0;
+
+ while(linePart != partBlockEnd)
+ {
+ ss >> linePart;
+
+ // Skip commented lines
+ if (linePart == partComment)
+ {
+ SkipLine(ss);
+ continue;
+ }
+
+ if (linePart == partTexture)
+ {
+ ss >> linePart;
+ textureRef = linePart;
+
+ // User defined Assimp config property to detect texture type from filename.
+ if (m_detectTextureTypeFromFilename)
+ {
+ size_t posSuffix = textureRef.find_last_of(".");
+ size_t posUnderscore = textureRef.find_last_of("_");
+
+ if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore)
+ {
+ string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
+ DefaultLogger::get()->debug(Formatter::format() << "Detecting texture type from filename postfix '" << identifier << "'");
+
+ if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
+ {
+ textureType = aiTextureType_NORMALS;
+ }
+ else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
+ {
+ textureType = aiTextureType_SPECULAR;
+ }
+ else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
+ {
+ textureType = aiTextureType_LIGHTMAP;
+ }
+ else if (identifier == "_disp" || identifier == "_displacement")
+ {
+ textureType = aiTextureType_DISPLACEMENT;
+ }
+ else
+ {
+ textureType = aiTextureType_DIFFUSE;
+ }
+ }
+ else
+ {
+ textureType = aiTextureType_DIFFUSE;
+ }
+ }
+ // Detect from texture unit name. This cannot be too broad as
+ // authors might give names like "LightSaber" or "NormalNinja".
+ else
+ {
+ string unitNameLower = Ogre::ToLower(textureUnitName);
+ if (unitNameLower.find("normalmap") != string::npos)
+ {
+ textureType = aiTextureType_NORMALS;
+ }
+ else if (unitNameLower.find("specularmap") != string::npos)
+ {
+ textureType = aiTextureType_SPECULAR;
+ }
+ else if (unitNameLower.find("lightmap") != string::npos)
+ {
+ textureType = aiTextureType_LIGHTMAP;
+ }
+ else if (unitNameLower.find("displacementmap") != string::npos)
+ {
+ textureType = aiTextureType_DISPLACEMENT;
+ }
+ else
+ {
+ textureType = aiTextureType_DIFFUSE;
+ }
+ }
+ }
+ else if (linePart == partTextCoordSet)
+ {
+ ss >> uvCoord;
+ }
+ /// @todo Implement
+ else if(linePart == partColorOp)
+ {
+ /*
+ ss >> linePart;
+ if("replace"==linePart)//I don't think, assimp has something for this...
+ {
+ }
+ else if("modulate"==linePart)
+ {
+ //TODO: set value
+ //material->AddProperty(aiTextureOp_Multiply)
+ }
+ */
+ }
+ }
+
+ if (textureRef.empty())
+ {
+ DefaultLogger::get()->warn("Texture reference is empty, ignoring texture_unit.");
+ return false;
+ }
+ if (textureType == aiTextureType_NONE)
+ {
+ DefaultLogger::get()->warn("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit.");
+ return false;
+ }
+
+ unsigned int textureTypeIndex = m_textures[textureType];
+ m_textures[textureType]++;
+
+ DefaultLogger::get()->debug(Formatter::format() << " texture '" << textureRef << "' type " << textureType
+ << " index " << textureTypeIndex << " UV " << uvCoord);
+
+ aiString assimpTextureRef(textureRef);
+ material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex));
+ material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex));
+
+ return true;
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreParsingUtils.h b/src/3rdparty/assimp/code/OgreParsingUtils.h
index d3a7aa8bf..def3cf733 100644
--- a/src/3rdparty/assimp/code/OgreParsingUtils.h
+++ b/src/3rdparty/assimp/code/OgreParsingUtils.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,6 +45,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
#include <functional>
+#include <algorithm>
+#include <stdint.h>
+#include <sstream>
+#include <cctype>
namespace Assimp
{
@@ -54,29 +58,29 @@ namespace Ogre
/// Returns a lower cased copy of @s.
static inline std::string ToLower(std::string s)
{
- std::transform(s.begin(), s.end(), s.begin(), ::tolower);
- return s;
+ std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+ return s;
}
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
{
- if (s.empty() || suffix.empty())
- {
- return false;
- }
- else if (s.length() < suffix.length())
- {
- return false;
- }
-
- if (!caseSensitive) {
- return EndsWith(ToLower(s), ToLower(suffix), true);
- }
-
- size_t len = suffix.length();
- std::string sSuffix = s.substr(s.length()-len, len);
- return (ASSIMP_stricmp(sSuffix, suffix) == 0);
+ if (s.empty() || suffix.empty())
+ {
+ return false;
+ }
+ else if (s.length() < suffix.length())
+ {
+ return false;
+ }
+
+ if (!caseSensitive) {
+ return EndsWith(ToLower(s), ToLower(suffix), true);
+ }
+
+ size_t len = suffix.length();
+ std::string sSuffix = s.substr(s.length()-len, len);
+ return (ASSIMP_stricmp(sSuffix, suffix) == 0);
}
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
@@ -84,52 +88,52 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo
/// Trim from start
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
{
- if (!newlines)
- {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
- }
- else
- {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
- }
- return s;
+ if (!newlines)
+ {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
+ }
+ else
+ {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+ }
+ return s;
}
/// Trim from end
static inline std::string &TrimRight(std::string &s, bool newlines = true)
{
- if (!newlines)
- {
- s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
- }
- else
- {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
- }
- return s;
+ if (!newlines)
+ {
+ s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
+ }
+ else
+ {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
+ }
+ return s;
}
/// Trim from both ends
static inline std::string &Trim(std::string &s, bool newlines = true)
{
- return TrimLeft(TrimRight(s, newlines), newlines);
+ return TrimLeft(TrimRight(s, newlines), newlines);
}
/// Skips a line from current @ss position until a newline. Returns the skipped part.
static inline std::string SkipLine(std::stringstream &ss)
{
- std::string skipped;
- getline(ss, skipped);
- return skipped;
+ std::string skipped;
+ getline(ss, skipped);
+ return skipped;
}
/// Skips a line and reads next element from @c ss to @c nextElement.
/** @return Skipped line content until newline. */
static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement)
{
- std::string skipped = SkipLine(ss);
- ss >> nextElement;
- return skipped;
+ std::string skipped = SkipLine(ss);
+ ss >> nextElement;
+ return skipped;
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreStructs.cpp b/src/3rdparty/assimp/code/OgreStructs.cpp
index 3eaf2df01..e2e8c8103 100644
--- a/src/3rdparty/assimp/code/OgreStructs.cpp
+++ b/src/3rdparty/assimp/code/OgreStructs.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,6 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OgreStructs.h"
#include "TinyFormatter.h"
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include "Exceptional.h"
+
namespace Assimp
{
@@ -50,247 +54,245 @@ namespace Ogre
// VertexElement
-VertexElement::VertexElement() :
- index(0),
- source(0),
- offset(0),
- type(VET_FLOAT1),
- semantic(VES_POSITION)
+VertexElement::VertexElement() :
+ index(0),
+ source(0),
+ offset(0),
+ type(VET_FLOAT1),
+ semantic(VES_POSITION)
{
}
size_t VertexElement::Size() const
{
- return TypeSize(type);
+ return TypeSize(type);
}
size_t VertexElement::ComponentCount() const
{
- return ComponentCount(type);
+ return ComponentCount(type);
}
size_t VertexElement::ComponentCount(Type type)
{
- switch(type)
- {
- case VET_COLOUR:
- case VET_COLOUR_ABGR:
- case VET_COLOUR_ARGB:
- case VET_FLOAT1:
- case VET_DOUBLE1:
- case VET_SHORT1:
- case VET_USHORT1:
- case VET_INT1:
- case VET_UINT1:
- return 1;
- case VET_FLOAT2:
- case VET_DOUBLE2:
- case VET_SHORT2:
- case VET_USHORT2:
- case VET_INT2:
- case VET_UINT2:
- return 2;
- case VET_FLOAT3:
- case VET_DOUBLE3:
- case VET_SHORT3:
- case VET_USHORT3:
- case VET_INT3:
- case VET_UINT3:
- return 3;
- case VET_FLOAT4:
- case VET_DOUBLE4:
- case VET_SHORT4:
- case VET_USHORT4:
- case VET_INT4:
- case VET_UINT4:
- case VET_UBYTE4:
- return 4;
- }
- return 0;
+ switch(type)
+ {
+ case VET_COLOUR:
+ case VET_COLOUR_ABGR:
+ case VET_COLOUR_ARGB:
+ case VET_FLOAT1:
+ case VET_DOUBLE1:
+ case VET_SHORT1:
+ case VET_USHORT1:
+ case VET_INT1:
+ case VET_UINT1:
+ return 1;
+ case VET_FLOAT2:
+ case VET_DOUBLE2:
+ case VET_SHORT2:
+ case VET_USHORT2:
+ case VET_INT2:
+ case VET_UINT2:
+ return 2;
+ case VET_FLOAT3:
+ case VET_DOUBLE3:
+ case VET_SHORT3:
+ case VET_USHORT3:
+ case VET_INT3:
+ case VET_UINT3:
+ return 3;
+ case VET_FLOAT4:
+ case VET_DOUBLE4:
+ case VET_SHORT4:
+ case VET_USHORT4:
+ case VET_INT4:
+ case VET_UINT4:
+ case VET_UBYTE4:
+ return 4;
+ }
+ return 0;
}
size_t VertexElement::TypeSize(Type type)
{
- switch(type)
- {
- case VET_COLOUR:
- case VET_COLOUR_ABGR:
- case VET_COLOUR_ARGB:
- return sizeof(unsigned int);
- case VET_FLOAT1:
- return sizeof(float);
- case VET_FLOAT2:
- return sizeof(float)*2;
- case VET_FLOAT3:
- return sizeof(float)*3;
- case VET_FLOAT4:
- return sizeof(float)*4;
- case VET_DOUBLE1:
- return sizeof(double);
- case VET_DOUBLE2:
- return sizeof(double)*2;
- case VET_DOUBLE3:
- return sizeof(double)*3;
- case VET_DOUBLE4:
- return sizeof(double)*4;
- case VET_SHORT1:
- return sizeof(short);
- case VET_SHORT2:
- return sizeof(short)*2;
- case VET_SHORT3:
- return sizeof(short)*3;
- case VET_SHORT4:
- return sizeof(short)*4;
- case VET_USHORT1:
- return sizeof(unsigned short);
- case VET_USHORT2:
- return sizeof(unsigned short)*2;
- case VET_USHORT3:
- return sizeof(unsigned short)*3;
- case VET_USHORT4:
- return sizeof(unsigned short)*4;
- case VET_INT1:
- return sizeof(int);
- case VET_INT2:
- return sizeof(int)*2;
- case VET_INT3:
- return sizeof(int)*3;
- case VET_INT4:
- return sizeof(int)*4;
- case VET_UINT1:
- return sizeof(unsigned int);
- case VET_UINT2:
- return sizeof(unsigned int)*2;
- case VET_UINT3:
- return sizeof(unsigned int)*3;
- case VET_UINT4:
- return sizeof(unsigned int)*4;
- case VET_UBYTE4:
- return sizeof(unsigned char)*4;
- }
- return 0;
+ switch(type)
+ {
+ case VET_COLOUR:
+ case VET_COLOUR_ABGR:
+ case VET_COLOUR_ARGB:
+ return sizeof(unsigned int);
+ case VET_FLOAT1:
+ return sizeof(float);
+ case VET_FLOAT2:
+ return sizeof(float)*2;
+ case VET_FLOAT3:
+ return sizeof(float)*3;
+ case VET_FLOAT4:
+ return sizeof(float)*4;
+ case VET_DOUBLE1:
+ return sizeof(double);
+ case VET_DOUBLE2:
+ return sizeof(double)*2;
+ case VET_DOUBLE3:
+ return sizeof(double)*3;
+ case VET_DOUBLE4:
+ return sizeof(double)*4;
+ case VET_SHORT1:
+ return sizeof(short);
+ case VET_SHORT2:
+ return sizeof(short)*2;
+ case VET_SHORT3:
+ return sizeof(short)*3;
+ case VET_SHORT4:
+ return sizeof(short)*4;
+ case VET_USHORT1:
+ return sizeof(unsigned short);
+ case VET_USHORT2:
+ return sizeof(unsigned short)*2;
+ case VET_USHORT3:
+ return sizeof(unsigned short)*3;
+ case VET_USHORT4:
+ return sizeof(unsigned short)*4;
+ case VET_INT1:
+ return sizeof(int);
+ case VET_INT2:
+ return sizeof(int)*2;
+ case VET_INT3:
+ return sizeof(int)*3;
+ case VET_INT4:
+ return sizeof(int)*4;
+ case VET_UINT1:
+ return sizeof(unsigned int);
+ case VET_UINT2:
+ return sizeof(unsigned int)*2;
+ case VET_UINT3:
+ return sizeof(unsigned int)*3;
+ case VET_UINT4:
+ return sizeof(unsigned int)*4;
+ case VET_UBYTE4:
+ return sizeof(unsigned char)*4;
+ }
+ return 0;
}
std::string VertexElement::TypeToString()
{
- return TypeToString(type);
+ return TypeToString(type);
}
std::string VertexElement::TypeToString(Type type)
{
- switch(type)
- {
- case VET_COLOUR: return "COLOUR";
- case VET_COLOUR_ABGR: return "COLOUR_ABGR";
- case VET_COLOUR_ARGB: return "COLOUR_ARGB";
- case VET_FLOAT1: return "FLOAT1";
- case VET_FLOAT2: return "FLOAT2";
- case VET_FLOAT3: return "FLOAT3";
- case VET_FLOAT4: return "FLOAT4";
- case VET_DOUBLE1: return "DOUBLE1";
- case VET_DOUBLE2: return "DOUBLE2";
- case VET_DOUBLE3: return "DOUBLE3";
- case VET_DOUBLE4: return "DOUBLE4";
- case VET_SHORT1: return "SHORT1";
- case VET_SHORT2: return "SHORT2";
- case VET_SHORT3: return "SHORT3";
- case VET_SHORT4: return "SHORT4";
- case VET_USHORT1: return "USHORT1";
- case VET_USHORT2: return "USHORT2";
- case VET_USHORT3: return "USHORT3";
- case VET_USHORT4: return "USHORT4";
- case VET_INT1: return "INT1";
- case VET_INT2: return "INT2";
- case VET_INT3: return "INT3";
- case VET_INT4: return "INT4";
- case VET_UINT1: return "UINT1";
- case VET_UINT2: return "UINT2";
- case VET_UINT3: return "UINT3";
- case VET_UINT4: return "UINT4";
- case VET_UBYTE4: return "UBYTE4";
- }
- return "Uknown_VertexElement::Type";
+ switch(type)
+ {
+ case VET_COLOUR: return "COLOUR";
+ case VET_COLOUR_ABGR: return "COLOUR_ABGR";
+ case VET_COLOUR_ARGB: return "COLOUR_ARGB";
+ case VET_FLOAT1: return "FLOAT1";
+ case VET_FLOAT2: return "FLOAT2";
+ case VET_FLOAT3: return "FLOAT3";
+ case VET_FLOAT4: return "FLOAT4";
+ case VET_DOUBLE1: return "DOUBLE1";
+ case VET_DOUBLE2: return "DOUBLE2";
+ case VET_DOUBLE3: return "DOUBLE3";
+ case VET_DOUBLE4: return "DOUBLE4";
+ case VET_SHORT1: return "SHORT1";
+ case VET_SHORT2: return "SHORT2";
+ case VET_SHORT3: return "SHORT3";
+ case VET_SHORT4: return "SHORT4";
+ case VET_USHORT1: return "USHORT1";
+ case VET_USHORT2: return "USHORT2";
+ case VET_USHORT3: return "USHORT3";
+ case VET_USHORT4: return "USHORT4";
+ case VET_INT1: return "INT1";
+ case VET_INT2: return "INT2";
+ case VET_INT3: return "INT3";
+ case VET_INT4: return "INT4";
+ case VET_UINT1: return "UINT1";
+ case VET_UINT2: return "UINT2";
+ case VET_UINT3: return "UINT3";
+ case VET_UINT4: return "UINT4";
+ case VET_UBYTE4: return "UBYTE4";
+ }
+ return "Uknown_VertexElement::Type";
}
std::string VertexElement::SemanticToString()
{
- return SemanticToString(semantic);
+ return SemanticToString(semantic);
}
std::string VertexElement::SemanticToString(Semantic semantic)
{
- switch(semantic)
- {
- case VES_POSITION: return "POSITION";
- case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS";
- case VES_BLEND_INDICES: return "BLEND_INDICES";
- case VES_NORMAL: return "NORMAL";
- case VES_DIFFUSE: return "DIFFUSE";
- case VES_SPECULAR: return "SPECULAR";
- case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES";
- case VES_BINORMAL: return "BINORMAL";
- case VES_TANGENT: return "TANGENT";
- }
- return "Uknown_VertexElement::Semantic";
+ switch(semantic)
+ {
+ case VES_POSITION: return "POSITION";
+ case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS";
+ case VES_BLEND_INDICES: return "BLEND_INDICES";
+ case VES_NORMAL: return "NORMAL";
+ case VES_DIFFUSE: return "DIFFUSE";
+ case VES_SPECULAR: return "SPECULAR";
+ case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES";
+ case VES_BINORMAL: return "BINORMAL";
+ case VES_TANGENT: return "TANGENT";
+ }
+ return "Uknown_VertexElement::Semantic";
}
// IVertexData
IVertexData::IVertexData() :
- count(0)
+ count(0)
{
}
bool IVertexData::HasBoneAssignments() const
{
- return !boneAssignments.empty();
+ return !boneAssignments.empty();
}
void IVertexData::AddVertexMapping(uint32_t oldIndex, uint32_t newIndex)
{
- BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]);
- vertexIndexMapping[oldIndex].push_back(newIndex);
+ BoneAssignmentsForVertex(oldIndex, newIndex, boneAssignmentsMap[newIndex]);
+ vertexIndexMapping[oldIndex].push_back(newIndex);
}
void IVertexData::BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const
{
- for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
- iter!=end; ++iter)
- {
- if (iter->vertexIndex == currentIndex)
- {
- VertexBoneAssignment a = (*iter);
- a.vertexIndex = newIndex;
- dest.push_back(a);
- }
- }
+ for (const auto &boneAssign : boneAssignments)
+ {
+ if (boneAssign.vertexIndex == currentIndex)
+ {
+ VertexBoneAssignment a = boneAssign;
+ a.vertexIndex = newIndex;
+ dest.push_back(a);
+ }
+ }
}
AssimpVertexBoneWeightList IVertexData::AssimpBoneWeights(size_t vertices)
{
- AssimpVertexBoneWeightList weights;
- for(size_t vi=0; vi<vertices; ++vi)
- {
- VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi];
- for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end();
- iter!=end; ++iter)
- {
- std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex];
- boneWeights.push_back(aiVertexWeight(vi, iter->weight));
- }
- }
- return weights;
+ AssimpVertexBoneWeightList weights;
+ for(size_t vi=0; vi<vertices; ++vi)
+ {
+ VertexBoneAssignmentList &vertexWeights = boneAssignmentsMap[vi];
+ for (VertexBoneAssignmentList::const_iterator iter=vertexWeights.begin(), end=vertexWeights.end();
+ iter!=end; ++iter)
+ {
+ std::vector<aiVertexWeight> &boneWeights = weights[iter->boneIndex];
+ boneWeights.push_back(aiVertexWeight(vi, iter->weight));
+ }
+ }
+ return weights;
}
std::set<uint16_t> IVertexData::ReferencedBonesByWeights() const
{
- std::set<uint16_t> referenced;
- for (VertexBoneAssignmentList::const_iterator iter=boneAssignments.begin(), end=boneAssignments.end();
- iter!=end; ++iter)
- {
- referenced.insert(iter->boneIndex);
- }
- return referenced;
+ std::set<uint16_t> referenced;
+ for (const auto &boneAssign : boneAssignments)
+ {
+ referenced.insert(boneAssign.boneIndex);
+ }
+ return referenced;
}
// VertexData
@@ -301,43 +303,42 @@ VertexData::VertexData()
VertexData::~VertexData()
{
- Reset();
+ Reset();
}
void VertexData::Reset()
{
- // Releases shared ptr memory streams.
- vertexBindings.clear();
- vertexElements.clear();
+ // Releases shared ptr memory streams.
+ vertexBindings.clear();
+ vertexElements.clear();
}
uint32_t VertexData::VertexSize(uint16_t source) const
{
- uint32_t size = 0;
- for(VertexElementList::const_iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
- {
- if (iter->source == source)
- size += iter->Size();
- }
- return size;
+ uint32_t size = 0;
+ for(const auto &element : vertexElements)
+ {
+ if (element.source == source)
+ size += element.Size();
+ }
+ return size;
}
MemoryStream *VertexData::VertexBuffer(uint16_t source)
{
- if (vertexBindings.find(source) != vertexBindings.end())
- return vertexBindings[source].get();
- return 0;
+ if (vertexBindings.find(source) != vertexBindings.end())
+ return vertexBindings[source].get();
+ return 0;
}
VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index)
{
- for(VertexElementList::iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
- {
- VertexElement &element = (*iter);
- if (element.semantic == semantic && element.index == index)
- return &element;
- }
- return 0;
+ for(auto & element : vertexElements)
+ {
+ if (element.semantic == semantic && element.index == index)
+ return &element;
+ }
+ return 0;
}
// VertexDataXml
@@ -348,843 +349,853 @@ VertexDataXml::VertexDataXml()
bool VertexDataXml::HasPositions() const
{
- return !positions.empty();
+ return !positions.empty();
}
bool VertexDataXml::HasNormals() const
{
- return !normals.empty();
+ return !normals.empty();
}
bool VertexDataXml::HasTangents() const
{
- return !tangents.empty();
+ return !tangents.empty();
}
bool VertexDataXml::HasUvs() const
{
- return !uvs.empty();
+ return !uvs.empty();
}
size_t VertexDataXml::NumUvs() const
{
- return uvs.size();
+ return uvs.size();
}
// IndexData
IndexData::IndexData() :
- count(0),
- faceCount(0),
- is32bit(false)
+ count(0),
+ faceCount(0),
+ is32bit(false)
{
}
IndexData::~IndexData()
{
- Reset();
+ Reset();
}
void IndexData::Reset()
{
- // Release shared ptr memory stream.
- buffer.reset();
+ // Release shared ptr memory stream.
+ buffer.reset();
}
size_t IndexData::IndexSize() const
{
- return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
+ return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
}
size_t IndexData::FaceSize() const
{
- return IndexSize() * 3;
+ return IndexSize() * 3;
}
// Mesh
-Mesh::Mesh() :
- sharedVertexData(0),
- skeleton(0),
- hasSkeletalAnimations(false)
+Mesh::Mesh()
+ : hasSkeletalAnimations(false)
+ , skeleton(NULL)
+ , sharedVertexData(NULL)
+ , subMeshes()
+ , animations()
+ , poses()
{
}
Mesh::~Mesh()
{
- Reset();
+ Reset();
}
void Mesh::Reset()
{
- OGRE_SAFE_DELETE(skeleton)
- OGRE_SAFE_DELETE(sharedVertexData)
+ OGRE_SAFE_DELETE(skeleton)
+ OGRE_SAFE_DELETE(sharedVertexData)
- for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(subMeshes[i])
- }
- subMeshes.clear();
- for(size_t i=0, len=animations.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(animations[i])
- }
- animations.clear();
- for(size_t i=0, len=poses.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(poses[i])
- }
- poses.clear();
+ for(auto &mesh : subMeshes) {
+ OGRE_SAFE_DELETE(mesh)
+ }
+ subMeshes.clear();
+ for(auto &anim : animations) {
+ OGRE_SAFE_DELETE(anim)
+ }
+ animations.clear();
+ for(auto &pose : poses) {
+ OGRE_SAFE_DELETE(pose)
+ }
+ poses.clear();
}
size_t Mesh::NumSubMeshes() const
{
- return subMeshes.size();
+ return subMeshes.size();
}
-SubMesh *Mesh::GetSubMesh(uint16_t index) const
+SubMesh *Mesh::GetSubMesh( size_t index ) const
{
- for(size_t i=0; i<subMeshes.size(); ++i)
- if (subMeshes[i]->index == index)
- return subMeshes[i];
- return 0;
+ for ( size_t i = 0; i < subMeshes.size(); ++i ) {
+ if ( subMeshes[ i ]->index == index ) {
+ return subMeshes[ i ];
+ }
+ }
+ return 0;
}
void Mesh::ConvertToAssimpScene(aiScene* dest)
{
- // Setup
- dest->mNumMeshes = NumSubMeshes();
- dest->mMeshes = new aiMesh*[dest->mNumMeshes];
-
- // Create root node
- dest->mRootNode = new aiNode();
- dest->mRootNode->mNumMeshes = dest->mNumMeshes;
- dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
-
- // Export meshes
- for(size_t i=0; i<dest->mNumMeshes; ++i)
- {
- dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
- dest->mRootNode->mMeshes[i] = i;
- }
-
- // Export skeleton
- if (skeleton)
- {
- // Bones
- if (!skeleton->bones.empty())
- {
- BoneList rootBones = skeleton->RootBones();
- dest->mRootNode->mNumChildren = rootBones.size();
- dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
-
- for(size_t i=0, len=rootBones.size(); i<len; ++i)
- {
- dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
- }
- }
-
- // Animations
- if (!skeleton->animations.empty())
- {
- dest->mNumAnimations = skeleton->animations.size();
- dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
-
- for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
- {
- dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
- }
- }
- }
+ if ( nullptr == dest ) {
+ return;
+ }
+
+ // Setup
+ dest->mNumMeshes = NumSubMeshes();
+ dest->mMeshes = new aiMesh*[dest->mNumMeshes];
+
+ // Create root node
+ dest->mRootNode = new aiNode();
+ dest->mRootNode->mNumMeshes = dest->mNumMeshes;
+ dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
+
+ // Export meshes
+ for(size_t i=0; i<dest->mNumMeshes; ++i) {
+ dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
+ dest->mRootNode->mMeshes[i] = i;
+ }
+
+ // Export skeleton
+ if (skeleton)
+ {
+ // Bones
+ if (!skeleton->bones.empty())
+ {
+ BoneList rootBones = skeleton->RootBones();
+ dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
+
+ for(size_t i=0, len=rootBones.size(); i<len; ++i)
+ {
+ dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
+ }
+ }
+
+ // Animations
+ if (!skeleton->animations.empty())
+ {
+ dest->mNumAnimations = skeleton->animations.size();
+ dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
+
+ for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
+ {
+ dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
+ }
+ }
+ }
}
// ISubMesh
ISubMesh::ISubMesh() :
- index(0),
- materialIndex(-1),
- usesSharedVertexData(false),
- operationType(OT_POINT_LIST)
+ index(0),
+ materialIndex(-1),
+ usesSharedVertexData(false),
+ operationType(OT_POINT_LIST)
{
}
// SubMesh
SubMesh::SubMesh() :
- vertexData(0),
- indexData(new IndexData())
+ vertexData(0),
+ indexData(new IndexData())
{
}
SubMesh::~SubMesh()
{
- Reset();
+ Reset();
}
void SubMesh::Reset()
{
- OGRE_SAFE_DELETE(vertexData)
- OGRE_SAFE_DELETE(indexData)
+ OGRE_SAFE_DELETE(vertexData)
+ OGRE_SAFE_DELETE(indexData)
}
aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
{
- if (operationType != OT_TRIANGLE_LIST) {
- throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType);
- }
-
- aiMesh *dest = new aiMesh();
- dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- if (!name.empty())
- dest->mName = name;
-
- // Material index
- if (materialIndex != -1)
- dest->mMaterialIndex = materialIndex;
-
- // Pick source vertex data from shader geometry or from internal geometry.
- VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
-
- VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION);
- VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL);
- VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0);
- VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1);
-
- // Sanity checks
- if (!positionsElement) {
- throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!");
- } else if (positionsElement->type != VertexElement::VET_FLOAT3) {
- throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
- } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) {
- throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
- }
-
- // Faces
- dest->mNumFaces = indexData->faceCount;
- dest->mFaces = new aiFace[dest->mNumFaces];
-
- // Assimp required unique vertices, we need to convert from Ogres shared indexing.
- size_t uniqueVertexCount = dest->mNumFaces * 3;
- dest->mNumVertices = uniqueVertexCount;
- dest->mVertices = new aiVector3D[dest->mNumVertices];
-
- // Source streams
- MemoryStream *positions = src->VertexBuffer(positionsElement->source);
- MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0);
- MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0);
- MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0);
-
- // Element size
- const size_t sizePosition = positionsElement->Size();
- const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0);
- const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0);
- const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0);
-
- // Vertex width
- const size_t vWidthPosition = src->VertexSize(positionsElement->source);
- const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0);
- const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0);
- const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0);
-
- bool boneAssignments = src->HasBoneAssignments();
-
- // Prepare normals
- if (normals)
- dest->mNormals = new aiVector3D[dest->mNumVertices];
-
- // Prepare UVs, ignoring incompatible UVs.
- if (uv1)
- {
- if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
- {
- dest->mNumUVComponents[0] = uv1Element->ComponentCount();
- dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
- }
- else
- {
- DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
- uv1 = 0;
- }
- }
- if (uv2)
- {
- if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
- {
- dest->mNumUVComponents[1] = uv2Element->ComponentCount();
- dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
- }
- else
- {
- DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
- uv2 = 0;
- }
- }
-
- aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0);
- aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0);
-
- MemoryStream *faces = indexData->buffer.get();
- for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize();
- fi<dest->mNumFaces; ++fi)
- {
- // Source Ogre face
- aiFace ogreFace;
- ogreFace.mNumIndices = 3;
- ogreFace.mIndices = new unsigned int[3];
-
- faces->Seek(fi * fsize, aiOrigin_SET);
- if (indexData->is32bit)
- {
- faces->Read(&ogreFace.mIndices[0], isize, 3);
- }
- else
- {
- uint16_t iout = 0;
- for (size_t ii=0; ii<3; ++ii)
- {
- faces->Read(&iout, isize, 1);
- ogreFace.mIndices[ii] = static_cast<unsigned int>(iout);
- }
- }
-
- // Destination Assimp face
- aiFace &face = dest->mFaces[fi];
- face.mNumIndices = 3;
- face.mIndices = new unsigned int[3];
-
- const size_t pos = fi * 3;
- for (size_t v=0; v<3; ++v)
- {
- const size_t newIndex = pos + v;
-
- // Write face index
- face.mIndices[v] = newIndex;
-
- // Ogres vertex index to ref into the source buffers.
- const size_t ogreVertexIndex = ogreFace.mIndices[v];
- src->AddVertexMapping(ogreVertexIndex, newIndex);
-
- // Position
- positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
- positions->Read(&dest->mVertices[newIndex], sizePosition, 1);
-
- // Normal
- if (normals)
- {
- normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET);
- normals->Read(&dest->mNormals[newIndex], sizeNormal, 1);
- }
- // UV0
- if (uv1 && uv1Dest)
- {
- uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET);
- uv1->Read(&uv1Dest[newIndex], sizeUv1, 1);
- uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
- }
- // UV1
- if (uv2 && uv2Dest)
- {
- uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET);
- uv2->Read(&uv2Dest[newIndex], sizeUv2, 1);
- uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
- }
- }
- }
-
- // Bones and bone weights
- if (parent->skeleton && boneAssignments)
- {
- AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
- std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
-
- dest->mNumBones = referencedBones.size();
- dest->mBones = new aiBone*[dest->mNumBones];
-
- size_t assimpBoneIndex = 0;
- for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
- {
- Bone *bone = parent->skeleton->BoneById((*rbIter));
- dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
- }
- }
-
- return dest;
+ if (operationType != OT_TRIANGLE_LIST) {
+ throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType);
+ }
+
+ aiMesh *dest = new aiMesh();
+ dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ if (!name.empty())
+ dest->mName = name;
+
+ // Material index
+ if (materialIndex != -1)
+ dest->mMaterialIndex = materialIndex;
+
+ // Pick source vertex data from shader geometry or from internal geometry.
+ VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
+
+ VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION);
+ VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL);
+ VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0);
+ VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1);
+
+ // Sanity checks
+ if (!positionsElement) {
+ throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!");
+ } else if (positionsElement->type != VertexElement::VET_FLOAT3) {
+ throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
+ } else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) {
+ throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
+ }
+
+ // Faces
+ dest->mNumFaces = indexData->faceCount;
+ dest->mFaces = new aiFace[dest->mNumFaces];
+
+ // Assimp required unique vertices, we need to convert from Ogres shared indexing.
+ size_t uniqueVertexCount = dest->mNumFaces * 3;
+ dest->mNumVertices = uniqueVertexCount;
+ dest->mVertices = new aiVector3D[dest->mNumVertices];
+
+ // Source streams
+ MemoryStream *positions = src->VertexBuffer(positionsElement->source);
+ MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0);
+ MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0);
+ MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0);
+
+ // Element size
+ const size_t sizePosition = positionsElement->Size();
+ const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0);
+ const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0);
+ const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0);
+
+ // Vertex width
+ const size_t vWidthPosition = src->VertexSize(positionsElement->source);
+ const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0);
+ const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0);
+ const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0);
+
+ bool boneAssignments = src->HasBoneAssignments();
+
+ // Prepare normals
+ if (normals)
+ dest->mNormals = new aiVector3D[dest->mNumVertices];
+
+ // Prepare UVs, ignoring incompatible UVs.
+ if (uv1)
+ {
+ if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
+ {
+ dest->mNumUVComponents[0] = uv1Element->ComponentCount();
+ dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
+ }
+ else
+ {
+ DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
+ uv1 = 0;
+ }
+ }
+ if (uv2)
+ {
+ if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
+ {
+ dest->mNumUVComponents[1] = uv2Element->ComponentCount();
+ dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
+ }
+ else
+ {
+ DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
+ uv2 = 0;
+ }
+ }
+
+ aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0);
+ aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0);
+
+ MemoryStream *faces = indexData->buffer.get();
+ for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize();
+ fi<dest->mNumFaces; ++fi)
+ {
+ // Source Ogre face
+ aiFace ogreFace;
+ ogreFace.mNumIndices = 3;
+ ogreFace.mIndices = new unsigned int[3];
+
+ faces->Seek(fi * fsize, aiOrigin_SET);
+ if (indexData->is32bit)
+ {
+ faces->Read(&ogreFace.mIndices[0], isize, 3);
+ }
+ else
+ {
+ uint16_t iout = 0;
+ for (size_t ii=0; ii<3; ++ii)
+ {
+ faces->Read(&iout, isize, 1);
+ ogreFace.mIndices[ii] = static_cast<unsigned int>(iout);
+ }
+ }
+
+ // Destination Assimp face
+ aiFace &face = dest->mFaces[fi];
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+
+ const size_t pos = fi * 3;
+ for (size_t v=0; v<3; ++v)
+ {
+ const size_t newIndex = pos + v;
+
+ // Write face index
+ face.mIndices[v] = newIndex;
+
+ // Ogres vertex index to ref into the source buffers.
+ const size_t ogreVertexIndex = ogreFace.mIndices[v];
+ src->AddVertexMapping(ogreVertexIndex, newIndex);
+
+ // Position
+ positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
+ positions->Read(&dest->mVertices[newIndex], sizePosition, 1);
+
+ // Normal
+ if (normals)
+ {
+ normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET);
+ normals->Read(&dest->mNormals[newIndex], sizeNormal, 1);
+ }
+ // UV0
+ if (uv1 && uv1Dest)
+ {
+ uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET);
+ uv1->Read(&uv1Dest[newIndex], sizeUv1, 1);
+ uv1Dest[newIndex].y = (uv1Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
+ }
+ // UV1
+ if (uv2 && uv2Dest)
+ {
+ uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET);
+ uv2->Read(&uv2Dest[newIndex], sizeUv2, 1);
+ uv2Dest[newIndex].y = (uv2Dest[newIndex].y * -1) + 1; // Flip UV from Ogre to Assimp form
+ }
+ }
+ }
+
+ // Bones and bone weights
+ if (parent->skeleton && boneAssignments)
+ {
+ AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
+ std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
+
+ dest->mNumBones = referencedBones.size();
+ dest->mBones = new aiBone*[dest->mNumBones];
+
+ size_t assimpBoneIndex = 0;
+ for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
+ {
+ Bone *bone = parent->skeleton->BoneById((*rbIter));
+ dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
+ }
+ }
+
+ return dest;
}
// MeshXml
MeshXml::MeshXml() :
- sharedVertexData(0),
- skeleton(0)
+ skeleton(0),
+ sharedVertexData(0)
{
}
MeshXml::~MeshXml()
{
- Reset();
+ Reset();
}
void MeshXml::Reset()
{
- OGRE_SAFE_DELETE(skeleton)
- OGRE_SAFE_DELETE(sharedVertexData)
+ OGRE_SAFE_DELETE(skeleton)
+ OGRE_SAFE_DELETE(sharedVertexData)
- for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(subMeshes[i])
- }
- subMeshes.clear();
+ for(auto &mesh : subMeshes) {
+ OGRE_SAFE_DELETE(mesh)
+ }
+ subMeshes.clear();
}
size_t MeshXml::NumSubMeshes() const
{
- return subMeshes.size();
+ return subMeshes.size();
}
SubMeshXml *MeshXml::GetSubMesh(uint16_t index) const
{
- for(size_t i=0; i<subMeshes.size(); ++i)
- if (subMeshes[i]->index == index)
- return subMeshes[i];
- return 0;
+ for(size_t i=0; i<subMeshes.size(); ++i)
+ if (subMeshes[i]->index == index)
+ return subMeshes[i];
+ return 0;
}
void MeshXml::ConvertToAssimpScene(aiScene* dest)
{
- // Setup
- dest->mNumMeshes = NumSubMeshes();
- dest->mMeshes = new aiMesh*[dest->mNumMeshes];
-
- // Create root node
- dest->mRootNode = new aiNode();
- dest->mRootNode->mNumMeshes = dest->mNumMeshes;
- dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
-
- // Export meshes
- for(size_t i=0; i<dest->mNumMeshes; ++i)
- {
- dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
- dest->mRootNode->mMeshes[i] = i;
- }
-
- // Export skeleton
- if (skeleton)
- {
- // Bones
- if (!skeleton->bones.empty())
- {
- BoneList rootBones = skeleton->RootBones();
- dest->mRootNode->mNumChildren = rootBones.size();
- dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
-
- for(size_t i=0, len=rootBones.size(); i<len; ++i)
- {
- dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
- }
- }
-
- // Animations
- if (!skeleton->animations.empty())
- {
- dest->mNumAnimations = skeleton->animations.size();
- dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
-
- for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
- {
- dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
- }
- }
- }
+ // Setup
+ dest->mNumMeshes = NumSubMeshes();
+ dest->mMeshes = new aiMesh*[dest->mNumMeshes];
+
+ // Create root node
+ dest->mRootNode = new aiNode();
+ dest->mRootNode->mNumMeshes = dest->mNumMeshes;
+ dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
+
+ // Export meshes
+ for(size_t i=0; i<dest->mNumMeshes; ++i)
+ {
+ dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
+ dest->mRootNode->mMeshes[i] = i;
+ }
+
+ // Export skeleton
+ if (skeleton)
+ {
+ // Bones
+ if (!skeleton->bones.empty())
+ {
+ BoneList rootBones = skeleton->RootBones();
+ dest->mRootNode->mNumChildren = rootBones.size();
+ dest->mRootNode->mChildren = new aiNode*[dest->mRootNode->mNumChildren];
+
+ for(size_t i=0, len=rootBones.size(); i<len; ++i)
+ {
+ dest->mRootNode->mChildren[i] = rootBones[i]->ConvertToAssimpNode(skeleton, dest->mRootNode);
+ }
+ }
+
+ // Animations
+ if (!skeleton->animations.empty())
+ {
+ dest->mNumAnimations = skeleton->animations.size();
+ dest->mAnimations = new aiAnimation*[dest->mNumAnimations];
+
+ for(size_t i=0, len=skeleton->animations.size(); i<len; ++i)
+ {
+ dest->mAnimations[i] = skeleton->animations[i]->ConvertToAssimpAnimation();
+ }
+ }
+ }
}
// SubMeshXml
SubMeshXml::SubMeshXml() :
- vertexData(0),
- indexData(new IndexDataXml())
+ indexData(new IndexDataXml()),
+ vertexData(0)
{
}
SubMeshXml::~SubMeshXml()
{
- Reset();
+ Reset();
}
void SubMeshXml::Reset()
{
- OGRE_SAFE_DELETE(indexData)
- OGRE_SAFE_DELETE(vertexData)
+ OGRE_SAFE_DELETE(indexData)
+ OGRE_SAFE_DELETE(vertexData)
}
aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
{
- aiMesh *dest = new aiMesh();
- dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- if (!name.empty())
- dest->mName = name;
-
- // Material index
- if (materialIndex != -1)
- dest->mMaterialIndex = materialIndex;
-
- // Faces
- dest->mNumFaces = indexData->faceCount;
- dest->mFaces = new aiFace[dest->mNumFaces];
-
- // Assimp required unique vertices, we need to convert from Ogres shared indexing.
- size_t uniqueVertexCount = dest->mNumFaces * 3;
- dest->mNumVertices = uniqueVertexCount;
- dest->mVertices = new aiVector3D[dest->mNumVertices];
-
- VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
- bool boneAssignments = src->HasBoneAssignments();
- bool normals = src->HasNormals();
- size_t uvs = src->NumUvs();
-
- // Prepare normals
- if (normals)
- dest->mNormals = new aiVector3D[dest->mNumVertices];
-
- // Prepare UVs
- for(size_t uvi=0; uvi<uvs; ++uvi)
- {
- dest->mNumUVComponents[uvi] = 2;
- dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices];
- }
-
- for (size_t fi=0; fi<dest->mNumFaces; ++fi)
- {
- // Source Ogre face
- aiFace &ogreFace = indexData->faces[fi];
-
- // Destination Assimp face
- aiFace &face = dest->mFaces[fi];
- face.mNumIndices = 3;
- face.mIndices = new unsigned int[3];
-
- const size_t pos = fi * 3;
- for (size_t v=0; v<3; ++v)
- {
- const size_t newIndex = pos + v;
-
- // Write face index
- face.mIndices[v] = newIndex;
-
- // Ogres vertex index to ref into the source buffers.
- const size_t ogreVertexIndex = ogreFace.mIndices[v];
- src->AddVertexMapping(ogreVertexIndex, newIndex);
-
- // Position
- dest->mVertices[newIndex] = src->positions[ogreVertexIndex];
-
- // Normal
- if (normals)
- dest->mNormals[newIndex] = src->normals[ogreVertexIndex];
-
- // UVs
- for(size_t uvi=0; uvi<uvs; ++uvi)
- {
- aiVector3D *uvDest = dest->mTextureCoords[uvi];
- std::vector<aiVector3D> &uvSrc = src->uvs[uvi];
- uvDest[newIndex] = uvSrc[ogreVertexIndex];
- }
- }
- }
-
- // Bones and bone weights
- if (parent->skeleton && boneAssignments)
- {
- AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
- std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
-
- dest->mNumBones = referencedBones.size();
- dest->mBones = new aiBone*[dest->mNumBones];
-
- size_t assimpBoneIndex = 0;
- for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
- {
- Bone *bone = parent->skeleton->BoneById((*rbIter));
- dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
- }
- }
-
- return dest;
+ aiMesh *dest = new aiMesh();
+ dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ if (!name.empty())
+ dest->mName = name;
+
+ // Material index
+ if (materialIndex != -1)
+ dest->mMaterialIndex = materialIndex;
+
+ // Faces
+ dest->mNumFaces = indexData->faceCount;
+ dest->mFaces = new aiFace[dest->mNumFaces];
+
+ // Assimp required unique vertices, we need to convert from Ogres shared indexing.
+ size_t uniqueVertexCount = dest->mNumFaces * 3;
+ dest->mNumVertices = uniqueVertexCount;
+ dest->mVertices = new aiVector3D[dest->mNumVertices];
+
+ VertexDataXml *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
+ bool boneAssignments = src->HasBoneAssignments();
+ bool normals = src->HasNormals();
+ size_t uvs = src->NumUvs();
+
+ // Prepare normals
+ if (normals)
+ dest->mNormals = new aiVector3D[dest->mNumVertices];
+
+ // Prepare UVs
+ for(size_t uvi=0; uvi<uvs; ++uvi)
+ {
+ dest->mNumUVComponents[uvi] = 2;
+ dest->mTextureCoords[uvi] = new aiVector3D[dest->mNumVertices];
+ }
+
+ for (size_t fi=0; fi<dest->mNumFaces; ++fi)
+ {
+ // Source Ogre face
+ aiFace &ogreFace = indexData->faces[fi];
+
+ // Destination Assimp face
+ aiFace &face = dest->mFaces[fi];
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+
+ const size_t pos = fi * 3;
+ for (size_t v=0; v<3; ++v)
+ {
+ const size_t newIndex = pos + v;
+
+ // Write face index
+ face.mIndices[v] = newIndex;
+
+ // Ogres vertex index to ref into the source buffers.
+ const size_t ogreVertexIndex = ogreFace.mIndices[v];
+ src->AddVertexMapping(ogreVertexIndex, newIndex);
+
+ // Position
+ dest->mVertices[newIndex] = src->positions[ogreVertexIndex];
+
+ // Normal
+ if (normals)
+ dest->mNormals[newIndex] = src->normals[ogreVertexIndex];
+
+ // UVs
+ for(size_t uvi=0; uvi<uvs; ++uvi)
+ {
+ aiVector3D *uvDest = dest->mTextureCoords[uvi];
+ std::vector<aiVector3D> &uvSrc = src->uvs[uvi];
+ uvDest[newIndex] = uvSrc[ogreVertexIndex];
+ }
+ }
+ }
+
+ // Bones and bone weights
+ if (parent->skeleton && boneAssignments)
+ {
+ AssimpVertexBoneWeightList weights = src->AssimpBoneWeights(dest->mNumVertices);
+ std::set<uint16_t> referencedBones = src->ReferencedBonesByWeights();
+
+ dest->mNumBones = referencedBones.size();
+ dest->mBones = new aiBone*[dest->mNumBones];
+
+ size_t assimpBoneIndex = 0;
+ for(std::set<uint16_t>::const_iterator rbIter=referencedBones.begin(), rbEnd=referencedBones.end(); rbIter != rbEnd; ++rbIter, ++assimpBoneIndex)
+ {
+ Bone *bone = parent->skeleton->BoneById((*rbIter));
+ dest->mBones[assimpBoneIndex] = bone->ConvertToAssimpBone(parent->skeleton, weights[bone->id]);
+ }
+ }
+
+ return dest;
}
// Animation
Animation::Animation(Skeleton *parent) :
- parentSkeleton(parent),
- parentMesh(0),
- length(0.0f),
- baseTime(-1.0f)
+ parentMesh(NULL),
+ parentSkeleton(parent),
+ length(0.0f),
+ baseTime(-1.0f)
{
}
-Animation::Animation(Mesh *parent) :
- parentMesh(parent),
- parentSkeleton(0),
- length(0.0f),
- baseTime(-1.0f)
+Animation::Animation(Mesh *parent) :
+ parentMesh(parent),
+ parentSkeleton(0),
+ length(0.0f),
+ baseTime(-1.0f)
{
}
VertexData *Animation::AssociatedVertexData(VertexAnimationTrack *track) const
{
- if (!parentMesh)
- return 0;
+ if (!parentMesh)
+ return 0;
- bool sharedGeom = (track->target == 0);
- if (sharedGeom)
- return parentMesh->sharedVertexData;
- else
- return parentMesh->GetSubMesh(track->target-1)->vertexData;
+ bool sharedGeom = (track->target == 0);
+ if (sharedGeom)
+ return parentMesh->sharedVertexData;
+ else
+ return parentMesh->GetSubMesh(track->target-1)->vertexData;
}
aiAnimation *Animation::ConvertToAssimpAnimation()
{
- aiAnimation *anim = new aiAnimation();
- anim->mName = name;
- anim->mDuration = static_cast<double>(length);
- anim->mTicksPerSecond = 1.0;
-
- // Tracks
- if (!tracks.empty())
- {
- anim->mNumChannels = tracks.size();
- anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-
- for(size_t i=0, len=tracks.size(); i<len; ++i)
- {
- anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton);
- }
- }
- return anim;
+ aiAnimation *anim = new aiAnimation();
+ anim->mName = name;
+ anim->mDuration = static_cast<double>(length);
+ anim->mTicksPerSecond = 1.0;
+
+ // Tracks
+ if (!tracks.empty())
+ {
+ anim->mNumChannels = tracks.size();
+ anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+ for(size_t i=0, len=tracks.size(); i<len; ++i)
+ {
+ anim->mChannels[i] = tracks[i].ConvertToAssimpAnimationNode(parentSkeleton);
+ }
+ }
+ return anim;
}
// Skeleton
Skeleton::Skeleton() :
- blendMode(ANIMBLEND_AVERAGE)
+ bones(),
+ animations(),
+ blendMode(ANIMBLEND_AVERAGE)
{
}
Skeleton::~Skeleton()
{
- Reset();
+ Reset();
}
void Skeleton::Reset()
{
- for(size_t i=0, len=bones.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(bones[i])
- }
- bones.clear();
- for(size_t i=0, len=animations.size(); i<len; ++i) {
- OGRE_SAFE_DELETE(animations[i])
- }
- animations.clear();
+ for(auto &bone : bones) {
+ OGRE_SAFE_DELETE(bone)
+ }
+ bones.clear();
+ for(auto &anim : animations) {
+ OGRE_SAFE_DELETE(anim)
+ }
+ animations.clear();
}
BoneList Skeleton::RootBones() const
{
- BoneList rootBones;
- for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
- {
- if (!(*iter)->IsParented())
- rootBones.push_back((*iter));
- }
- return rootBones;
+ BoneList rootBones;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if (!(*iter)->IsParented())
+ rootBones.push_back((*iter));
+ }
+ return rootBones;
}
size_t Skeleton::NumRootBones() const
{
- size_t num = 0;
- for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
- {
- if (!(*iter)->IsParented())
- num++;
- }
- return num;
+ size_t num = 0;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if (!(*iter)->IsParented())
+ num++;
+ }
+ return num;
}
Bone *Skeleton::BoneByName(const std::string &name) const
{
- for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
- {
- if ((*iter)->name == name)
- return (*iter);
- }
- return 0;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if ((*iter)->name == name)
+ return (*iter);
+ }
+ return 0;
}
Bone *Skeleton::BoneById(uint16_t id) const
{
- for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
- {
- if ((*iter)->id == id)
- return (*iter);
- }
- return 0;
+ for(BoneList::const_iterator iter = bones.begin(); iter != bones.end(); ++iter)
+ {
+ if ((*iter)->id == id)
+ return (*iter);
+ }
+ return 0;
}
// Bone
Bone::Bone() :
- id(0),
- parent(0),
- parentId(-1),
- scale(1.0f, 1.0f, 1.0f)
+ id(0),
+ parent(0),
+ parentId(-1),
+ scale(1.0f, 1.0f, 1.0f)
{
}
bool Bone::IsParented() const
{
- return (parentId != -1 && parent != 0);
+ return (parentId != -1 && parent != 0);
}
uint16_t Bone::ParentId() const
{
- return static_cast<uint16_t>(parentId);
+ return static_cast<uint16_t>(parentId);
}
void Bone::AddChild(Bone *bone)
{
- if (!bone)
- return;
- if (bone->IsParented())
- throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name);
-
- bone->parent = this;
- bone->parentId = id;
- children.push_back(bone->id);
+ if (!bone)
+ return;
+ if (bone->IsParented())
+ throw DeadlyImportError("Attaching child Bone that is already parented: " + bone->name);
+
+ bone->parent = this;
+ bone->parentId = id;
+ children.push_back(bone->id);
}
void Bone::CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton)
{
- if (!IsParented())
- worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse();
- else
- worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix;
+ if (!IsParented())
+ worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse();
+ else
+ worldMatrix = aiMatrix4x4(scale, rotation, position).Inverse() * parent->worldMatrix;
- defaultPose = aiMatrix4x4(scale, rotation, position);
+ defaultPose = aiMatrix4x4(scale, rotation, position);
- // Recursively for all children now that the parent matrix has been calculated.
- for (size_t i=0, len=children.size(); i<len; ++i)
- {
- Bone *child = skeleton->BoneById(children[i]);
- if (!child) {
- throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
- }
- child->CalculateWorldMatrixAndDefaultPose(skeleton);
- }
+ // Recursively for all children now that the parent matrix has been calculated.
+ for (auto boneId : children)
+ {
+ Bone *child = skeleton->BoneById(boneId);
+ if (!child) {
+ throw DeadlyImportError(Formatter::format() << "CalculateWorldMatrixAndDefaultPose: Failed to find child bone " << boneId << " for parent " << id << " " << name);
+ }
+ child->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
}
aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
{
- // Bone node
- aiNode* node = new aiNode(name);
- node->mParent = parentNode;
- node->mTransformation = defaultPose;
-
- // Children
- if (!children.empty())
- {
- node->mNumChildren = children.size();
- node->mChildren = new aiNode*[node->mNumChildren];
-
- for(size_t i=0, len=children.size(); i<len; ++i)
- {
- Bone *child = skeleton->BoneById(children[i]);
- if (!child) {
- throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
- }
- node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node);
- }
- }
- return node;
-}
-
-aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights)
-{
- aiBone *bone = new aiBone();
- bone->mName = name;
- bone->mOffsetMatrix = worldMatrix;
-
- if (!boneWeights.empty())
- {
- bone->mNumWeights = boneWeights.size();
- bone->mWeights = new aiVertexWeight[boneWeights.size()];
- memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
- }
-
- return bone;
+ // Bone node
+ aiNode* node = new aiNode(name);
+ node->mParent = parentNode;
+ node->mTransformation = defaultPose;
+
+ // Children
+ if (!children.empty())
+ {
+ node->mNumChildren = children.size();
+ node->mChildren = new aiNode*[node->mNumChildren];
+
+ for(size_t i=0, len=children.size(); i<len; ++i)
+ {
+ Bone *child = skeleton->BoneById(children[i]);
+ if (!child) {
+ throw DeadlyImportError(Formatter::format() << "ConvertToAssimpNode: Failed to find child bone " << children[i] << " for parent " << id << " " << name);
+ }
+ node->mChildren[i] = child->ConvertToAssimpNode(skeleton, node);
+ }
+ }
+ return node;
+}
+
+aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
+{
+ aiBone *bone = new aiBone();
+ bone->mName = name;
+ bone->mOffsetMatrix = worldMatrix;
+
+ if (!boneWeights.empty())
+ {
+ bone->mNumWeights = boneWeights.size();
+ bone->mWeights = new aiVertexWeight[boneWeights.size()];
+ memcpy(bone->mWeights, &boneWeights[0], boneWeights.size() * sizeof(aiVertexWeight));
+ }
+
+ return bone;
}
// VertexAnimationTrack
VertexAnimationTrack::VertexAnimationTrack() :
- target(0),
- type(VAT_NONE)
+ type(VAT_NONE),
+ target(0)
{
}
aiNodeAnim *VertexAnimationTrack::ConvertToAssimpAnimationNode(Skeleton *skeleton)
{
- if (boneName.empty() || type != VAT_TRANSFORM) {
- throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM");
- }
+ if (boneName.empty() || type != VAT_TRANSFORM) {
+ throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM");
+ }
+
+ aiNodeAnim *nodeAnim = new aiNodeAnim();
+ nodeAnim->mNodeName = boneName;
- aiNodeAnim *nodeAnim = new aiNodeAnim();
- nodeAnim->mNodeName = boneName;
-
- Bone *bone = skeleton->BoneByName(boneName);
- if (!bone) {
- throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton");
- }
+ Bone *bone = skeleton->BoneByName(boneName);
+ if (!bone) {
+ throw DeadlyImportError("VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton");
+ }
- // Keyframes
- size_t numKeyframes = transformKeyFrames.size();
+ // Keyframes
+ size_t numKeyframes = transformKeyFrames.size();
- nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes];
- nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes];
- nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes];
- nodeAnim->mNumPositionKeys = numKeyframes;
- nodeAnim->mNumRotationKeys = numKeyframes;
- nodeAnim->mNumScalingKeys = numKeyframes;
+ nodeAnim->mPositionKeys = new aiVectorKey[numKeyframes];
+ nodeAnim->mRotationKeys = new aiQuatKey[numKeyframes];
+ nodeAnim->mScalingKeys = new aiVectorKey[numKeyframes];
+ nodeAnim->mNumPositionKeys = numKeyframes;
+ nodeAnim->mNumRotationKeys = numKeyframes;
+ nodeAnim->mNumScalingKeys = numKeyframes;
- for(size_t kfi=0; kfi<numKeyframes; ++kfi)
- {
- TransformKeyFrame &kfSource = transformKeyFrames[kfi];
+ for(size_t kfi=0; kfi<numKeyframes; ++kfi)
+ {
+ TransformKeyFrame &kfSource = transformKeyFrames[kfi];
- // Calculate the complete transformation from world space to bone space
- aiVector3D pos; aiQuaternion rot; aiVector3D scale;
+ // Calculate the complete transformation from world space to bone space
+ aiVector3D pos; aiQuaternion rot; aiVector3D scale;
- aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform();
- finalTransform.Decompose(scale, rot, pos);
+ aiMatrix4x4 finalTransform = bone->defaultPose * kfSource.Transform();
+ finalTransform.Decompose(scale, rot, pos);
- double t = static_cast<double>(kfSource.timePos);
- nodeAnim->mPositionKeys[kfi].mTime = t;
- nodeAnim->mRotationKeys[kfi].mTime = t;
- nodeAnim->mScalingKeys[kfi].mTime = t;
+ double t = static_cast<double>(kfSource.timePos);
+ nodeAnim->mPositionKeys[kfi].mTime = t;
+ nodeAnim->mRotationKeys[kfi].mTime = t;
+ nodeAnim->mScalingKeys[kfi].mTime = t;
- nodeAnim->mPositionKeys[kfi].mValue = pos;
- nodeAnim->mRotationKeys[kfi].mValue = rot;
- nodeAnim->mScalingKeys[kfi].mValue = scale;
- }
+ nodeAnim->mPositionKeys[kfi].mValue = pos;
+ nodeAnim->mRotationKeys[kfi].mValue = rot;
+ nodeAnim->mScalingKeys[kfi].mValue = scale;
+ }
- return nodeAnim;
+ return nodeAnim;
}
// TransformKeyFrame
-TransformKeyFrame::TransformKeyFrame() :
- timePos(0.0f),
- scale(1.0f, 1.0f, 1.0f)
+TransformKeyFrame::TransformKeyFrame() :
+ timePos(0.0f),
+ scale(1.0f, 1.0f, 1.0f)
{
}
aiMatrix4x4 TransformKeyFrame::Transform()
{
- return aiMatrix4x4(scale, rotation, position);
+ return aiMatrix4x4(scale, rotation, position);
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreStructs.h b/src/3rdparty/assimp/code/OgreStructs.h
index 75cadf4b7..c4e86a805 100644
--- a/src/3rdparty/assimp/code/OgreStructs.h
+++ b/src/3rdparty/assimp/code/OgreStructs.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,12 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
-#include "AssimpPCH.h"
#include "MemoryIOWrapper.h"
+#include <memory>
+#include <assimp/mesh.h>
+#include <map>
+#include <vector>
+#include <set>
+
+struct aiNodeAnim;
+struct aiAnimation;
+struct aiNode;
+struct aiMaterial;
+struct aiScene;
/** @note Parts of this implementation, for example enums, deserialization constants and logic
- has been copied directly with minor modifications from the MIT licensed Ogre3D code base.
- See more from https://bitbucket.org/sinbad/ogre. */
+ has been copied directly with minor modifications from the MIT licensed Ogre3D code base.
+ See more from https://bitbucket.org/sinbad/ogre. */
namespace Assimp
{
@@ -66,106 +76,106 @@ class Skeleton;
// Typedefs
typedef Assimp::MemoryIOStream MemoryStream;
-typedef boost::shared_ptr<MemoryStream> MemoryStreamPtr;
+typedef std::shared_ptr<MemoryStream> MemoryStreamPtr;
typedef std::map<uint16_t, MemoryStreamPtr> VertexBufferBindings;
// Ogre Vertex Element
class VertexElement
{
public:
- /// Vertex element semantics, used to identify the meaning of vertex buffer contents
- enum Semantic {
- /// Position, 3 reals per vertex
- VES_POSITION = 1,
- /// Blending weights
- VES_BLEND_WEIGHTS = 2,
- /// Blending indices
- VES_BLEND_INDICES = 3,
- /// Normal, 3 reals per vertex
- VES_NORMAL = 4,
- /// Diffuse colours
- VES_DIFFUSE = 5,
- /// Specular colours
- VES_SPECULAR = 6,
- /// Texture coordinates
- VES_TEXTURE_COORDINATES = 7,
- /// Binormal (Y axis if normal is Z)
- VES_BINORMAL = 8,
- /// Tangent (X axis if normal is Z)
- VES_TANGENT = 9,
- /// The number of VertexElementSemantic elements (note - the first value VES_POSITION is 1)
- VES_COUNT = 9
- };
-
- /// Vertex element type, used to identify the base types of the vertex contents
- enum Type
- {
- VET_FLOAT1 = 0,
- VET_FLOAT2 = 1,
- VET_FLOAT3 = 2,
- VET_FLOAT4 = 3,
- /// alias to more specific colour type - use the current rendersystem's colour packing
- VET_COLOUR = 4,
- VET_SHORT1 = 5,
- VET_SHORT2 = 6,
- VET_SHORT3 = 7,
- VET_SHORT4 = 8,
- VET_UBYTE4 = 9,
- /// D3D style compact colour
- VET_COLOUR_ARGB = 10,
- /// GL style compact colour
- VET_COLOUR_ABGR = 11,
- VET_DOUBLE1 = 12,
- VET_DOUBLE2 = 13,
- VET_DOUBLE3 = 14,
- VET_DOUBLE4 = 15,
- VET_USHORT1 = 16,
- VET_USHORT2 = 17,
- VET_USHORT3 = 18,
- VET_USHORT4 = 19,
- VET_INT1 = 20,
- VET_INT2 = 21,
- VET_INT3 = 22,
- VET_INT4 = 23,
- VET_UINT1 = 24,
- VET_UINT2 = 25,
- VET_UINT3 = 26,
- VET_UINT4 = 27
- };
-
- VertexElement();
-
- /// Size of the vertex element in bytes.
- size_t Size() const;
-
- /// Count of components in this element, eg. VET_FLOAT3 return 3.
- size_t ComponentCount() const;
-
- /// Type as string.
- std::string TypeToString();
-
- /// Semantic as string.
- std::string SemanticToString();
-
- static size_t TypeSize(Type type);
- static size_t ComponentCount(Type type);
- static std::string TypeToString(Type type);
- static std::string SemanticToString(Semantic semantic);
-
- uint16_t index;
- uint16_t source;
- uint16_t offset;
- Type type;
- Semantic semantic;
+ /// Vertex element semantics, used to identify the meaning of vertex buffer contents
+ enum Semantic {
+ /// Position, 3 reals per vertex
+ VES_POSITION = 1,
+ /// Blending weights
+ VES_BLEND_WEIGHTS = 2,
+ /// Blending indices
+ VES_BLEND_INDICES = 3,
+ /// Normal, 3 reals per vertex
+ VES_NORMAL = 4,
+ /// Diffuse colours
+ VES_DIFFUSE = 5,
+ /// Specular colours
+ VES_SPECULAR = 6,
+ /// Texture coordinates
+ VES_TEXTURE_COORDINATES = 7,
+ /// Binormal (Y axis if normal is Z)
+ VES_BINORMAL = 8,
+ /// Tangent (X axis if normal is Z)
+ VES_TANGENT = 9,
+ /// The number of VertexElementSemantic elements (note - the first value VES_POSITION is 1)
+ VES_COUNT = 9
+ };
+
+ /// Vertex element type, used to identify the base types of the vertex contents
+ enum Type
+ {
+ VET_FLOAT1 = 0,
+ VET_FLOAT2 = 1,
+ VET_FLOAT3 = 2,
+ VET_FLOAT4 = 3,
+ /// alias to more specific colour type - use the current rendersystem's colour packing
+ VET_COLOUR = 4,
+ VET_SHORT1 = 5,
+ VET_SHORT2 = 6,
+ VET_SHORT3 = 7,
+ VET_SHORT4 = 8,
+ VET_UBYTE4 = 9,
+ /// D3D style compact colour
+ VET_COLOUR_ARGB = 10,
+ /// GL style compact colour
+ VET_COLOUR_ABGR = 11,
+ VET_DOUBLE1 = 12,
+ VET_DOUBLE2 = 13,
+ VET_DOUBLE3 = 14,
+ VET_DOUBLE4 = 15,
+ VET_USHORT1 = 16,
+ VET_USHORT2 = 17,
+ VET_USHORT3 = 18,
+ VET_USHORT4 = 19,
+ VET_INT1 = 20,
+ VET_INT2 = 21,
+ VET_INT3 = 22,
+ VET_INT4 = 23,
+ VET_UINT1 = 24,
+ VET_UINT2 = 25,
+ VET_UINT3 = 26,
+ VET_UINT4 = 27
+ };
+
+ VertexElement();
+
+ /// Size of the vertex element in bytes.
+ size_t Size() const;
+
+ /// Count of components in this element, eg. VET_FLOAT3 return 3.
+ size_t ComponentCount() const;
+
+ /// Type as string.
+ std::string TypeToString();
+
+ /// Semantic as string.
+ std::string SemanticToString();
+
+ static size_t TypeSize(Type type);
+ static size_t ComponentCount(Type type);
+ static std::string TypeToString(Type type);
+ static std::string SemanticToString(Semantic semantic);
+
+ uint16_t index;
+ uint16_t source;
+ uint16_t offset;
+ Type type;
+ Semantic semantic;
};
typedef std::vector<VertexElement> VertexElementList;
/// Ogre Vertex Bone Assignment
struct VertexBoneAssignment
{
- uint32_t vertexIndex;
- uint16_t boneIndex;
- float weight;
+ uint32_t vertexIndex;
+ uint16_t boneIndex;
+ float weight;
};
typedef std::vector<VertexBoneAssignment> VertexBoneAssignmentList;
typedef std::map<uint32_t, VertexBoneAssignmentList > VertexBoneAssignmentsMap;
@@ -175,195 +185,195 @@ typedef std::map<uint16_t, std::vector<aiVertexWeight> > AssimpVertexBoneWeightL
class IVertexData
{
public:
- IVertexData();
-
- /// Returns if bone assignments are available.
- bool HasBoneAssignments() const;
-
- /// Add vertex mapping from old to new index.
- void AddVertexMapping(uint32_t oldIndex, uint32_t newIndex);
-
- /// Returns re-mapped bone assignments.
- /** @note Uses mappings added via AddVertexMapping. */
- AssimpVertexBoneWeightList AssimpBoneWeights(size_t vertices);
-
- /// Returns a set of bone indexes that are referenced by bone assignments (weights).
- std::set<uint16_t> ReferencedBonesByWeights() const;
-
- /// Vertex count.
- uint32_t count;
-
- /// Bone assignments.
- VertexBoneAssignmentList boneAssignments;
-
+ IVertexData();
+
+ /// Returns if bone assignments are available.
+ bool HasBoneAssignments() const;
+
+ /// Add vertex mapping from old to new index.
+ void AddVertexMapping(uint32_t oldIndex, uint32_t newIndex);
+
+ /// Returns re-mapped bone assignments.
+ /** @note Uses mappings added via AddVertexMapping. */
+ AssimpVertexBoneWeightList AssimpBoneWeights(size_t vertices);
+
+ /// Returns a set of bone indexes that are referenced by bone assignments (weights).
+ std::set<uint16_t> ReferencedBonesByWeights() const;
+
+ /// Vertex count.
+ uint32_t count;
+
+ /// Bone assignments.
+ VertexBoneAssignmentList boneAssignments;
+
private:
- void BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const;
-
- std::map<uint32_t, std::vector<uint32_t> > vertexIndexMapping;
- VertexBoneAssignmentsMap boneAssignmentsMap;
+ void BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const;
+
+ std::map<uint32_t, std::vector<uint32_t> > vertexIndexMapping;
+ VertexBoneAssignmentsMap boneAssignmentsMap;
};
// Ogre Vertex Data
class VertexData : public IVertexData
{
public:
- VertexData();
- ~VertexData();
+ VertexData();
+ ~VertexData();
- /// Releases all memory that this data structure owns.
- void Reset();
+ /// Releases all memory that this data structure owns.
+ void Reset();
- /// Get vertex size for @c source.
- uint32_t VertexSize(uint16_t source) const;
+ /// Get vertex size for @c source.
+ uint32_t VertexSize(uint16_t source) const;
- /// Get vertex buffer for @c source.
- MemoryStream *VertexBuffer(uint16_t source);
+ /// Get vertex buffer for @c source.
+ MemoryStream *VertexBuffer(uint16_t source);
- /// Get vertex element for @c semantic for @c index.
- VertexElement *GetVertexElement(VertexElement::Semantic semantic, uint16_t index = 0);
+ /// Get vertex element for @c semantic for @c index.
+ VertexElement *GetVertexElement(VertexElement::Semantic semantic, uint16_t index = 0);
- /// Vertex elements.
- VertexElementList vertexElements;
+ /// Vertex elements.
+ VertexElementList vertexElements;
- /// Vertex buffers mapped to bind index.
- VertexBufferBindings vertexBindings;
+ /// Vertex buffers mapped to bind index.
+ VertexBufferBindings vertexBindings;
};
// Ogre Index Data
class IndexData
{
public:
- IndexData();
- ~IndexData();
+ IndexData();
+ ~IndexData();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
- /// Releases all memory that this data structure owns.
- void Reset();
+ /// Index size in bytes.
+ size_t IndexSize() const;
- /// Index size in bytes.
- size_t IndexSize() const;
+ /// Face size in bytes.
+ size_t FaceSize() const;
- /// Face size in bytes.
- size_t FaceSize() const;
+ /// Index count.
+ uint32_t count;
- /// Index count.
- uint32_t count;
-
- /// Face count.
- uint32_t faceCount;
+ /// Face count.
+ uint32_t faceCount;
- /// If has 32-bit indexes.
- bool is32bit;
+ /// If has 32-bit indexes.
+ bool is32bit;
- /// Index buffer.
- MemoryStreamPtr buffer;
+ /// Index buffer.
+ MemoryStreamPtr buffer;
};
/// Ogre Pose
class Pose
{
public:
- struct Vertex
- {
- uint32_t index;
- aiVector3D offset;
- aiVector3D normal;
- };
- typedef std::map<uint32_t, Vertex> PoseVertexMap;
-
- Pose() : target(0), hasNormals(false) {}
-
- /// Name.
- std::string name;
-
- /// Target.
- uint16_t target;
-
- /// Does vertices map have normals.
- bool hasNormals;
-
- /// Vertex offset and normals.
- PoseVertexMap vertices;
+ struct Vertex
+ {
+ uint32_t index;
+ aiVector3D offset;
+ aiVector3D normal;
+ };
+ typedef std::map<uint32_t, Vertex> PoseVertexMap;
+
+ Pose() : target(0), hasNormals(false) {}
+
+ /// Name.
+ std::string name;
+
+ /// Target.
+ uint16_t target;
+
+ /// Does vertices map have normals.
+ bool hasNormals;
+
+ /// Vertex offset and normals.
+ PoseVertexMap vertices;
};
typedef std::vector<Pose*> PoseList;
/// Ogre Pose Key Frame Ref
struct PoseRef
{
- uint16_t index;
- float influence;
+ uint16_t index;
+ float influence;
};
typedef std::vector<PoseRef> PoseRefList;
/// Ogre Pose Key Frame
struct PoseKeyFrame
{
- /// Time position in the animation.
- float timePos;
+ /// Time position in the animation.
+ float timePos;
- PoseRefList references;
+ PoseRefList references;
};
typedef std::vector<PoseKeyFrame> PoseKeyFrameList;
/// Ogre Morph Key Frame
struct MorphKeyFrame
{
- /// Time position in the animation.
- float timePos;
+ /// Time position in the animation.
+ float timePos;
- MemoryStreamPtr buffer;
+ MemoryStreamPtr buffer;
};
typedef std::vector<MorphKeyFrame> MorphKeyFrameList;
/// Ogre animation key frame
struct TransformKeyFrame
{
- TransformKeyFrame();
-
- aiMatrix4x4 Transform();
-
- float timePos;
-
- aiQuaternion rotation;
- aiVector3D position;
- aiVector3D scale;
+ TransformKeyFrame();
+
+ aiMatrix4x4 Transform();
+
+ float timePos;
+
+ aiQuaternion rotation;
+ aiVector3D position;
+ aiVector3D scale;
};
typedef std::vector<TransformKeyFrame> TransformKeyFrameList;
/// Ogre Animation Track
struct VertexAnimationTrack
{
- enum Type
- {
- /// No animation
- VAT_NONE = 0,
- /// Morph animation is made up of many interpolated snapshot keyframes
- VAT_MORPH = 1,
- /// Pose animation is made up of a single delta pose keyframe
- VAT_POSE = 2,
- /// Keyframe that has its on pos, rot and scale for a time position
- VAT_TRANSFORM = 3
- };
-
- VertexAnimationTrack();
-
- /// Convert to Assimp node animation.
- aiNodeAnim *ConvertToAssimpAnimationNode(Skeleton *skeleton);
-
- // Animation type.
- Type type;
-
- /// Vertex data target.
- /** 0 == shared geometry
- >0 == submesh index + 1 */
- uint16_t target;
-
- /// Only valid for VAT_TRANSFORM.
- std::string boneName;
-
- /// Only one of these will contain key frames, depending on the type enum.
- PoseKeyFrameList poseKeyFrames;
- MorphKeyFrameList morphKeyFrames;
- TransformKeyFrameList transformKeyFrames;
+ enum Type
+ {
+ /// No animation
+ VAT_NONE = 0,
+ /// Morph animation is made up of many interpolated snapshot keyframes
+ VAT_MORPH = 1,
+ /// Pose animation is made up of a single delta pose keyframe
+ VAT_POSE = 2,
+ /// Keyframe that has its on pos, rot and scale for a time position
+ VAT_TRANSFORM = 3
+ };
+
+ VertexAnimationTrack();
+
+ /// Convert to Assimp node animation.
+ aiNodeAnim *ConvertToAssimpAnimationNode(Skeleton *skeleton);
+
+ // Animation type.
+ Type type;
+
+ /// Vertex data target.
+ /** 0 == shared geometry
+ >0 == submesh index + 1 */
+ uint16_t target;
+
+ /// Only valid for VAT_TRANSFORM.
+ std::string boneName;
+
+ /// Only one of these will contain key frames, depending on the type enum.
+ PoseKeyFrameList poseKeyFrames;
+ MorphKeyFrameList morphKeyFrames;
+ TransformKeyFrameList transformKeyFrames;
};
typedef std::vector<VertexAnimationTrack> VertexAnimationTrackList;
@@ -371,38 +381,38 @@ typedef std::vector<VertexAnimationTrack> VertexAnimationTrackList;
class Animation
{
public:
- Animation(Skeleton *parent);
- Animation(Mesh *parent);
+ explicit Animation(Skeleton *parent);
+ explicit Animation(Mesh *parent);
- /// Returns the associated vertex data for a track in this animation.
- /** @note Only valid to call when parent Mesh is set. */
- VertexData *AssociatedVertexData(VertexAnimationTrack *track) const;
+ /// Returns the associated vertex data for a track in this animation.
+ /** @note Only valid to call when parent Mesh is set. */
+ VertexData *AssociatedVertexData(VertexAnimationTrack *track) const;
- /// Convert to Assimp animation.
- aiAnimation *ConvertToAssimpAnimation();
+ /// Convert to Assimp animation.
+ aiAnimation *ConvertToAssimpAnimation();
- /// Parent mesh.
- /** @note Set only when animation is read from a mesh. */
- Mesh *parentMesh;
+ /// Parent mesh.
+ /** @note Set only when animation is read from a mesh. */
+ Mesh *parentMesh;
- /// Parent skeleton.
- /** @note Set only when animation is read from a skeleton. */
- Skeleton *parentSkeleton;
+ /// Parent skeleton.
+ /** @note Set only when animation is read from a skeleton. */
+ Skeleton *parentSkeleton;
- /// Animation name.
- std::string name;
+ /// Animation name.
+ std::string name;
- /// Base animation name.
- std::string baseName;
+ /// Base animation name.
+ std::string baseName;
- /// Length in seconds.
- float length;
+ /// Length in seconds.
+ float length;
- /// Base animation key time.
- float baseTime;
+ /// Base animation key time.
+ float baseTime;
- /// Animation tracks.
- VertexAnimationTrackList tracks;
+ /// Animation tracks.
+ VertexAnimationTrackList tracks;
};
typedef std::vector<Animation*> AnimationList;
@@ -410,39 +420,39 @@ typedef std::vector<Animation*> AnimationList;
class Bone
{
public:
- Bone();
-
- /// Returns if this bone is parented.
- bool IsParented() const;
-
- /// Parent index as uint16_t. Internally int32_t as -1 means unparented.
- uint16_t ParentId() const;
-
- /// Add child bone.
- void AddChild(Bone *bone);
-
- /// Calculates the world matrix for bone and its children.
- void CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton);
-
- /// Convert to Assimp node (animation nodes).
- aiNode *ConvertToAssimpNode(Skeleton *parent, aiNode *parentNode = 0);
-
- /// Convert to Assimp bone (mesh bones).
- aiBone *ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights);
-
- uint16_t id;
- std::string name;
-
- Bone *parent;
- int32_t parentId;
- std::vector<uint16_t> children;
-
- aiVector3D position;
- aiQuaternion rotation;
- aiVector3D scale;
-
- aiMatrix4x4 worldMatrix;
- aiMatrix4x4 defaultPose;
+ Bone();
+
+ /// Returns if this bone is parented.
+ bool IsParented() const;
+
+ /// Parent index as uint16_t. Internally int32_t as -1 means unparented.
+ uint16_t ParentId() const;
+
+ /// Add child bone.
+ void AddChild(Bone *bone);
+
+ /// Calculates the world matrix for bone and its children.
+ void CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton);
+
+ /// Convert to Assimp node (animation nodes).
+ aiNode *ConvertToAssimpNode(Skeleton *parent, aiNode *parentNode = 0);
+
+ /// Convert to Assimp bone (mesh bones).
+ aiBone *ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights);
+
+ uint16_t id;
+ std::string name;
+
+ Bone *parent;
+ int32_t parentId;
+ std::vector<uint16_t> children;
+
+ aiVector3D position;
+ aiQuaternion rotation;
+ aiVector3D scale;
+
+ aiMatrix4x4 worldMatrix;
+ aiMatrix4x4 defaultPose;
};
typedef std::vector<Bone*> BoneList;
@@ -450,107 +460,107 @@ typedef std::vector<Bone*> BoneList;
class Skeleton
{
public:
- enum BlendMode
- {
- /// Animations are applied by calculating a weighted average of all animations
- ANIMBLEND_AVERAGE = 0,
- /// Animations are applied by calculating a weighted cumulative total
- ANIMBLEND_CUMULATIVE = 1
- };
-
- Skeleton();
- ~Skeleton();
-
- /// Releases all memory that this data structure owns.
- void Reset();
-
- /// Returns unparented root bones.
- BoneList RootBones() const;
-
- /// Returns number of unparented root bones.
- size_t NumRootBones() const;
-
- /// Get bone by name.
- Bone *BoneByName(const std::string &name) const;
-
- /// Get bone by id.
- Bone *BoneById(uint16_t id) const;
-
- BoneList bones;
- AnimationList animations;
-
- /// @todo Take blend mode into account, but where?
- BlendMode blendMode;
+ enum BlendMode
+ {
+ /// Animations are applied by calculating a weighted average of all animations
+ ANIMBLEND_AVERAGE = 0,
+ /// Animations are applied by calculating a weighted cumulative total
+ ANIMBLEND_CUMULATIVE = 1
+ };
+
+ Skeleton();
+ ~Skeleton();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ /// Returns unparented root bones.
+ BoneList RootBones() const;
+
+ /// Returns number of unparented root bones.
+ size_t NumRootBones() const;
+
+ /// Get bone by name.
+ Bone *BoneByName(const std::string &name) const;
+
+ /// Get bone by id.
+ Bone *BoneById(uint16_t id) const;
+
+ BoneList bones;
+ AnimationList animations;
+
+ /// @todo Take blend mode into account, but where?
+ BlendMode blendMode;
};
/// Ogre Sub Mesh interface, inherited by the binary and XML implementations.
class ISubMesh
{
public:
- /// @note Full list of Ogre types, not all of them are supported and exposed to Assimp.
- enum OperationType
- {
- /// A list of points, 1 vertex per point
- OT_POINT_LIST = 1,
- /// A list of lines, 2 vertices per line
- OT_LINE_LIST = 2,
- /// A strip of connected lines, 1 vertex per line plus 1 start vertex
- OT_LINE_STRIP = 3,
- /// A list of triangles, 3 vertices per triangle
- OT_TRIANGLE_LIST = 4,
- /// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that
- OT_TRIANGLE_STRIP = 5,
- /// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
- OT_TRIANGLE_FAN = 6
- };
-
- ISubMesh();
-
- /// SubMesh index.
- unsigned int index;
-
- /// SubMesh name.
- std::string name;
-
- /// Material used by this submesh.
- std::string materialRef;
-
- /// Texture alias information.
- std::string textureAliasName;
- std::string textureAliasRef;
-
- /// Assimp scene material index used by this submesh.
- /** -1 if no material or material could not be imported. */
- int materialIndex;
-
- /// If submesh uses shared geometry from parent mesh.
- bool usesSharedVertexData;
-
- /// Operation type.
- OperationType operationType;
+ /// @note Full list of Ogre types, not all of them are supported and exposed to Assimp.
+ enum OperationType
+ {
+ /// A list of points, 1 vertex per point
+ OT_POINT_LIST = 1,
+ /// A list of lines, 2 vertices per line
+ OT_LINE_LIST = 2,
+ /// A strip of connected lines, 1 vertex per line plus 1 start vertex
+ OT_LINE_STRIP = 3,
+ /// A list of triangles, 3 vertices per triangle
+ OT_TRIANGLE_LIST = 4,
+ /// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that
+ OT_TRIANGLE_STRIP = 5,
+ /// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
+ OT_TRIANGLE_FAN = 6
+ };
+
+ ISubMesh();
+
+ /// SubMesh index.
+ unsigned int index;
+
+ /// SubMesh name.
+ std::string name;
+
+ /// Material used by this submesh.
+ std::string materialRef;
+
+ /// Texture alias information.
+ std::string textureAliasName;
+ std::string textureAliasRef;
+
+ /// Assimp scene material index used by this submesh.
+ /** -1 if no material or material could not be imported. */
+ int materialIndex;
+
+ /// If submesh uses shared geometry from parent mesh.
+ bool usesSharedVertexData;
+
+ /// Operation type.
+ OperationType operationType;
};
/// Ogre SubMesh
class SubMesh : public ISubMesh
{
public:
- SubMesh();
- ~SubMesh();
-
- /// Releases all memory that this data structure owns.
- /** @note Vertex and index data contains shared ptrs
- that are freed automatically. In practice the ref count
- should be 0 after this reset. */
- void Reset();
-
- /// Covert to Assimp mesh.
- aiMesh *ConvertToAssimpMesh(Mesh *parent);
-
- /// Vertex data.
- VertexData *vertexData;
-
- /// Index data.
- IndexData *indexData;
+ SubMesh();
+ ~SubMesh();
+
+ /// Releases all memory that this data structure owns.
+ /** @note Vertex and index data contains shared ptrs
+ that are freed automatically. In practice the ref count
+ should be 0 after this reset. */
+ void Reset();
+
+ /// Covert to Assimp mesh.
+ aiMesh *ConvertToAssimpMesh(Mesh *parent);
+
+ /// Vertex data.
+ VertexData *vertexData;
+
+ /// Index data.
+ IndexData *indexData;
};
typedef std::vector<SubMesh*> SubMeshList;
@@ -558,87 +568,90 @@ typedef std::vector<SubMesh*> SubMeshList;
class Mesh
{
public:
- Mesh();
- ~Mesh();
+ /// Constructor.
+ Mesh();
- /// Releases all memory that this data structure owns.
- void Reset();
+ /// Destructor.
+ ~Mesh();
- /// Returns number of subMeshes.
- size_t NumSubMeshes() const;
+ /// Releases all memory that this data structure owns.
+ void Reset();
- /// Returns submesh for @c index.
- SubMesh *GetSubMesh(uint16_t index) const;
+ /// Returns number of subMeshes.
+ size_t NumSubMeshes() const;
- /// Convert mesh to Assimp scene.
- void ConvertToAssimpScene(aiScene* dest);
+ /// Returns submesh for @c index.
+ SubMesh *GetSubMesh( size_t index) const;
- /// Mesh has skeletal animations.
- bool hasSkeletalAnimations;
-
- /// Skeleton reference.
- std::string skeletonRef;
+ /// Convert mesh to Assimp scene.
+ void ConvertToAssimpScene(aiScene* dest);
- /// Skeleton.
- Skeleton *skeleton;
+ /// Mesh has skeletal animations.
+ bool hasSkeletalAnimations;
- /// Vertex data
- VertexData *sharedVertexData;
+ /// Skeleton reference.
+ std::string skeletonRef;
- /// Sub meshes.
- SubMeshList subMeshes;
+ /// Skeleton.
+ Skeleton *skeleton;
- /// Animations
- AnimationList animations;
+ /// Vertex data
+ VertexData *sharedVertexData;
- /// Poses
- PoseList poses;
+ /// Sub meshes.
+ SubMeshList subMeshes;
+
+ /// Animations
+ AnimationList animations;
+
+ /// Poses
+ PoseList poses;
};
/// Ogre XML Vertex Data
class VertexDataXml : public IVertexData
{
public:
- VertexDataXml();
-
- bool HasPositions() const;
- bool HasNormals() const;
- bool HasTangents() const;
- bool HasUvs() const;
- size_t NumUvs() const;
-
- std::vector<aiVector3D> positions;
- std::vector<aiVector3D> normals;
- std::vector<aiVector3D> tangents;
- std::vector<std::vector<aiVector3D> > uvs;
+ VertexDataXml();
+
+ bool HasPositions() const;
+ bool HasNormals() const;
+ bool HasTangents() const;
+ bool HasUvs() const;
+ size_t NumUvs() const;
+
+ std::vector<aiVector3D> positions;
+ std::vector<aiVector3D> normals;
+ std::vector<aiVector3D> tangents;
+ std::vector<std::vector<aiVector3D> > uvs;
};
/// Ogre XML Index Data
class IndexDataXml
{
public:
- IndexDataXml() : faceCount(0) {}
+ IndexDataXml() : faceCount(0) {}
- /// Face count.
- uint32_t faceCount;
+ /// Face count.
+ uint32_t faceCount;
- std::vector<aiFace> faces;
+ std::vector<aiFace> faces;
};
/// Ogre XML SubMesh
class SubMeshXml : public ISubMesh
{
public:
- SubMeshXml();
- ~SubMeshXml();
-
- /// Releases all memory that this data structure owns.
- void Reset();
-
- aiMesh *ConvertToAssimpMesh(MeshXml *parent);
-
- IndexDataXml *indexData;
- VertexDataXml *vertexData;
+ SubMeshXml();
+ ~SubMeshXml();
+
+ /// Releases all memory that this data structure owns.
+ void Reset();
+
+ aiMesh *ConvertToAssimpMesh(MeshXml *parent);
+
+ IndexDataXml *indexData;
+ VertexDataXml *vertexData;
};
typedef std::vector<SubMeshXml*> SubMeshXmlList;
@@ -646,32 +659,32 @@ typedef std::vector<SubMeshXml*> SubMeshXmlList;
class MeshXml
{
public:
- MeshXml();
- ~MeshXml();
+ MeshXml();
+ ~MeshXml();
- /// Releases all memory that this data structure owns.
- void Reset();
+ /// Releases all memory that this data structure owns.
+ void Reset();
- /// Returns number of subMeshes.
- size_t NumSubMeshes() const;
+ /// Returns number of subMeshes.
+ size_t NumSubMeshes() const;
- /// Returns submesh for @c index.
- SubMeshXml *GetSubMesh(uint16_t index) const;
+ /// Returns submesh for @c index.
+ SubMeshXml *GetSubMesh(uint16_t index) const;
- /// Convert mesh to Assimp scene.
- void ConvertToAssimpScene(aiScene* dest);
+ /// Convert mesh to Assimp scene.
+ void ConvertToAssimpScene(aiScene* dest);
- /// Skeleton reference.
- std::string skeletonRef;
+ /// Skeleton reference.
+ std::string skeletonRef;
- /// Skeleton.
- Skeleton *skeleton;
+ /// Skeleton.
+ Skeleton *skeleton;
- /// Vertex data
- VertexDataXml *sharedVertexData;
+ /// Vertex data
+ VertexDataXml *sharedVertexData;
- /// Sub meshes.
- SubMeshXmlList subMeshes;
+ /// Sub meshes.
+ SubMeshXmlList subMeshes;
};
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.cpp b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
index 733e36c03..494d8e00c 100644
--- a/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OgreParsingUtils.h"
#include "TinyFormatter.h"
+#include <assimp/DefaultLogger.hpp>
+#include <memory>
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
@@ -54,173 +56,174 @@ namespace Assimp
namespace Ogre
{
-void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
+AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error)
{
- if (!error.empty())
- {
- throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
- }
- else
- {
- throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
- }
+ if (!error.empty())
+ {
+ throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'");
+ }
+ else
+ {
+ throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'");
+ }
}
-template<>
+template<>
int32_t OgreXmlSerializer::ReadAttribute<int32_t>(const std::string &name) const
{
- if (HasAttribute(name.c_str()))
- {
- return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name.c_str()));
- }
- else
- {
- ThrowAttibuteError(m_reader, name);
- return 0;
- }
+ if (HasAttribute(name.c_str()))
+ {
+ return static_cast<int32_t>(m_reader->getAttributeValueAsInt(name.c_str()));
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return 0;
+ }
}
-template<>
+template<>
uint32_t OgreXmlSerializer::ReadAttribute<uint32_t>(const std::string &name) const
{
- if (HasAttribute(name.c_str()))
- {
- /** @note This is hackish. But we are never expecting unsigned values that go outside the
- int32_t range. Just monitor for negative numbers and kill the import. */
- int32_t temp = ReadAttribute<int32_t>(name);
- if (temp >= 0)
- {
- return static_cast<uint32_t>(temp);
- }
- else
- {
- ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
- }
- }
- else
- {
- ThrowAttibuteError(m_reader, name);
- }
- return 0;
+ if (HasAttribute(name.c_str()))
+ {
+ /** @note This is hackish. But we are never expecting unsigned values that go outside the
+ int32_t range. Just monitor for negative numbers and kill the import. */
+ int32_t temp = ReadAttribute<int32_t>(name);
+ if (temp >= 0)
+ {
+ return static_cast<uint32_t>(temp);
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value");
+ }
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ }
+ return 0;
}
-template<>
+template<>
uint16_t OgreXmlSerializer::ReadAttribute<uint16_t>(const std::string &name) const
{
- if (HasAttribute(name.c_str()))
- {
- return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
- }
- else
- {
- ThrowAttibuteError(m_reader, name);
- }
- return 0;
+ if (HasAttribute(name.c_str()))
+ {
+ return static_cast<uint16_t>(ReadAttribute<uint32_t>(name));
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ }
+ return 0;
}
-template<>
+template<>
float OgreXmlSerializer::ReadAttribute<float>(const std::string &name) const
{
- if (HasAttribute(name.c_str()))
- {
- return m_reader->getAttributeValueAsFloat(name.c_str());
- }
- else
- {
- ThrowAttibuteError(m_reader, name);
- return 0;
- }
+ if (HasAttribute(name.c_str()))
+ {
+ return m_reader->getAttributeValueAsFloat(name.c_str());
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return 0;
+ }
}
-template<>
+template<>
std::string OgreXmlSerializer::ReadAttribute<std::string>(const std::string &name) const
{
- const char* value = m_reader->getAttributeValue(name.c_str());
- if (value)
- {
- return std::string(value);
- }
- else
- {
- ThrowAttibuteError(m_reader, name);
- return "";
- }
+ const char* value = m_reader->getAttributeValue(name.c_str());
+ if (value)
+ {
+ return std::string(value);
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name);
+ return "";
+ }
}
-template<>
+template<>
bool OgreXmlSerializer::ReadAttribute<bool>(const std::string &name) const
{
- std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
- if (ASSIMP_stricmp(value, "true") == 0)
- {
- return true;
- }
- else if (ASSIMP_stricmp(value, "false") == 0)
- {
- return false;
- }
- else
- {
- ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
- return false;
- }
+ std::string value = Ogre::ToLower(ReadAttribute<std::string>(name));
+ if (ASSIMP_stricmp(value, "true") == 0)
+ {
+ return true;
+ }
+ else if (ASSIMP_stricmp(value, "false") == 0)
+ {
+ return false;
+ }
+ else
+ {
+ ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
+ return false;
+ }
}
bool OgreXmlSerializer::HasAttribute(const std::string &name) const
{
- return (m_reader->getAttributeValue(name.c_str()) != 0);
+ return (m_reader->getAttributeValue(name.c_str()) != 0);
}
std::string &OgreXmlSerializer::NextNode()
{
- do
- {
- if (!m_reader->read())
- {
- m_currentNodeName = "";
- return m_currentNodeName;
- }
- }
- while(m_reader->getNodeType() != irr::io::EXN_ELEMENT);
-
- CurrentNodeName(true);
+ do
+ {
+ if (!m_reader->read())
+ {
+ m_currentNodeName = "";
+ return m_currentNodeName;
+ }
+ }
+ while(m_reader->getNodeType() != irr::io::EXN_ELEMENT);
+
+ CurrentNodeName(true);
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
- DefaultLogger::get()->debug("<" + m_currentNodeName + ">");
+ DefaultLogger::get()->debug("<" + m_currentNodeName + ">");
#endif
- return m_currentNodeName;
+ return m_currentNodeName;
}
bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const
{
- return (ASSIMP_stricmp(m_currentNodeName, name) == 0);
+ return (ASSIMP_stricmp(m_currentNodeName, name) == 0);
}
std::string OgreXmlSerializer::CurrentNodeName(bool forceRead)
{
- if (forceRead)
- m_currentNodeName = std::string(m_reader->getNodeName());
- return m_currentNodeName;
+ if (forceRead)
+ m_currentNodeName = std::string(m_reader->getNodeName());
+ return m_currentNodeName;
}
std::string &OgreXmlSerializer::SkipCurrentNode()
{
#if (OGRE_XML_SERIALIZER_DEBUG == 1)
- DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
+ DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">");
#endif
- for(;;)
- {
- if (!m_reader->read())
- {
- m_currentNodeName = "";
- return m_currentNodeName;
- }
- if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END)
- continue;
- else if (std::string(m_reader->getNodeName()) == m_currentNodeName)
- break;
- }
- return NextNode();
+ for(;;)
+ {
+ if (!m_reader->read())
+ {
+ m_currentNodeName = "";
+ return m_currentNodeName;
+ }
+ if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END)
+ continue;
+ else if (std::string(m_reader->getNodeName()) == m_currentNodeName)
+ break;
+ }
+ return NextNode();
}
// Mesh XML constants
@@ -300,701 +303,699 @@ const std::string anZ = "z";
MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader)
{
- OgreXmlSerializer serializer(reader);
+ OgreXmlSerializer serializer(reader);
- MeshXml *mesh = new MeshXml();
- serializer.ReadMesh(mesh);
- return mesh;
+ MeshXml *mesh = new MeshXml();
+ serializer.ReadMesh(mesh);
+ return mesh;
}
void OgreXmlSerializer::ReadMesh(MeshXml *mesh)
{
- if (NextNode() != nnMesh) {
- throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
- }
-
- DefaultLogger::get()->debug("Reading Mesh");
-
- NextNode();
-
- // Root level nodes
- while(m_currentNodeName == nnSharedGeometry ||
- m_currentNodeName == nnSubMeshes ||
- m_currentNodeName == nnSkeletonLink ||
- m_currentNodeName == nnBoneAssignments ||
- m_currentNodeName == nnLOD ||
- m_currentNodeName == nnSubMeshNames ||
- m_currentNodeName == nnExtremes ||
- m_currentNodeName == nnPoses ||
- m_currentNodeName == nnAnimations)
- {
- if (m_currentNodeName == nnSharedGeometry)
- {
- mesh->sharedVertexData = new VertexDataXml();
- ReadGeometry(mesh->sharedVertexData);
- }
- else if (m_currentNodeName == nnSubMeshes)
- {
- NextNode();
- while(m_currentNodeName == nnSubMesh) {
- ReadSubMesh(mesh);
- }
- }
- else if (m_currentNodeName == nnBoneAssignments)
- {
- ReadBoneAssignments(mesh->sharedVertexData);
- }
- else if (m_currentNodeName == nnSkeletonLink)
- {
- mesh->skeletonRef = ReadAttribute<std::string>("name");
- DefaultLogger::get()->debug("Read skeleton link " + mesh->skeletonRef);
- NextNode();
- }
- // Assimp incompatible/ignored nodes
- else
- SkipCurrentNode();
- }
+ if (NextNode() != nnMesh) {
+ throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <mesh>");
+ }
+
+ DefaultLogger::get()->debug("Reading Mesh");
+
+ NextNode();
+
+ // Root level nodes
+ while(m_currentNodeName == nnSharedGeometry ||
+ m_currentNodeName == nnSubMeshes ||
+ m_currentNodeName == nnSkeletonLink ||
+ m_currentNodeName == nnBoneAssignments ||
+ m_currentNodeName == nnLOD ||
+ m_currentNodeName == nnSubMeshNames ||
+ m_currentNodeName == nnExtremes ||
+ m_currentNodeName == nnPoses ||
+ m_currentNodeName == nnAnimations)
+ {
+ if (m_currentNodeName == nnSharedGeometry)
+ {
+ mesh->sharedVertexData = new VertexDataXml();
+ ReadGeometry(mesh->sharedVertexData);
+ }
+ else if (m_currentNodeName == nnSubMeshes)
+ {
+ NextNode();
+ while(m_currentNodeName == nnSubMesh) {
+ ReadSubMesh(mesh);
+ }
+ }
+ else if (m_currentNodeName == nnBoneAssignments)
+ {
+ ReadBoneAssignments(mesh->sharedVertexData);
+ }
+ else if (m_currentNodeName == nnSkeletonLink)
+ {
+ mesh->skeletonRef = ReadAttribute<std::string>("name");
+ DefaultLogger::get()->debug("Read skeleton link " + mesh->skeletonRef);
+ NextNode();
+ }
+ // Assimp incompatible/ignored nodes
+ else
+ SkipCurrentNode();
+ }
}
void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest)
{
- dest->count = ReadAttribute<uint32_t>("vertexcount");
- DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
+ dest->count = ReadAttribute<uint32_t>("vertexcount");
+ DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
- NextNode();
- while(m_currentNodeName == nnVertexBuffer) {
- ReadGeometryVertexBuffer(dest);
- }
+ NextNode();
+ while(m_currentNodeName == nnVertexBuffer) {
+ ReadGeometryVertexBuffer(dest);
+ }
}
void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest)
{
- bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
- bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
- bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
- uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
-
- // Not having positions is a error only if a previous vertex buffer did not have them.
- if (!positions && !dest->HasPositions()) {
- throw DeadlyImportError("Vertex buffer does not contain positions!");
- }
-
- if (positions)
- {
- DefaultLogger::get()->debug(" - Contains positions");
- dest->positions.reserve(dest->count);
- }
- if (normals)
- {
- DefaultLogger::get()->debug(" - Contains normals");
- dest->normals.reserve(dest->count);
- }
- if (tangents)
- {
- DefaultLogger::get()->debug(" - Contains tangents");
- dest->tangents.reserve(dest->count);
- }
- if (uvs > 0)
- {
- DefaultLogger::get()->debug(Formatter::format() << " - Contains " << uvs << " texture coords");
- dest->uvs.resize(uvs);
- for(size_t i=0, len=dest->uvs.size(); i<len; ++i) {
- dest->uvs[i].reserve(dest->count);
- }
- }
-
- bool warnBinormal = true;
- bool warnColorDiffuse = true;
- bool warnColorSpecular = true;
-
- NextNode();
-
- while(m_currentNodeName == nnVertex ||
- m_currentNodeName == nnPosition ||
- m_currentNodeName == nnNormal ||
- m_currentNodeName == nnTangent ||
- m_currentNodeName == nnBinormal ||
- m_currentNodeName == nnTexCoord ||
- m_currentNodeName == nnColorDiffuse ||
- m_currentNodeName == nnColorSpecular)
- {
- if (m_currentNodeName == nnVertex) {
- NextNode();
- }
-
- /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
-
- if (positions && m_currentNodeName == nnPosition)
- {
- aiVector3D pos;
- pos.x = ReadAttribute<float>(anX);
- pos.y = ReadAttribute<float>(anY);
- pos.z = ReadAttribute<float>(anZ);
- dest->positions.push_back(pos);
- }
- else if (normals && m_currentNodeName == nnNormal)
- {
- aiVector3D normal;
- normal.x = ReadAttribute<float>(anX);
- normal.y = ReadAttribute<float>(anY);
- normal.z = ReadAttribute<float>(anZ);
- dest->normals.push_back(normal);
- }
- else if (tangents && m_currentNodeName == nnTangent)
- {
- aiVector3D tangent;
- tangent.x = ReadAttribute<float>(anX);
- tangent.y = ReadAttribute<float>(anY);
- tangent.z = ReadAttribute<float>(anZ);
- dest->tangents.push_back(tangent);
- }
- else if (uvs > 0 && m_currentNodeName == nnTexCoord)
- {
- for(size_t i=0, len=dest->uvs.size(); i<len; ++i)
- {
- if (m_currentNodeName != nnTexCoord) {
- throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
- }
-
- aiVector3D uv;
- uv.x = ReadAttribute<float>("u");
- uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
- dest->uvs[i].push_back(uv);
-
- NextNode();
- }
- // Continue main loop as above already read next node
- continue;
- }
- else
- {
- /// @todo Remove this stuff once implemented. We only want to log warnings once per element.
- bool warn = true;
- if (m_currentNodeName == nnBinormal)
- {
- if (warnBinormal)
- {
- warnBinormal = false;
- }
- else
- {
- warn = false;
- }
- }
- else if (m_currentNodeName == nnColorDiffuse)
- {
- if (warnColorDiffuse)
- {
- warnColorDiffuse = false;
- }
- else
- {
- warn = false;
- }
- }
- else if (m_currentNodeName == nnColorSpecular)
- {
- if (warnColorSpecular)
- {
- warnColorSpecular = false;
- }
- else
- {
- warn = false;
- }
- }
- if (warn) {
- DefaultLogger::get()->warn("Vertex buffer attribute read not implemented for element: " + m_currentNodeName);
- }
- }
-
- // Advance
- NextNode();
- }
-
- // Sanity checks
- if (dest->positions.size() != dest->count) {
- throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
- }
- if (normals && dest->normals.size() != dest->count) {
- throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count);
- }
- if (tangents && dest->tangents.size() != dest->count) {
- throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count);
- }
- for(unsigned int i=0; i<dest->uvs.size(); ++i)
- {
- if (dest->uvs[i].size() != dest->count) {
- throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size()
- << " uvs for uv index " << i << " when should have read " << dest->count);
- }
- }
+ bool positions = (HasAttribute("positions") && ReadAttribute<bool>("positions"));
+ bool normals = (HasAttribute("normals") && ReadAttribute<bool>("normals"));
+ bool tangents = (HasAttribute("tangents") && ReadAttribute<bool>("tangents"));
+ uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute<uint32_t>("texture_coords") : 0);
+
+ // Not having positions is a error only if a previous vertex buffer did not have them.
+ if (!positions && !dest->HasPositions()) {
+ throw DeadlyImportError("Vertex buffer does not contain positions!");
+ }
+
+ if (positions)
+ {
+ DefaultLogger::get()->debug(" - Contains positions");
+ dest->positions.reserve(dest->count);
+ }
+ if (normals)
+ {
+ DefaultLogger::get()->debug(" - Contains normals");
+ dest->normals.reserve(dest->count);
+ }
+ if (tangents)
+ {
+ DefaultLogger::get()->debug(" - Contains tangents");
+ dest->tangents.reserve(dest->count);
+ }
+ if (uvs > 0)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << " - Contains " << uvs << " texture coords");
+ dest->uvs.resize(uvs);
+ for(size_t i=0, len=dest->uvs.size(); i<len; ++i) {
+ dest->uvs[i].reserve(dest->count);
+ }
+ }
+
+ bool warnBinormal = true;
+ bool warnColorDiffuse = true;
+ bool warnColorSpecular = true;
+
+ NextNode();
+
+ while(m_currentNodeName == nnVertex ||
+ m_currentNodeName == nnPosition ||
+ m_currentNodeName == nnNormal ||
+ m_currentNodeName == nnTangent ||
+ m_currentNodeName == nnBinormal ||
+ m_currentNodeName == nnTexCoord ||
+ m_currentNodeName == nnColorDiffuse ||
+ m_currentNodeName == nnColorSpecular)
+ {
+ if (m_currentNodeName == nnVertex) {
+ NextNode();
+ }
+
+ /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
+
+ if (positions && m_currentNodeName == nnPosition)
+ {
+ aiVector3D pos;
+ pos.x = ReadAttribute<float>(anX);
+ pos.y = ReadAttribute<float>(anY);
+ pos.z = ReadAttribute<float>(anZ);
+ dest->positions.push_back(pos);
+ }
+ else if (normals && m_currentNodeName == nnNormal)
+ {
+ aiVector3D normal;
+ normal.x = ReadAttribute<float>(anX);
+ normal.y = ReadAttribute<float>(anY);
+ normal.z = ReadAttribute<float>(anZ);
+ dest->normals.push_back(normal);
+ }
+ else if (tangents && m_currentNodeName == nnTangent)
+ {
+ aiVector3D tangent;
+ tangent.x = ReadAttribute<float>(anX);
+ tangent.y = ReadAttribute<float>(anY);
+ tangent.z = ReadAttribute<float>(anZ);
+ dest->tangents.push_back(tangent);
+ }
+ else if (uvs > 0 && m_currentNodeName == nnTexCoord)
+ {
+ for(auto &uvs : dest->uvs)
+ {
+ if (m_currentNodeName != nnTexCoord) {
+ throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
+ }
+
+ aiVector3D uv;
+ uv.x = ReadAttribute<float>("u");
+ uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
+ uvs.push_back(uv);
+
+ NextNode();
+ }
+ // Continue main loop as above already read next node
+ continue;
+ }
+ else
+ {
+ /// @todo Remove this stuff once implemented. We only want to log warnings once per element.
+ bool warn = true;
+ if (m_currentNodeName == nnBinormal)
+ {
+ if (warnBinormal)
+ {
+ warnBinormal = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ else if (m_currentNodeName == nnColorDiffuse)
+ {
+ if (warnColorDiffuse)
+ {
+ warnColorDiffuse = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ else if (m_currentNodeName == nnColorSpecular)
+ {
+ if (warnColorSpecular)
+ {
+ warnColorSpecular = false;
+ }
+ else
+ {
+ warn = false;
+ }
+ }
+ if (warn) {
+ DefaultLogger::get()->warn("Vertex buffer attribute read not implemented for element: " + m_currentNodeName);
+ }
+ }
+
+ // Advance
+ NextNode();
+ }
+
+ // Sanity checks
+ if (dest->positions.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
+ }
+ if (normals && dest->normals.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count);
+ }
+ if (tangents && dest->tangents.size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count);
+ }
+ for(unsigned int i=0; i<dest->uvs.size(); ++i)
+ {
+ if (dest->uvs[i].size() != dest->count) {
+ throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size()
+ << " uvs for uv index " << i << " when should have read " << dest->count);
+ }
+ }
}
void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh)
{
- static const std::string anMaterial = "material";
- static const std::string anUseSharedVertices = "usesharedvertices";
- static const std::string anCount = "count";
- static const std::string anV1 = "v1";
- static const std::string anV2 = "v2";
- static const std::string anV3 = "v3";
- static const std::string anV4 = "v4";
-
- SubMeshXml* submesh = new SubMeshXml();
-
- if (HasAttribute(anMaterial)) {
- submesh->materialRef = ReadAttribute<std::string>(anMaterial);
- }
- if (HasAttribute(anUseSharedVertices)) {
- submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
- }
-
- DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
- DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
- DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
-
- // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
- // of faces and geometry changed, and not if we have more than one of one
- /// @todo Fix above comment with better read logic below
-
- bool quadWarned = false;
-
- NextNode();
- while(m_currentNodeName == nnFaces ||
- m_currentNodeName == nnGeometry ||
- m_currentNodeName == nnTextures ||
- m_currentNodeName == nnBoneAssignments)
- {
- if (m_currentNodeName == nnFaces)
- {
- submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
- submesh->indexData->faces.reserve(submesh->indexData->faceCount);
-
- NextNode();
- while(m_currentNodeName == nnFace)
- {
- aiFace face;
- face.mNumIndices = 3;
- face.mIndices = new unsigned int[3];
- face.mIndices[0] = ReadAttribute<uint32_t>(anV1);
- face.mIndices[1] = ReadAttribute<uint32_t>(anV2);
- face.mIndices[2] = ReadAttribute<uint32_t>(anV3);
-
- /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
- if (!quadWarned && HasAttribute(anV4)) {
- DefaultLogger::get()->warn("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
- quadWarned = true;
- }
-
- submesh->indexData->faces.push_back(face);
-
- // Advance
- NextNode();
- }
-
- if (submesh->indexData->faces.size() == submesh->indexData->faceCount)
- {
- DefaultLogger::get()->debug(Formatter::format() << " - Faces " << submesh->indexData->faceCount);
- }
- else
- {
- throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
- }
- }
- else if (m_currentNodeName == nnGeometry)
- {
- if (submesh->usesSharedVertexData) {
- throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
- }
-
- submesh->vertexData = new VertexDataXml();
- ReadGeometry(submesh->vertexData);
- }
- else if (m_currentNodeName == nnBoneAssignments)
- {
- ReadBoneAssignments(submesh->vertexData);
- }
- // Assimp incompatible/ignored nodes
- else
- SkipCurrentNode();
- }
-
- submesh->index = mesh->subMeshes.size();
- mesh->subMeshes.push_back(submesh);
+ static const std::string anMaterial = "material";
+ static const std::string anUseSharedVertices = "usesharedvertices";
+ static const std::string anCount = "count";
+ static const std::string anV1 = "v1";
+ static const std::string anV2 = "v2";
+ static const std::string anV3 = "v3";
+ static const std::string anV4 = "v4";
+
+ SubMeshXml* submesh = new SubMeshXml();
+
+ if (HasAttribute(anMaterial)) {
+ submesh->materialRef = ReadAttribute<std::string>(anMaterial);
+ }
+ if (HasAttribute(anUseSharedVertices)) {
+ submesh->usesSharedVertexData = ReadAttribute<bool>(anUseSharedVertices);
+ }
+
+ DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
+ DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
+ DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
+
+ // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order
+ // of faces and geometry changed, and not if we have more than one of one
+ /// @todo Fix above comment with better read logic below
+
+ bool quadWarned = false;
+
+ NextNode();
+ while(m_currentNodeName == nnFaces ||
+ m_currentNodeName == nnGeometry ||
+ m_currentNodeName == nnTextures ||
+ m_currentNodeName == nnBoneAssignments)
+ {
+ if (m_currentNodeName == nnFaces)
+ {
+ submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
+ submesh->indexData->faces.reserve(submesh->indexData->faceCount);
+
+ NextNode();
+ while(m_currentNodeName == nnFace)
+ {
+ aiFace face;
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+ face.mIndices[0] = ReadAttribute<uint32_t>(anV1);
+ face.mIndices[1] = ReadAttribute<uint32_t>(anV2);
+ face.mIndices[2] = ReadAttribute<uint32_t>(anV3);
+
+ /// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
+ if (!quadWarned && HasAttribute(anV4)) {
+ DefaultLogger::get()->warn("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
+ quadWarned = true;
+ }
+
+ submesh->indexData->faces.push_back(face);
+
+ // Advance
+ NextNode();
+ }
+
+ if (submesh->indexData->faces.size() == submesh->indexData->faceCount)
+ {
+ DefaultLogger::get()->debug(Formatter::format() << " - Faces " << submesh->indexData->faceCount);
+ }
+ else
+ {
+ throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
+ }
+ }
+ else if (m_currentNodeName == nnGeometry)
+ {
+ if (submesh->usesSharedVertexData) {
+ throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
+ }
+
+ submesh->vertexData = new VertexDataXml();
+ ReadGeometry(submesh->vertexData);
+ }
+ else if (m_currentNodeName == nnBoneAssignments)
+ {
+ ReadBoneAssignments(submesh->vertexData);
+ }
+ // Assimp incompatible/ignored nodes
+ else
+ SkipCurrentNode();
+ }
+
+ submesh->index = mesh->subMeshes.size();
+ mesh->subMeshes.push_back(submesh);
}
void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest)
{
- if (!dest) {
- throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
- }
-
- static const std::string anVertexIndex = "vertexindex";
- static const std::string anBoneIndex = "boneindex";
- static const std::string anWeight = "weight";
-
- std::set<uint32_t> influencedVertices;
-
- NextNode();
- while(m_currentNodeName == nnVertexBoneAssignment)
- {
- VertexBoneAssignment ba;
- ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
- ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
- ba.weight = ReadAttribute<float>(anWeight);
-
- dest->boneAssignments.push_back(ba);
- influencedVertices.insert(ba.vertexIndex);
-
- NextNode();
- }
-
- /** Normalize bone weights.
- Some exporters wont care if the sum of all bone weights
- for a single vertex equals 1 or not, so validate here. */
- const float epsilon = 0.05f;
- for(std::set<uint32_t>::const_iterator iter=influencedVertices.begin(), end=influencedVertices.end(); iter != end; ++iter)
- {
- const uint32_t vertexIndex = (*iter);
-
- float sum = 0.0f;
- for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
- {
- if (baIter->vertexIndex == vertexIndex)
- sum += baIter->weight;
- }
- if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
- {
- for (VertexBoneAssignmentList::iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
- {
- if (baIter->vertexIndex == vertexIndex)
- baIter->weight /= sum;
- }
- }
- }
-
- DefaultLogger::get()->debug(Formatter::format() << " - " << dest->boneAssignments.size() << " bone assignments");
+ if (!dest) {
+ throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
+ }
+
+ static const std::string anVertexIndex = "vertexindex";
+ static const std::string anBoneIndex = "boneindex";
+ static const std::string anWeight = "weight";
+
+ std::set<uint32_t> influencedVertices;
+
+ NextNode();
+ while(m_currentNodeName == nnVertexBoneAssignment)
+ {
+ VertexBoneAssignment ba;
+ ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
+ ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
+ ba.weight = ReadAttribute<float>(anWeight);
+
+ dest->boneAssignments.push_back(ba);
+ influencedVertices.insert(ba.vertexIndex);
+
+ NextNode();
+ }
+
+ /** Normalize bone weights.
+ Some exporters wont care if the sum of all bone weights
+ for a single vertex equals 1 or not, so validate here. */
+ const float epsilon = 0.05f;
+ for (const uint32_t vertexIndex : influencedVertices)
+ {
+ float sum = 0.0f;
+ for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter)
+ {
+ if (baIter->vertexIndex == vertexIndex)
+ sum += baIter->weight;
+ }
+ if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
+ {
+ for (auto &boneAssign : dest->boneAssignments)
+ {
+ if (boneAssign.vertexIndex == vertexIndex)
+ boneAssign.weight /= sum;
+ }
+ }
+ }
+
+ DefaultLogger::get()->debug(Formatter::format() << " - " << dest->boneAssignments.size() << " bone assignments");
}
// Skeleton
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
{
- if (!mesh || mesh->skeletonRef.empty())
- return false;
-
- // Highly unusual to see in read world cases but support
- // XML mesh referencing a binary skeleton file.
- if (EndsWith(mesh->skeletonRef, ".skeleton", false))
- {
- if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh))
- return true;
-
- /** Last fallback if .skeleton failed to be read. Try reading from
- .skeleton.xml even if the XML file referenced a binary skeleton.
- @note This logic was in the previous version and I don't want to break
- old code that might depends on it. */
- mesh->skeletonRef = mesh->skeletonRef + ".xml";
- }
-
- XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
- if (!reader.get())
- return false;
-
- Skeleton *skeleton = new Skeleton();
- OgreXmlSerializer serializer(reader.get());
- serializer.ReadSkeleton(skeleton);
- mesh->skeleton = skeleton;
- return true;
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ // Highly unusual to see in read world cases but support
+ // XML mesh referencing a binary skeleton file.
+ if (EndsWith(mesh->skeletonRef, ".skeleton", false))
+ {
+ if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh))
+ return true;
+
+ /** Last fallback if .skeleton failed to be read. Try reading from
+ .skeleton.xml even if the XML file referenced a binary skeleton.
+ @note This logic was in the previous version and I don't want to break
+ old code that might depends on it. */
+ mesh->skeletonRef = mesh->skeletonRef + ".xml";
+ }
+
+ XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreXmlSerializer serializer(reader.get());
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
}
bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
{
- if (!mesh || mesh->skeletonRef.empty())
- return false;
-
- XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
- if (!reader.get())
- return false;
-
- Skeleton *skeleton = new Skeleton();
- OgreXmlSerializer serializer(reader.get());
- serializer.ReadSkeleton(skeleton);
- mesh->skeleton = skeleton;
- return true;
+ if (!mesh || mesh->skeletonRef.empty())
+ return false;
+
+ XmlReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
+ if (!reader.get())
+ return false;
+
+ Skeleton *skeleton = new Skeleton();
+ OgreXmlSerializer serializer(reader.get());
+ serializer.ReadSkeleton(skeleton);
+ mesh->skeleton = skeleton;
+ return true;
}
XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
{
- if (!EndsWith(filename, ".skeleton.xml", false))
- {
- DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
- return XmlReaderPtr();
- }
-
- if (!pIOHandler->Exists(filename))
- {
- DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
- return XmlReaderPtr();
- }
-
- boost::scoped_ptr<IOStream> file(pIOHandler->Open(filename));
- if (!file.get()) {
- throw DeadlyImportError("Failed to open skeleton file " + filename);
- }
-
- boost::scoped_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
- XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
- if (!reader.get()) {
- throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
- }
- return reader;
+ if (!EndsWith(filename, ".skeleton.xml", false))
+ {
+ DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
+ return XmlReaderPtr();
+ }
+
+ if (!pIOHandler->Exists(filename))
+ {
+ DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
+ return XmlReaderPtr();
+ }
+
+ std::unique_ptr<IOStream> file(pIOHandler->Open(filename));
+ if (!file.get()) {
+ throw DeadlyImportError("Failed to open skeleton file " + filename);
+ }
+
+ std::unique_ptr<CIrrXML_IOStreamReader> stream(new CIrrXML_IOStreamReader(file.get()));
+ XmlReaderPtr reader = XmlReaderPtr(irr::io::createIrrXMLReader(stream.get()));
+ if (!reader.get()) {
+ throw DeadlyImportError("Failed to create XML reader for skeleton file " + filename);
+ }
+ return reader;
}
void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton)
{
- if (NextNode() != nnSkeleton) {
- throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
- }
-
- DefaultLogger::get()->debug("Reading Skeleton");
-
- // Optional blend mode from root node
- if (HasAttribute("blendmode")) {
- skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative"
- ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
- }
-
- NextNode();
-
- // Root level nodes
- while(m_currentNodeName == nnBones ||
- m_currentNodeName == nnBoneHierarchy ||
- m_currentNodeName == nnAnimations ||
- m_currentNodeName == nnAnimationLinks)
- {
- if (m_currentNodeName == nnBones)
- ReadBones(skeleton);
- else if (m_currentNodeName == nnBoneHierarchy)
- ReadBoneHierarchy(skeleton);
- else if (m_currentNodeName == nnAnimations)
- ReadAnimations(skeleton);
- else
- SkipCurrentNode();
- }
+ if (NextNode() != nnSkeleton) {
+ throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting <skeleton>");
+ }
+
+ DefaultLogger::get()->debug("Reading Skeleton");
+
+ // Optional blend mode from root node
+ if (HasAttribute("blendmode")) {
+ skeleton->blendMode = (ToLower(ReadAttribute<std::string>("blendmode")) == "cumulative"
+ ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE);
+ }
+
+ NextNode();
+
+ // Root level nodes
+ while(m_currentNodeName == nnBones ||
+ m_currentNodeName == nnBoneHierarchy ||
+ m_currentNodeName == nnAnimations ||
+ m_currentNodeName == nnAnimationLinks)
+ {
+ if (m_currentNodeName == nnBones)
+ ReadBones(skeleton);
+ else if (m_currentNodeName == nnBoneHierarchy)
+ ReadBoneHierarchy(skeleton);
+ else if (m_currentNodeName == nnAnimations)
+ ReadAnimations(skeleton);
+ else
+ SkipCurrentNode();
+ }
}
void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton)
{
- if (skeleton->bones.empty()) {
- throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
- }
-
- DefaultLogger::get()->debug(" - Animations");
-
- NextNode();
- while(m_currentNodeName == nnAnimation)
- {
- Animation *anim = new Animation(skeleton);
- anim->name = ReadAttribute<std::string>("name");
- anim->length = ReadAttribute<float>("length");
-
- if (NextNode() != nnTracks) {
- throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
- }
-
- ReadAnimationTracks(anim);
- skeleton->animations.push_back(anim);
-
- DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
- }
+ if (skeleton->bones.empty()) {
+ throw DeadlyImportError("Cannot read <animations> for a Skeleton without bones");
+ }
+
+ DefaultLogger::get()->debug(" - Animations");
+
+ NextNode();
+ while(m_currentNodeName == nnAnimation)
+ {
+ Animation *anim = new Animation(skeleton);
+ anim->name = ReadAttribute<std::string>("name");
+ anim->length = ReadAttribute<float>("length");
+
+ if (NextNode() != nnTracks) {
+ throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
+ }
+
+ ReadAnimationTracks(anim);
+ skeleton->animations.push_back(anim);
+
+ DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
+ }
}
void OgreXmlSerializer::ReadAnimationTracks(Animation *dest)
{
- NextNode();
- while(m_currentNodeName == nnTrack)
- {
- VertexAnimationTrack track;
- track.type = VertexAnimationTrack::VAT_TRANSFORM;
- track.boneName = ReadAttribute<std::string>("bone");
+ NextNode();
+ while(m_currentNodeName == nnTrack)
+ {
+ VertexAnimationTrack track;
+ track.type = VertexAnimationTrack::VAT_TRANSFORM;
+ track.boneName = ReadAttribute<std::string>("bone");
- if (NextNode() != nnKeyFrames) {
- throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
- }
+ if (NextNode() != nnKeyFrames) {
+ throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
+ }
- ReadAnimationKeyFrames(dest, &track);
+ ReadAnimationKeyFrames(dest, &track);
- dest->tracks.push_back(track);
- }
+ dest->tracks.push_back(track);
+ }
}
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest)
{
- const aiVector3D zeroVec(0.f, 0.f, 0.f);
-
- NextNode();
- while(m_currentNodeName == nnKeyFrame)
- {
- TransformKeyFrame keyframe;
- keyframe.timePos = ReadAttribute<float>("time");
-
- NextNode();
- while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale)
- {
- if (m_currentNodeName == nnTranslate)
- {
- keyframe.position.x = ReadAttribute<float>(anX);
- keyframe.position.y = ReadAttribute<float>(anY);
- keyframe.position.z = ReadAttribute<float>(anZ);
- }
- else if (m_currentNodeName == nnRotate)
- {
- float angle = ReadAttribute<float>("angle");
-
- if (NextNode() != nnAxis) {
- throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name);
- }
-
- aiVector3D axis;
- axis.x = ReadAttribute<float>(anX);
- axis.y = ReadAttribute<float>(anY);
- axis.z = ReadAttribute<float>(anZ);
- if (axis.Equal(zeroVec))
- {
- axis.x = 1.0f;
- if (angle != 0) {
- DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation: " + anim->name);
- }
- }
- keyframe.rotation = aiQuaternion(axis, angle);
- }
- else if (m_currentNodeName == nnScale)
- {
- keyframe.scale.x = ReadAttribute<float>(anX);
- keyframe.scale.y = ReadAttribute<float>(anY);
- keyframe.scale.z = ReadAttribute<float>(anZ);
- }
-
- NextNode();
- }
-
- dest->transformKeyFrames.push_back(keyframe);
- }
+ const aiVector3D zeroVec(0.f, 0.f, 0.f);
+
+ NextNode();
+ while(m_currentNodeName == nnKeyFrame)
+ {
+ TransformKeyFrame keyframe;
+ keyframe.timePos = ReadAttribute<float>("time");
+
+ NextNode();
+ while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale)
+ {
+ if (m_currentNodeName == nnTranslate)
+ {
+ keyframe.position.x = ReadAttribute<float>(anX);
+ keyframe.position.y = ReadAttribute<float>(anY);
+ keyframe.position.z = ReadAttribute<float>(anZ);
+ }
+ else if (m_currentNodeName == nnRotate)
+ {
+ float angle = ReadAttribute<float>("angle");
+
+ if (NextNode() != nnAxis) {
+ throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name);
+ }
+
+ aiVector3D axis;
+ axis.x = ReadAttribute<float>(anX);
+ axis.y = ReadAttribute<float>(anY);
+ axis.z = ReadAttribute<float>(anZ);
+ if (axis.Equal(zeroVec))
+ {
+ axis.x = 1.0f;
+ if (angle != 0) {
+ DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation: " + anim->name);
+ }
+ }
+ keyframe.rotation = aiQuaternion(axis, angle);
+ }
+ else if (m_currentNodeName == nnScale)
+ {
+ keyframe.scale.x = ReadAttribute<float>(anX);
+ keyframe.scale.y = ReadAttribute<float>(anY);
+ keyframe.scale.z = ReadAttribute<float>(anZ);
+ }
+
+ NextNode();
+ }
+
+ dest->transformKeyFrames.push_back(keyframe);
+ }
}
void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton)
{
- if (skeleton->bones.empty()) {
- throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
- }
-
- while(NextNode() == nnBoneParent)
- {
- const std::string name = ReadAttribute<std::string>("bone");
- const std::string parentName = ReadAttribute<std::string>("parent");
-
- Bone *bone = skeleton->BoneByName(name);
- Bone *parent = skeleton->BoneByName(parentName);
-
- if (bone && parent)
- parent->AddChild(bone);
- else
- throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
- }
-
- // Calculate bone matrices for root bones. Recursively calculates their children.
- for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
- {
- Bone *bone = skeleton->bones[i];
- if (!bone->IsParented())
- bone->CalculateWorldMatrixAndDefaultPose(skeleton);
- }
+ if (skeleton->bones.empty()) {
+ throw DeadlyImportError("Cannot read <bonehierarchy> for a Skeleton without bones");
+ }
+
+ while(NextNode() == nnBoneParent)
+ {
+ const std::string name = ReadAttribute<std::string>("bone");
+ const std::string parentName = ReadAttribute<std::string>("parent");
+
+ Bone *bone = skeleton->BoneByName(name);
+ Bone *parent = skeleton->BoneByName(parentName);
+
+ if (bone && parent)
+ parent->AddChild(bone);
+ else
+ throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
+ }
+
+ // Calculate bone matrices for root bones. Recursively calculates their children.
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *bone = skeleton->bones[i];
+ if (!bone->IsParented())
+ bone->CalculateWorldMatrixAndDefaultPose(skeleton);
+ }
}
bool BoneCompare(Bone *a, Bone *b)
{
- return (a->id < b->id);
+ return (a->id < b->id);
}
void OgreXmlSerializer::ReadBones(Skeleton *skeleton)
{
- DefaultLogger::get()->debug(" - Bones");
-
- NextNode();
- while(m_currentNodeName == nnBone)
- {
- Bone *bone = new Bone();
- bone->id = ReadAttribute<uint16_t>("id");
- bone->name = ReadAttribute<std::string>("name");
-
- NextNode();
- while(m_currentNodeName == nnPosition ||
- m_currentNodeName == nnRotation ||
- m_currentNodeName == nnScale)
- {
- if (m_currentNodeName == nnPosition)
- {
- bone->position.x = ReadAttribute<float>(anX);
- bone->position.y = ReadAttribute<float>(anY);
- bone->position.z = ReadAttribute<float>(anZ);
- }
- else if (m_currentNodeName == nnRotation)
- {
- float angle = ReadAttribute<float>("angle");
-
- if (NextNode() != nnAxis) {
- throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id);
- }
-
- aiVector3D axis;
- axis.x = ReadAttribute<float>(anX);
- axis.y = ReadAttribute<float>(anY);
- axis.z = ReadAttribute<float>(anZ);
-
- bone->rotation = aiQuaternion(axis, angle);
- }
- else if (m_currentNodeName == nnScale)
- {
- /// @todo Implement taking scale into account in matrix/pose calculations!
- if (HasAttribute("factor"))
- {
- float factor = ReadAttribute<float>("factor");
- bone->scale.Set(factor, factor, factor);
- }
- else
- {
- if (HasAttribute(anX))
- bone->scale.x = ReadAttribute<float>(anX);
- if (HasAttribute(anY))
- bone->scale.y = ReadAttribute<float>(anY);
- if (HasAttribute(anZ))
- bone->scale.z = ReadAttribute<float>(anZ);
- }
- }
-
- NextNode();
- }
-
- skeleton->bones.push_back(bone);
- }
-
- // Order bones by Id
- std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare);
-
- // Validate that bone indexes are not skipped.
- /** @note Left this from original authors code, but not sure if this is strictly necessary
- as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
- for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
- {
- Bone *b = skeleton->bones[i];
- DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name);
-
- if (b->id != static_cast<uint16_t>(i)) {
- throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i);
- }
- }
+ DefaultLogger::get()->debug(" - Bones");
+
+ NextNode();
+ while(m_currentNodeName == nnBone)
+ {
+ Bone *bone = new Bone();
+ bone->id = ReadAttribute<uint16_t>("id");
+ bone->name = ReadAttribute<std::string>("name");
+
+ NextNode();
+ while(m_currentNodeName == nnPosition ||
+ m_currentNodeName == nnRotation ||
+ m_currentNodeName == nnScale)
+ {
+ if (m_currentNodeName == nnPosition)
+ {
+ bone->position.x = ReadAttribute<float>(anX);
+ bone->position.y = ReadAttribute<float>(anY);
+ bone->position.z = ReadAttribute<float>(anZ);
+ }
+ else if (m_currentNodeName == nnRotation)
+ {
+ float angle = ReadAttribute<float>("angle");
+
+ if (NextNode() != nnAxis) {
+ throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id);
+ }
+
+ aiVector3D axis;
+ axis.x = ReadAttribute<float>(anX);
+ axis.y = ReadAttribute<float>(anY);
+ axis.z = ReadAttribute<float>(anZ);
+
+ bone->rotation = aiQuaternion(axis, angle);
+ }
+ else if (m_currentNodeName == nnScale)
+ {
+ /// @todo Implement taking scale into account in matrix/pose calculations!
+ if (HasAttribute("factor"))
+ {
+ float factor = ReadAttribute<float>("factor");
+ bone->scale.Set(factor, factor, factor);
+ }
+ else
+ {
+ if (HasAttribute(anX))
+ bone->scale.x = ReadAttribute<float>(anX);
+ if (HasAttribute(anY))
+ bone->scale.y = ReadAttribute<float>(anY);
+ if (HasAttribute(anZ))
+ bone->scale.z = ReadAttribute<float>(anZ);
+ }
+ }
+
+ NextNode();
+ }
+
+ skeleton->bones.push_back(bone);
+ }
+
+ // Order bones by Id
+ std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare);
+
+ // Validate that bone indexes are not skipped.
+ /** @note Left this from original authors code, but not sure if this is strictly necessary
+ as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */
+ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
+ {
+ Bone *b = skeleton->bones[i];
+ DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name);
+
+ if (b->id != static_cast<uint16_t>(i)) {
+ throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i);
+ }
+ }
}
} // Ogre
diff --git a/src/3rdparty/assimp/code/OgreXmlSerializer.h b/src/3rdparty/assimp/code/OgreXmlSerializer.h
index 62257f81c..47b4cafc0 100644
--- a/src/3rdparty/assimp/code/OgreXmlSerializer.h
+++ b/src/3rdparty/assimp/code/OgreXmlSerializer.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -52,61 +52,61 @@ namespace Ogre
{
typedef irr::io::IrrXMLReader XmlReader;
-typedef boost::shared_ptr<XmlReader> XmlReaderPtr;
+typedef std::shared_ptr<XmlReader> XmlReaderPtr;
class OgreXmlSerializer
{
public:
- /// Imports mesh and returns the result.
- /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
- static MeshXml *ImportMesh(XmlReader *reader);
-
- /// Imports skeleton to @c mesh.
- /** If mesh does not have a skeleton reference or the skeleton file
- cannot be found it is not a fatal DeadlyImportError.
- @return If skeleton import was successful. */
- static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
- static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
+ /// Imports mesh and returns the result.
+ /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
+ static MeshXml *ImportMesh(XmlReader *reader);
+
+ /// Imports skeleton to @c mesh.
+ /** If mesh does not have a skeleton reference or the skeleton file
+ cannot be found it is not a fatal DeadlyImportError.
+ @return If skeleton import was successful. */
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
+ static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
private:
- OgreXmlSerializer(XmlReader *reader) :
- m_reader(reader)
- {
- }
-
- static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
-
- // Mesh
- void ReadMesh(MeshXml *mesh);
- void ReadSubMesh(MeshXml *mesh);
-
- void ReadGeometry(VertexDataXml *dest);
- void ReadGeometryVertexBuffer(VertexDataXml *dest);
-
- void ReadBoneAssignments(VertexDataXml *dest);
-
- // Skeleton
- void ReadSkeleton(Skeleton *skeleton);
-
- void ReadBones(Skeleton *skeleton);
- void ReadBoneHierarchy(Skeleton *skeleton);
-
- void ReadAnimations(Skeleton *skeleton);
- void ReadAnimationTracks(Animation *dest);
- void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
-
- template<typename T>
- T ReadAttribute(const std::string &name) const;
- bool HasAttribute(const std::string &name) const;
-
- std::string &NextNode();
- std::string &SkipCurrentNode();
-
- bool CurrentNodeNameEquals(const std::string &name) const;
- std::string CurrentNodeName(bool forceRead = false);
-
- XmlReader *m_reader;
- std::string m_currentNodeName;
+ explicit OgreXmlSerializer(XmlReader *reader) :
+ m_reader(reader)
+ {
+ }
+
+ static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
+
+ // Mesh
+ void ReadMesh(MeshXml *mesh);
+ void ReadSubMesh(MeshXml *mesh);
+
+ void ReadGeometry(VertexDataXml *dest);
+ void ReadGeometryVertexBuffer(VertexDataXml *dest);
+
+ void ReadBoneAssignments(VertexDataXml *dest);
+
+ // Skeleton
+ void ReadSkeleton(Skeleton *skeleton);
+
+ void ReadBones(Skeleton *skeleton);
+ void ReadBoneHierarchy(Skeleton *skeleton);
+
+ void ReadAnimations(Skeleton *skeleton);
+ void ReadAnimationTracks(Animation *dest);
+ void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
+
+ template<typename T>
+ T ReadAttribute(const std::string &name) const;
+ bool HasAttribute(const std::string &name) const;
+
+ std::string &NextNode();
+ std::string &SkipCurrentNode();
+
+ bool CurrentNodeNameEquals(const std::string &name) const;
+ std::string CurrentNodeName(bool forceRead = false);
+
+ XmlReader *m_reader;
+ std::string m_currentNodeName;
};
} // Ogre
diff --git a/src/3rdparty/assimp/code/OpenGEXExporter.cpp b/src/3rdparty/assimp/code/OpenGEXExporter.cpp
new file mode 100644
index 000000000..77a60fdfb
--- /dev/null
+++ b/src/3rdparty/assimp/code/OpenGEXExporter.cpp
@@ -0,0 +1,56 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#include "OpenGEXExporter.h"
+
+namespace Assimp {
+namespace OpenGEX {
+
+#ifndef ASSIMP_BUILD_NO_OPENGEX_EXPORTER
+
+OpenGEXExporter::OpenGEXExporter() {
+}
+
+OpenGEXExporter::~OpenGEXExporter() {
+}
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_EXPORTER
+
+} // Namespace OpenGEX
+} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/OpenGEXExporter.h b/src/3rdparty/assimp/code/OpenGEXExporter.h
new file mode 100644
index 000000000..f9757f41c
--- /dev/null
+++ b/src/3rdparty/assimp/code/OpenGEXExporter.h
@@ -0,0 +1,66 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEX_EXPORTER_H
+#define AI_OPENGEX_EXPORTER_H
+
+#include <assimp/types.h>
+
+#ifndef ASSIMP_BUILD_NO_OPENGEX_EXPORTER
+
+namespace Assimp {
+
+struct aiScene;
+
+namespace OpenGEX {
+
+class OpenGEXExporter {
+public:
+ OpenGEXExporter();
+ ~OpenGEXExporter();
+ bool exportScene( const char *filename, const aiScene* pScene );
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_EXPORTER
+
+#endif // AI_OPENGEX_EXPORTER_H
+
diff --git a/src/3rdparty/assimp/code/OpenGEXImporter.cpp b/src/3rdparty/assimp/code/OpenGEXImporter.cpp
new file mode 100644
index 000000000..f3a886a96
--- /dev/null
+++ b/src/3rdparty/assimp/code/OpenGEXImporter.cpp
@@ -0,0 +1,1190 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "OpenGEXImporter.h"
+#include "DefaultIOSystem.h"
+#include <assimp/DefaultLogger.hpp>
+#include "MakeVerboseFormat.h"
+#include "StringComparison.h"
+
+#include <openddlparser/OpenDDLParser.h>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
+
+#include <vector>
+
+static const std::string OpenGexExt = "ogex";
+
+static const aiImporterDesc desc = {
+ "Open Game Engine Exchange",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ OpenGexExt.c_str()
+};
+
+namespace Grammar {
+ static const std::string MetricType = "Metric";
+ static const std::string Metric_DistanceType = "distance";
+ static const std::string Metric_AngleType = "angle";
+ static const std::string Metric_TimeType = "time";
+ static const std::string Metric_UpType = "up";
+ static const std::string NameType = "Name";
+ static const std::string ObjectRefType = "ObjectRef";
+ static const std::string MaterialRefType = "MaterialRef";
+ static const std::string MetricKeyType = "key";
+ static const std::string GeometryNodeType = "GeometryNode";
+ static const std::string CameraNodeType = "CameraNode";
+ static const std::string LightNodeType = "LightNode";
+ static const std::string GeometryObjectType = "GeometryObject";
+ static const std::string CameraObjectType = "CameraObject";
+ static const std::string LightObjectType = "LightObject";
+ static const std::string TransformType = "Transform";
+ static const std::string MeshType = "Mesh";
+ static const std::string VertexArrayType = "VertexArray";
+ static const std::string IndexArrayType = "IndexArray";
+ static const std::string MaterialType = "Material";
+ static const std::string ColorType = "Color";
+ static const std::string ParamType = "Param";
+ static const std::string TextureType = "Texture";
+ static const std::string AttenType = "Atten";
+
+ static const std::string DiffuseColorToken = "diffuse";
+ static const std::string SpecularColorToken = "specular";
+ static const std::string EmissionColorToken = "emission";
+
+ static const std::string DiffuseTextureToken = "diffuse";
+ static const std::string DiffuseSpecularTextureToken = "specular";
+ static const std::string SpecularPowerTextureToken = "specular_power";
+ static const std::string EmissionTextureToken = "emission";
+ static const std::string OpacyTextureToken = "opacity";
+ static const std::string TransparencyTextureToken = "transparency";
+ static const std::string NormalTextureToken = "normal";
+
+ enum TokenType {
+ NoneType = -1,
+ MetricToken,
+ NameToken,
+ ObjectRefToken,
+ MaterialRefToken,
+ MetricKeyToken,
+ GeometryNodeToken,
+ CameraNodeToken,
+ LightNodeToken,
+ GeometryObjectToken,
+ CameraObjectToken,
+ LightObjectToken,
+ TransformToken,
+ MeshToken,
+ VertexArrayToken,
+ IndexArrayToken,
+ MaterialToken,
+ ColorToken,
+ ParamToken,
+ TextureToken,
+ AttenToken
+ };
+
+ static const std::string ValidMetricToken[ 4 ] = {
+ Metric_DistanceType,
+ Metric_AngleType,
+ Metric_TimeType,
+ Metric_UpType
+ };
+
+ static int isValidMetricType( const char *token ) {
+ if( nullptr == token ) {
+ return false;
+ }
+
+ int idx( -1 );
+ for( size_t i = 0; i < 4; i++ ) {
+ if( ValidMetricToken[ i ] == token ) {
+ idx = (int) i;
+ break;
+ }
+ }
+
+ return idx;
+ }
+
+ static TokenType matchTokenType( const char *tokenType ) {
+ if( MetricType == tokenType ) {
+ return MetricToken;
+ } else if( NameType == tokenType ) {
+ return NameToken;
+ } else if( ObjectRefType == tokenType ) {
+ return ObjectRefToken;
+ } else if( MaterialRefType == tokenType ) {
+ return MaterialRefToken;
+ } else if( MetricKeyType == tokenType ) {
+ return MetricKeyToken;
+ } else if ( GeometryNodeType == tokenType ) {
+ return GeometryNodeToken;
+ } else if ( CameraNodeType == tokenType ) {
+ return CameraNodeToken;
+ } else if ( LightNodeType == tokenType ) {
+ return LightNodeToken;
+ } else if ( GeometryObjectType == tokenType ) {
+ return GeometryObjectToken;
+ } else if ( CameraObjectType == tokenType ) {
+ return CameraObjectToken;
+ } else if ( LightObjectType == tokenType ) {
+ return LightObjectToken;
+ } else if( TransformType == tokenType ) {
+ return TransformToken;
+ } else if( MeshType == tokenType ) {
+ return MeshToken;
+ } else if( VertexArrayType == tokenType ) {
+ return VertexArrayToken;
+ } else if( IndexArrayType == tokenType ) {
+ return IndexArrayToken;
+ } else if( MaterialType == tokenType ) {
+ return MaterialToken;
+ } else if ( ColorType == tokenType ) {
+ return ColorToken;
+ } else if ( ParamType == tokenType ) {
+ return ParamToken;
+ } else if( TextureType == tokenType ) {
+ return TextureToken;
+ } else if ( AttenType == tokenType ) {
+ return AttenToken;
+ }
+
+ return NoneType;
+ }
+
+} // Namespace Grammar
+
+namespace Assimp {
+namespace OpenGEX {
+
+USE_ODDLPARSER_NS
+
+//------------------------------------------------------------------------------------------------
+static void propId2StdString( Property *prop, std::string &name, std::string &key ) {
+ name = key = "";
+ if ( nullptr == prop ) {
+ return;
+ }
+
+ if ( nullptr != prop->m_key ) {
+ name = prop->m_key->m_buffer;
+ if ( Value::ddl_string == prop->m_value->m_type ) {
+ key = prop->m_value->getString();
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::VertexContainer::VertexContainer()
+: m_numVerts( 0 )
+, m_vertices( nullptr )
+, m_numNormals( 0 )
+, m_normals( nullptr )
+, m_numUVComps()
+, m_textureCoords()
+ {
+ // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::VertexContainer::~VertexContainer() {
+ delete[] m_vertices;
+ delete[] m_normals;
+
+ for(auto &texcoords : m_textureCoords) {
+ delete [] texcoords;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::RefInfo( aiNode *node, Type type, std::vector<std::string> &names )
+: m_node( node )
+, m_type( type )
+, m_Names( names ) {
+ // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::RefInfo::~RefInfo() {
+ // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::OpenGEXImporter()
+: m_root( nullptr )
+, m_nodeChildMap()
+, m_meshCache()
+, m_mesh2refMap()
+, m_ctx( nullptr )
+, m_metrics()
+, m_currentNode( nullptr )
+, m_currentVertices()
+, m_currentMesh( nullptr )
+, m_currentMaterial( nullptr )
+, m_currentLight( nullptr )
+, m_currentCamera( nullptr )
+, m_tokenType( Grammar::NoneType )
+, m_materialCache()
+, m_cameraCache()
+, m_lightCache()
+, m_nodeStack()
+, m_unresolvedRefStack() {
+ // empty
+}
+
+//------------------------------------------------------------------------------------------------
+OpenGEXImporter::~OpenGEXImporter() {
+ m_ctx = NULL;
+}
+
+//------------------------------------------------------------------------------------------------
+bool OpenGEXImporter::CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const {
+ bool canRead( false );
+ if( !checkSig ) {
+ canRead = SimpleExtensionCheck( file, OpenGexExt.c_str() );
+ } else {
+ static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
+ canRead = BaseImporter::SearchFileHeaderForToken( pIOHandler, file, token, 4 );
+ }
+
+ return canRead;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) {
+ // open source file
+ IOStream *file = pIOHandler->Open( filename, "rb" );
+ if( !file ) {
+ throw DeadlyImportError( "Failed to open file " + filename );
+ }
+
+ std::vector<char> buffer;
+ TextFileToBuffer( file, buffer );
+
+ OpenDDLParser myParser;
+ myParser.setBuffer( &buffer[ 0 ], buffer.size() );
+ bool success( myParser.parse() );
+ if( success ) {
+ m_ctx = myParser.getContext();
+ pScene->mRootNode = new aiNode;
+ pScene->mRootNode->mName.Set( filename );
+ handleNodes( m_ctx->m_root, pScene );
+ }
+
+ copyMeshes( pScene );
+ copyCameras( pScene );
+ copyLights( pScene );
+ resolveReferences();
+ createNodeTree( pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+const aiImporterDesc *OpenGEXImporter::GetInfo() const {
+ return &desc;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::SetupProperties( const Importer *pImp ) {
+ if( nullptr == pImp ) {
+ return;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node ) {
+ return;
+ }
+
+ DDLNode::DllNodeList childs = node->getChildNodeList();
+ for( DDLNode::DllNodeList::iterator it = childs.begin(); it != childs.end(); ++it ) {
+ Grammar::TokenType tokenType( Grammar::matchTokenType( ( *it )->getType().c_str() ) );
+ switch( tokenType ) {
+ case Grammar::MetricToken:
+ handleMetricNode( *it, pScene );
+ break;
+
+ case Grammar::NameToken:
+ handleNameNode( *it, pScene );
+ break;
+
+ case Grammar::ObjectRefToken:
+ handleObjectRefNode( *it, pScene );
+ break;
+
+ case Grammar::MaterialRefToken:
+ handleMaterialRefNode( *it, pScene );
+ break;
+
+ case Grammar::MetricKeyToken:
+ break;
+
+ case Grammar::GeometryNodeToken:
+ handleGeometryNode( *it, pScene );
+ break;
+
+ case Grammar::CameraNodeToken:
+ handleCameraNode( *it, pScene );
+ break;
+
+ case Grammar::LightNodeToken:
+ handleLightNode( *it, pScene );
+ break;
+
+ case Grammar::GeometryObjectToken:
+ handleGeometryObject( *it, pScene );
+ break;
+
+ case Grammar::CameraObjectToken:
+ handleCameraObject( *it, pScene );
+ break;
+
+ case Grammar::LightObjectToken:
+ handleLightObject( *it, pScene );
+ break;
+
+ case Grammar::TransformToken:
+ handleTransformNode( *it, pScene );
+ break;
+
+ case Grammar::MeshToken:
+ handleMeshNode( *it, pScene );
+ break;
+
+ case Grammar::VertexArrayToken:
+ handleVertexArrayNode( *it, pScene );
+ break;
+
+ case Grammar::IndexArrayToken:
+ handleIndexArrayNode( *it, pScene );
+ break;
+
+ case Grammar::MaterialToken:
+ handleMaterialNode( *it, pScene );
+ break;
+
+ case Grammar::ColorToken:
+ handleColorNode( *it, pScene );
+ break;
+
+ case Grammar::ParamToken:
+ handleParamNode( *it, pScene );
+ break;
+
+ case Grammar::TextureToken:
+ handleTextureNode( *it, pScene );
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node || nullptr == m_ctx ) {
+ return;
+ }
+
+ if( m_ctx->m_root != node->getParent() ) {
+ return;
+ }
+
+ Property *prop( node->getProperties() );
+ while( nullptr != prop ) {
+ if( nullptr != prop->m_key ) {
+ if( Value::ddl_string == prop->m_value->m_type ) {
+ std::string valName( ( char* ) prop->m_value->m_data );
+ int type( Grammar::isValidMetricType( valName.c_str() ) );
+ if( Grammar::NoneType != type ) {
+ Value *val( node->getValue() );
+ if( nullptr != val ) {
+ if( Value::ddl_float == val->m_type ) {
+ m_metrics[ type ].m_floatValue = val->getFloat();
+ } else if( Value::ddl_int32 == val->m_type ) {
+ m_metrics[ type ].m_intValue = val->getInt32();
+ } else if( Value::ddl_string == val->m_type ) {
+ m_metrics[type].m_stringValue = std::string( val->getString() );
+ } else {
+ throw DeadlyImportError( "OpenGEX: invalid data type for Metric node." );
+ }
+ }
+ }
+ }
+ }
+ prop = prop->m_next;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
+ if( NULL == m_currentNode ) {
+ throw DeadlyImportError( "No current node for name." );
+ return;
+ }
+
+ Value *val( node->getValue() );
+ if( NULL != val ) {
+ if( Value::ddl_string != val->m_type ) {
+ throw DeadlyImportError( "OpenGEX: invalid data type for value in node name." );
+ return;
+ }
+
+ const std::string name( val->getString() );
+ if( m_tokenType == Grammar::GeometryNodeToken || m_tokenType == Grammar::LightNodeToken
+ || m_tokenType == Grammar::CameraNodeToken ) {
+ m_currentNode->mName.Set( name.c_str() );
+ } else if( m_tokenType == Grammar::MaterialToken ) {
+
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+static void getRefNames( DDLNode *node, std::vector<std::string> &names ) {
+ ai_assert( NULL != node );
+
+ Reference *ref = node->getReferences();
+ if( nullptr != ref ) {
+ for( size_t i = 0; i < ref->m_numRefs; i++ ) {
+ Name *currentName( ref->m_referencedName[ i ] );
+ if( nullptr != currentName && nullptr != currentName->m_id ) {
+ const std::string name( currentName->m_id->m_buffer );
+ if( !name.empty() ) {
+ names.push_back( name );
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
+ if( nullptr == m_currentNode ) {
+ throw DeadlyImportError( "No parent node for name." );
+ return;
+ }
+
+ std::vector<std::string> objRefNames;
+ getRefNames( node, objRefNames );
+
+ // when we are dealing with a geometry node prepare the mesh cache
+ if ( m_tokenType == Grammar::GeometryNodeToken ) {
+ m_currentNode->mNumMeshes = objRefNames.size();
+ m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ];
+ if ( !objRefNames.empty() ) {
+ m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == m_currentNode ) {
+ throw DeadlyImportError( "No parent node for name." );
+ return;
+ }
+
+ std::vector<std::string> matRefNames;
+ getRefNames( node, matRefNames );
+ if( !matRefNames.empty() ) {
+ m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) );
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryNode( DDLNode *node, aiScene *pScene ) {
+ aiNode *newNode = new aiNode;
+ pushNode( newNode, pScene );
+ m_tokenType = Grammar::GeometryNodeToken;
+ m_currentNode = newNode;
+ handleNodes( node, pScene );
+
+ popNode();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleCameraNode( DDLNode *node, aiScene *pScene ) {
+ aiCamera *camera( new aiCamera );
+ m_cameraCache.push_back( camera );
+ m_currentCamera = camera;
+
+ aiNode *newNode = new aiNode;
+ pushNode( newNode, pScene );
+ m_tokenType = Grammar::CameraNodeToken;
+ m_currentNode = newNode;
+
+ handleNodes( node, pScene );
+
+ popNode();
+
+ m_currentCamera->mName.Set( newNode->mName.C_Str() );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleLightNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ aiLight *light( new aiLight );
+ m_lightCache.push_back( light );
+ m_currentLight = light;
+
+ aiNode *newNode = new aiNode;
+ m_tokenType = Grammar::LightNodeToken;
+ m_currentNode = newNode;
+ pushNode( newNode, pScene );
+
+ handleNodes( node, pScene );
+
+ popNode();
+
+ m_currentLight->mName.Set( newNode->mName.C_Str() );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleGeometryObject( DDLNode *node, aiScene *pScene ) {
+ // parameters will be parsed normally in the tree, so just go for it
+ handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleCameraObject( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ // parameters will be parsed normally in the tree, so just go for it
+
+ handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleLightObject( ODDLParser::DDLNode *node, aiScene *pScene ) {
+
+ Property *prop( node->findPropertyByName( "type" ) );
+ if ( nullptr != prop ) {
+ if ( nullptr != prop->m_value ) {
+ std::string typeStr( prop->m_value->getString() );
+ if ( "point" == typeStr ) {
+ m_currentLight->mType = aiLightSource_POINT;
+ } else if ( "spot" == typeStr ) {
+ m_currentLight->mType = aiLightSource_SPOT;
+ } else if ( "infinite" == typeStr ) {
+ m_currentLight->mType = aiLightSource_DIRECTIONAL;
+ }
+ }
+ }
+
+ // parameters will be parsed normally in the tree, so just go for it
+ handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+static void setMatrix( aiNode *node, DataArrayList *transformData ) {
+ ai_assert( nullptr != node );
+ ai_assert( nullptr != transformData );
+
+ float m[ 16 ];
+ size_t i( 1 );
+ Value *next( transformData->m_dataList->m_next );
+ m[ 0 ] = transformData->m_dataList->getFloat();
+ while( next != nullptr ) {
+ m[ i ] = next->getFloat();
+ next = next->m_next;
+ i++;
+ }
+
+ node->mTransformation.a1 = m[ 0 ];
+ node->mTransformation.a2 = m[ 4 ];
+ node->mTransformation.a3 = m[ 8 ];
+ node->mTransformation.a4 = m[ 12 ];
+
+ node->mTransformation.b1 = m[ 1 ];
+ node->mTransformation.b2 = m[ 5 ];
+ node->mTransformation.b3 = m[ 9 ];
+ node->mTransformation.b4 = m[ 13 ];
+
+ node->mTransformation.c1 = m[ 2 ];
+ node->mTransformation.c2 = m[ 6 ];
+ node->mTransformation.c3 = m[ 10 ];
+ node->mTransformation.c4 = m[ 14 ];
+
+ node->mTransformation.d1 = m[ 3 ];
+ node->mTransformation.d2 = m[ 7 ];
+ node->mTransformation.d3 = m[ 11 ];
+ node->mTransformation.d4 = m[ 15 ];
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == m_currentNode ) {
+ throw DeadlyImportError( "No parent node for name." );
+ return;
+ }
+
+ DataArrayList *transformData( node->getDataArrayList() );
+ if( nullptr != transformData ) {
+ if( transformData->m_numItems != 16 ) {
+ throw DeadlyImportError( "Invalid number of data for transform matrix." );
+ return;
+ }
+ setMatrix( m_currentNode, transformData );
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ m_currentMesh = new aiMesh;
+ const size_t meshidx( m_meshCache.size() );
+ m_meshCache.push_back( m_currentMesh );
+
+ Property *prop = node->getProperties();
+ if( nullptr != prop ) {
+ std::string propName, propKey;
+ propId2StdString( prop, propName, propKey );
+ if( "primitive" == propName ) {
+ if ( "points" == propKey ) {
+ m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ } else if ( "lines" == propKey ) {
+ m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ } else if( "triangles" == propKey ) {
+ m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ } else if ( "quads" == propKey ) {
+ m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ } else {
+ DefaultLogger::get()->warn( propKey + " is not supported primitive type." );
+ }
+ }
+ }
+
+ handleNodes( node, pScene );
+
+ DDLNode *parent( node->getParent() );
+ if( nullptr != parent ) {
+ const std::string &name = parent->getName();
+ m_mesh2refMap[ name ] = meshidx;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+enum MeshAttribute {
+ None,
+ Position,
+ Normal,
+ TexCoord
+};
+
+//------------------------------------------------------------------------------------------------
+static MeshAttribute getAttributeByName( const char *attribName ) {
+ ai_assert( nullptr != attribName );
+
+ if( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) {
+ return Position;
+ } else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) {
+ return Normal;
+ } else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) {
+ return TexCoord;
+ }
+
+ return None;
+}
+
+//------------------------------------------------------------------------------------------------
+static void fillVector3( aiVector3D *vec3, Value *vals ) {
+ ai_assert( nullptr != vec3 );
+ ai_assert( nullptr != vals );
+
+ float x( 0.0f ), y( 0.0f ), z( 0.0f );
+ Value *next( vals );
+ x = next->getFloat();
+ next = next->m_next;
+ y = next->getFloat();
+ next = next->m_next;
+ if( nullptr != next ) {
+ z = next->getFloat();
+ }
+
+ vec3->Set( x, y, z );
+}
+
+//------------------------------------------------------------------------------------------------
+static size_t countDataArrayListItems( DataArrayList *vaList ) {
+ size_t numItems( 0 );
+ if( nullptr == vaList ) {
+ return numItems;
+ }
+
+ DataArrayList *next( vaList );
+ while( nullptr != next ) {
+ if( nullptr != vaList->m_dataList ) {
+ numItems++;
+ }
+ next = next->m_next;
+ }
+
+ return numItems;
+}
+
+//------------------------------------------------------------------------------------------------
+static void copyVectorArray( size_t numItems, DataArrayList *vaList, aiVector3D *vectorArray ) {
+ for( size_t i = 0; i < numItems; i++ ) {
+ Value *next( vaList->m_dataList );
+ fillVector3( &vectorArray[ i ], next );
+ vaList = vaList->m_next;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node ) {
+ throw DeadlyImportError( "No parent node for name." );
+ return;
+ }
+
+ Property *prop( node->getProperties() );
+ if( nullptr != prop ) {
+ std::string propName, propKey;
+ propId2StdString( prop, propName, propKey );
+ MeshAttribute attribType( getAttributeByName( propKey.c_str() ) );
+ if( None == attribType ) {
+ return;
+ }
+
+ DataArrayList *vaList = node->getDataArrayList();
+ if( nullptr == vaList ) {
+ return;
+ }
+
+ const size_t numItems( countDataArrayListItems( vaList ) );
+
+ if( Position == attribType ) {
+ m_currentVertices.m_numVerts = numItems;
+ m_currentVertices.m_vertices = new aiVector3D[ numItems ];
+ copyVectorArray( numItems, vaList, m_currentVertices.m_vertices );
+ } else if( Normal == attribType ) {
+ m_currentVertices.m_numNormals = numItems;
+ m_currentVertices.m_normals = new aiVector3D[ numItems ];
+ copyVectorArray( numItems, vaList, m_currentVertices.m_normals );
+ } else if( TexCoord == attribType ) {
+ m_currentVertices.m_numUVComps[ 0 ] = numItems;
+ m_currentVertices.m_textureCoords[ 0 ] = new aiVector3D[ numItems ];
+ copyVectorArray( numItems, vaList, m_currentVertices.m_textureCoords[ 0 ] );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node ) {
+ throw DeadlyImportError( "No parent node for name." );
+ return;
+ }
+
+ if( nullptr == m_currentMesh ) {
+ throw DeadlyImportError( "No current mesh for index data found." );
+ return;
+ }
+
+ DataArrayList *vaList = node->getDataArrayList();
+ if( nullptr == vaList ) {
+ return;
+ }
+
+ const size_t numItems( countDataArrayListItems( vaList ) );
+ m_currentMesh->mNumFaces = numItems;
+ m_currentMesh->mFaces = new aiFace[ numItems ];
+ m_currentMesh->mNumVertices = numItems * 3;
+ m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ];
+ bool hasNormalCoords( false );
+ if ( m_currentVertices.m_numNormals > 0 ) {
+ m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ];
+ hasNormalCoords = true;
+ }
+ bool hasTexCoords( false );
+ if ( m_currentVertices.m_numUVComps[ 0 ] > 0 ) {
+ m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumVertices ];
+ hasTexCoords = true;
+ }
+
+ unsigned int index( 0 );
+ for( size_t i = 0; i < m_currentMesh->mNumFaces; i++ ) {
+ aiFace &current( m_currentMesh->mFaces[ i ] );
+ current.mNumIndices = 3;
+ current.mIndices = new unsigned int[ current.mNumIndices ];
+ Value *next( vaList->m_dataList );
+ for( size_t indices = 0; indices < current.mNumIndices; indices++ ) {
+ const int idx( next->getUnsignedInt32() );
+ ai_assert( static_cast<size_t>( idx ) <= m_currentVertices.m_numVerts );
+ ai_assert( index < m_currentMesh->mNumVertices );
+ aiVector3D &pos = ( m_currentVertices.m_vertices[ idx ] );
+ m_currentMesh->mVertices[ index ].Set( pos.x, pos.y, pos.z );
+ if ( hasNormalCoords ) {
+ aiVector3D &normal = ( m_currentVertices.m_normals[ idx ] );
+ m_currentMesh->mNormals[ index ].Set( normal.x, normal.y, normal.z );
+ }
+ if ( hasTexCoords ) {
+ aiVector3D &tex = ( m_currentVertices.m_textureCoords[ 0 ][ idx ] );
+ m_currentMesh->mTextureCoords[ 0 ][ index ].Set( tex.x, tex.y, tex.z );
+ }
+ current.mIndices[ indices ] = index;
+ index++;
+
+ next = next->m_next;
+ }
+ vaList = vaList->m_next;
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+static void getColorRGB( aiColor3D *pColor, DataArrayList *colList ) {
+ if( nullptr == pColor || nullptr == colList ) {
+ return;
+ }
+
+ ai_assert( 3 == colList->m_numItems );
+ Value *val( colList->m_dataList );
+ pColor->r = val->getFloat();
+ val = val->getNext();
+ pColor->g = val->getFloat();
+ val = val->getNext();
+ pColor->b = val->getFloat();
+}
+
+//------------------------------------------------------------------------------------------------
+enum ColorType {
+ NoneColor = 0,
+ DiffuseColor,
+ SpecularColor,
+ EmissionColor,
+ LightColor
+};
+
+//------------------------------------------------------------------------------------------------
+static ColorType getColorType( Text *id ) {
+ if ( nullptr == id ) {
+ return NoneColor;
+ }
+
+ if( *id == Grammar::DiffuseColorToken ) {
+ return DiffuseColor;
+ } else if( *id == Grammar::SpecularColorToken ) {
+ return SpecularColor;
+ } else if( *id == Grammar::EmissionColorToken ) {
+ return EmissionColor;
+ } else if ( *id == "light" ) {
+ return LightColor;
+ }
+
+ return NoneColor;
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ m_currentMaterial = new aiMaterial;
+ m_materialCache.push_back( m_currentMaterial );
+ m_tokenType = Grammar::MaterialToken;
+ handleNodes( node, pScene );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node ) {
+ return;
+ }
+
+ Property *prop = node->findPropertyByName( "attrib" );
+ if( nullptr != prop ) {
+ if( nullptr != prop->m_value ) {
+ DataArrayList *colList( node->getDataArrayList() );
+ if( nullptr == colList ) {
+ return;
+ }
+ aiColor3D col;
+ getColorRGB( &col, colList );
+ const ColorType colType( getColorType( prop->m_key ) );
+ if( DiffuseColor == colType ) {
+ m_currentMaterial->AddProperty( &col, 1, AI_MATKEY_COLOR_DIFFUSE );
+ } else if( SpecularColor == colType ) {
+ m_currentMaterial->AddProperty( &col, 1, AI_MATKEY_COLOR_SPECULAR );
+ } else if( EmissionColor == colType ) {
+ m_currentMaterial->AddProperty( &col, 1, AI_MATKEY_COLOR_EMISSIVE );
+ } else if ( LightColor == colType ) {
+ m_currentLight->mColorDiffuse = col;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if( nullptr == node ) {
+ return;
+ }
+
+ Property *prop = node->findPropertyByName( "attrib" );
+ if( nullptr != prop ) {
+ if( nullptr != prop->m_value ) {
+ Value *val( node->getValue() );
+ if( nullptr != val ) {
+ aiString tex;
+ tex.Set( val->getString() );
+ if( prop->m_value->getString() == Grammar::DiffuseTextureToken ) {
+ m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
+ } else if( prop->m_value->getString() == Grammar::SpecularPowerTextureToken ) {
+ m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR( 0 ) );
+
+ } else if( prop->m_value->getString() == Grammar::EmissionTextureToken ) {
+ m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE( 0 ) );
+ } else if( prop->m_value->getString() == Grammar::OpacyTextureToken ) {
+ m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_OPACITY( 0 ) );
+ } else if( prop->m_value->getString() == Grammar::TransparencyTextureToken ) {
+ // ToDo!
+ // m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
+ } else if( prop->m_value->getString() == Grammar::NormalTextureToken ) {
+ m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) );
+ } else {
+ ai_assert( false );
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if ( nullptr == node ) {
+ return;
+ }
+
+ Property *prop = node->findPropertyByName( "attrib" );
+ if ( nullptr == prop ) {
+ return;
+ }
+
+ if ( nullptr != prop->m_value ) {
+ Value *val( node->getValue() );
+ if ( nullptr == val ) {
+ return;
+ }
+ const float floatVal( val->getFloat() );
+ if ( prop->m_value != nullptr ) {
+ if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) {
+ m_currentCamera->mHorizontalFOV = floatVal;
+ } else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 3 ) ) {
+ m_currentCamera->mClipPlaneNear = floatVal;
+ } else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) {
+ m_currentCamera->mClipPlaneFar = floatVal;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene *pScene ) {
+ if ( nullptr == node ) {
+ return;
+ }
+
+ Property *prop = node->findPropertyByName( "curve" );
+ if ( nullptr != prop ) {
+ if ( nullptr != prop->m_value ) {
+ Value *val( node->getValue() );
+ const float floatVal( val->getFloat() );
+ if ( 0 == strncmp( "scale", prop->m_value->getString(), strlen( "scale" ) ) ) {
+ m_currentLight->mAttenuationQuadratic = floatVal;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::copyMeshes( aiScene *pScene ) {
+ ai_assert( nullptr != pScene );
+
+ if( m_meshCache.empty() ) {
+ return;
+ }
+
+ pScene->mNumMeshes = m_meshCache.size();
+ pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+ std::copy( m_meshCache.begin(), m_meshCache.end(), pScene->mMeshes );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::copyCameras( aiScene *pScene ) {
+ ai_assert( nullptr != pScene );
+
+ if ( m_cameraCache.empty() ) {
+ return;
+ }
+
+ pScene->mNumCameras = m_cameraCache.size();
+ pScene->mCameras = new aiCamera*[ pScene->mNumCameras ];
+ std::copy( m_cameraCache.begin(), m_cameraCache.end(), pScene->mCameras );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::copyLights( aiScene *pScene ) {
+ ai_assert( nullptr != pScene );
+
+ if ( m_lightCache.empty() ) {
+ return;
+ }
+
+ pScene->mNumLights = m_lightCache.size();
+ pScene->mLights = new aiLight*[ pScene->mNumLights ];
+ std::copy( m_lightCache.begin(), m_lightCache.end(), pScene->mLights );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::resolveReferences() {
+ if( m_unresolvedRefStack.empty() ) {
+ return;
+ }
+
+ RefInfo *currentRefInfo( NULL );
+ for( std::vector<RefInfo*>::iterator it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) {
+ currentRefInfo = *it;
+ if( NULL != currentRefInfo ) {
+ aiNode *node( currentRefInfo->m_node );
+ if( RefInfo::MeshRef == currentRefInfo->m_type ) {
+ for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) {
+ const std::string &name( currentRefInfo->m_Names[ i ] );
+ ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) );
+ if( m_mesh2refMap.end() != it ) {
+ unsigned int meshIdx = m_mesh2refMap[ name ];
+ node->mMeshes[ i ] = meshIdx;
+ }
+ }
+ } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
+ // ToDo!
+ } else {
+ throw DeadlyImportError( "Unknown reference info to resolve." );
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::createNodeTree( aiScene *pScene ) {
+ if( nullptr == m_root ) {
+ return;
+ }
+
+ if( m_root->m_children.empty() ) {
+ return;
+ }
+
+ pScene->mRootNode->mNumChildren = m_root->m_children.size();
+ pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
+ std::copy( m_root->m_children.begin(), m_root->m_children.end(), pScene->mRootNode->mChildren );
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
+ ai_assert( nullptr != pScene );
+
+ if ( NULL == node ) {
+ return;
+ }
+
+ ChildInfo *info( nullptr );
+ if( m_nodeStack.empty() ) {
+ node->mParent = pScene->mRootNode;
+ NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
+ if( m_nodeChildMap.end() == it ) {
+ info = new ChildInfo;
+ m_root = info;
+ m_nodeChildMap[ node->mParent ] = info;
+ } else {
+ info = it->second;
+ }
+ info->m_children.push_back( node );
+ } else {
+ aiNode *parent( m_nodeStack.back() );
+ ai_assert( nullptr != parent );
+ node->mParent = parent;
+ NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
+ if( m_nodeChildMap.end() == it ) {
+ info = new ChildInfo;
+ m_nodeChildMap[ node->mParent ] = info;
+ } else {
+ info = it->second;
+ }
+ info->m_children.push_back( node );
+ }
+ m_nodeStack.push_back( node );
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::popNode() {
+ if( m_nodeStack.empty() ) {
+ return nullptr;
+ }
+
+ aiNode *node( top() );
+ m_nodeStack.pop_back();
+
+ return node;
+}
+
+//------------------------------------------------------------------------------------------------
+aiNode *OpenGEXImporter::top() const {
+ if( m_nodeStack.empty() ) {
+ return nullptr;
+ }
+
+ return m_nodeStack.back();
+}
+
+//------------------------------------------------------------------------------------------------
+void OpenGEXImporter::clearNodeStack() {
+ m_nodeStack.clear();
+}
+
+//------------------------------------------------------------------------------------------------
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER
diff --git a/src/3rdparty/assimp/code/OpenGEXImporter.h b/src/3rdparty/assimp/code/OpenGEXImporter.h
new file mode 100644
index 000000000..d655fb60b
--- /dev/null
+++ b/src/3rdparty/assimp/code/OpenGEXImporter.h
@@ -0,0 +1,209 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEX_IMPORTER_H
+#define AI_OPENGEX_IMPORTER_H
+
+#ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#include "BaseImporter.h"
+#include <assimp/mesh.h>
+
+#include <vector>
+#include <list>
+
+namespace ODDLParser {
+ class DDLNode;
+ struct Context;
+}
+
+struct aiNode;
+struct aiMaterial;
+struct aiCamera;
+struct aiLight;
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct MetricInfo {
+ enum Type {
+ Distance = 0,
+ Angle,
+ Time,
+ Up,
+ Max
+ };
+
+ std::string m_stringValue;
+ float m_floatValue;
+ int m_intValue;
+
+ MetricInfo()
+ : m_stringValue( "" )
+ , m_floatValue( 0.0f )
+ , m_intValue( -1 ) {
+ // empty
+ }
+};
+
+/** @brief This class is used to implement the OpenGEX importer
+ *
+ * See http://opengex.org/OpenGEX.pdf for spec.
+ */
+class OpenGEXImporter : public BaseImporter {
+public:
+ /// The class constructor.
+ OpenGEXImporter();
+
+ /// The class destructor.
+ virtual ~OpenGEXImporter();
+
+ /// BaseImporter override.
+ virtual bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const;
+
+ /// BaseImporter override.
+ virtual void InternReadFile( const std::string &file, aiScene *pScene, IOSystem *pIOHandler );
+
+ /// BaseImporter override.
+ virtual const aiImporterDesc *GetInfo() const;
+
+ /// BaseImporter override.
+ virtual void SetupProperties( const Importer *pImp );
+
+protected:
+ void handleNodes( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleMetricNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleNameNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleObjectRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleGeometryNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleCameraNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleLightNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleGeometryObject( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleCameraObject( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleLightObject( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleMeshNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleParamNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void handleAttenNode( ODDLParser::DDLNode *node, aiScene *pScene );
+ void copyMeshes( aiScene *pScene );
+ void copyCameras( aiScene *pScene );
+ void copyLights( aiScene *pScene );
+
+ void resolveReferences();
+ void pushNode( aiNode *node, aiScene *pScene );
+ aiNode *popNode();
+ aiNode *top() const;
+ void clearNodeStack();
+ void createNodeTree( aiScene *pScene );
+
+private:
+ struct VertexContainer {
+ size_t m_numVerts;
+ aiVector3D *m_vertices;
+ size_t m_numNormals;
+ aiVector3D *m_normals;
+ size_t m_numUVComps[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+ aiVector3D *m_textureCoords[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+
+ VertexContainer();
+ ~VertexContainer();
+
+ private:
+ VertexContainer( const VertexContainer & );
+ VertexContainer &operator = ( const VertexContainer & );
+ };
+
+ struct RefInfo {
+ enum Type {
+ MeshRef,
+ MaterialRef
+ };
+
+ aiNode *m_node;
+ Type m_type;
+ std::vector<std::string> m_Names;
+
+ RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
+ ~RefInfo();
+
+ private:
+ RefInfo( const RefInfo & );
+ RefInfo &operator = ( const RefInfo & );
+ };
+
+ struct ChildInfo {
+ typedef std::list<aiNode*> NodeList;
+ std::list<aiNode*> m_children;
+ };
+ ChildInfo *m_root;
+ typedef std::map<aiNode*, ChildInfo*> NodeChildMap;
+ NodeChildMap m_nodeChildMap;
+
+ std::vector<aiMesh*> m_meshCache;
+ typedef std::map<std::string, size_t> ReferenceMap;
+ std::map<std::string, size_t> m_mesh2refMap;
+
+ ODDLParser::Context *m_ctx;
+ MetricInfo m_metrics[ MetricInfo::Max ];
+ aiNode *m_currentNode;
+ VertexContainer m_currentVertices;
+ aiMesh *m_currentMesh;
+ aiMaterial *m_currentMaterial;
+ aiLight *m_currentLight;
+ aiCamera *m_currentCamera;
+ int m_tokenType;
+ std::vector<aiMaterial*> m_materialCache;
+ std::vector<aiCamera*> m_cameraCache;
+ std::vector<aiLight*> m_lightCache;
+ std::vector<aiNode*> m_nodeStack;
+ std::vector<RefInfo*> m_unresolvedRefStack;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_OPENGEX_IMPORTER
+
+#endif // AI_OPENGEX_IMPORTER_H
diff --git a/src/3rdparty/assimp/code/OpenGEXStructs.h b/src/3rdparty/assimp/code/OpenGEXStructs.h
new file mode 100644
index 000000000..837597975
--- /dev/null
+++ b/src/3rdparty/assimp/code/OpenGEXStructs.h
@@ -0,0 +1,265 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_OPENGEXSTRUCTS_H_INC
+#define AI_OPENGEXSTRUCTS_H_INC
+
+#include <string>
+#include <map>
+
+namespace Assimp {
+namespace OpenGEX {
+
+struct Skin;
+struct Object;
+struct LightObject;
+struct CameraObject;
+struct Material;
+struct BoneNode;
+struct BoneCountArray;
+struct BoneIndexArray;
+struct BoneWeightArray;
+
+struct Metric {
+ float m_distance;
+ float m_angle;
+ float m_time;
+ float m_up;
+};
+
+struct VertexArray {
+ std::string arrayAttrib;
+ unsigned int morphIndex;
+};
+
+struct IndexArray {
+ unsigned int materialIndex;
+ unsigned int restartIndex;
+ std::string frontFace;
+};
+
+struct Mesh {
+ unsigned int meshLevel;
+ std::string meshPrimitive;
+ Skin *skinStructure;
+};
+
+struct Node {
+ std::string nodeName;
+};
+
+struct GeometryNode {
+ bool visibleFlag[ 2 ];
+ bool shadowFlag[ 2 ];
+ bool motionBlurFlag[ 2 ];
+};
+
+struct LightNode {
+ bool shadowFlag[ 2 ];
+ const LightObject *lightObjectStructure;
+};
+
+struct CameraNode {
+ const CameraObject *cameraObjectStructure;
+};
+
+struct GeometryObject {
+ Object *object;
+ bool visibleFlag;
+ bool shadowFlag;
+ bool motionBlurFlag;
+ std::map<std::string, Mesh*> meshMap;
+};
+
+struct LightObject {
+ Object *object;
+ std::string typeString;
+ bool shadowFlag;
+};
+
+
+struct CameraObject {
+ float focalLength;
+ float nearDepth;
+ float farDepth;
+};
+
+struct Matrix {
+ bool objectFlag;
+};
+
+struct Transform {
+ Matrix *matrix;
+ int transformCount;
+ const float *transformArray;
+};
+
+struct Translation {
+ std::string translationKind;
+};
+
+struct Rotation {
+ std::string rotationKind;
+};
+
+struct Scale {
+ std::string scaleKind;
+};
+
+struct Name {
+ std::string name;
+};
+
+
+struct ObjectRef {
+ Object *targetStructure;
+};
+
+struct MaterialRef {
+ unsigned int materialIndex;
+ const Material *targetStructure;
+};
+
+struct BoneRefArray {
+ int boneCount;
+ const BoneNode **boneNodeArray;
+};
+
+struct BoneCount {
+ int vertexCount;
+ const unsigned short *boneCountArray;
+ unsigned short *arrayStorage;
+};
+
+struct BoneIndex {
+ int boneIndexCount;
+ const unsigned short *boneIndexArray;
+ unsigned short *arrayStorage;
+};
+
+
+struct BoneWeight {
+ int boneWeightCount;
+ const float *boneWeightArray;
+};
+
+struct Skeleton {
+ const BoneRefArray *boneRefArrayStructure;
+ const Transform *transformStructure;
+};
+
+struct Skin {
+ const Skeleton *skeletonStructure;
+ const BoneCountArray *boneCountArrayStructure;
+ const BoneIndexArray *boneIndexArrayStructure;
+ const BoneWeightArray *boneWeightArrayStructure;
+};
+
+struct Material {
+ bool twoSidedFlag;
+ const char *materialName;
+};
+
+struct Attrib {
+ std::string attribString;
+};
+
+struct Param {
+ float param;
+};
+
+struct Color {
+ float color[ 4 ];
+};
+
+struct Texture {
+ std::string textureName;
+ unsigned int texcoordIndex;
+};
+
+struct Atten {
+ std::string attenKind;
+ std::string curveType;
+
+ float beginParam;
+ float endParam;
+
+ float scaleParam;
+ float offsetParam;
+
+ float constantParam;
+ float linearParam;
+ float quadraticParam;
+
+ float powerParam;
+};
+
+struct Key {
+ std::string keyKind;
+ bool scalarFlag;
+};
+
+struct Curve {
+ std::string curveType;
+ const Key *keyValueStructure;
+ const Key *keyControlStructure[ 2 ];
+ const Key *keyTensionStructure;
+ const Key *keyContinuityStructure;
+ const Key *keyBiasStructure;
+};
+
+struct Animation {
+ int clipIndex;
+ bool beginFlag;
+ bool endFlag;
+ float beginTime;
+ float endTime;
+};
+
+struct OpenGexDataDescription {
+ float distanceScale;
+ float angleScale;
+ float timeScale;
+ int upDirection;
+};
+
+} // Namespace OpenGEX
+} // Namespace Assimp
+
+#endif // AI_OPENGEXSTRUCTS_H_INC
diff --git a/src/3rdparty/assimp/code/OptimizeGraph.cpp b/src/3rdparty/assimp/code/OptimizeGraph.cpp
index 2d825c42e..ec37bd447 100644
--- a/src/3rdparty/assimp/code/OptimizeGraph.cpp
+++ b/src/3rdparty/assimp/code/OptimizeGraph.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,13 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the aiProcess_OptimizGraph step
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
-using namespace Assimp;
#include "OptimizeGraph.h"
#include "ProcessHelper.h"
#include "SceneCombiner.h"
+#include "Exceptional.h"
+#include <stdio.h>
+
+using namespace Assimp;
#define AI_RESERVED_NODE_NAME "$Reserved_And_Evil"
@@ -57,17 +60,21 @@ using namespace Assimp;
* The unhashed variant should be faster, except for *very* large data sets
*/
#ifdef AI_OG_USE_HASHING
- // Use our standard hashing function to compute the hash
-# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length)
+ // Use our standard hashing function to compute the hash
+# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length)
#else
- // Otherwise hope that std::string will utilize a static buffer
- // for shorter node names. This would avoid endless heap copying.
-# define AI_OG_GETKEY(str) std::string(str.data)
+ // Otherwise hope that std::string will utilize a static buffer
+ // for shorter node names. This would avoid endless heap copying.
+# define AI_OG_GETKEY(str) std::string(str.data)
#endif
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OptimizeGraphProcess::OptimizeGraphProcess()
+ : mScene()
+ , nodes_in()
+ , nodes_out()
+ , count_merged()
{}
// ------------------------------------------------------------------------------------------------
@@ -79,274 +86,274 @@ OptimizeGraphProcess::~OptimizeGraphProcess()
// Returns whether the processing step is present in the given flag field.
bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const
{
- return (0 != (pFlags & aiProcess_OptimizeGraph));
+ return (0 != (pFlags & aiProcess_OptimizeGraph));
}
// ------------------------------------------------------------------------------------------------
// Setup properties for the postprocessing step
void OptimizeGraphProcess::SetupProperties(const Importer* pImp)
-{
- // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST
- std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,"");
- AddLockedNodeList(tmp);
+{
+ // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST
+ std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,"");
+ AddLockedNodeList(tmp);
}
// ------------------------------------------------------------------------------------------------
// Collect new children
void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes)
{
- nodes_in += nd->mNumChildren;
-
- // Process children
- std::list<aiNode*> child_nodes;
- for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
-
- CollectNewChildren(nd->mChildren[i],child_nodes);
- nd->mChildren[i] = NULL;
- }
-
- // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest).
- if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) {
- for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
-
- if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) {
- (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation;
- nodes.push_back(*it);
-
- it = child_nodes.erase(it);
- continue;
- }
- ++it;
- }
-
- if (nd->mNumMeshes || child_nodes.size()) {
- nodes.push_back(nd);
- }
- else {
- delete nd; /* bye, node */
- return;
- }
- }
- else {
-
- // Retain our current position in the hierarchy
- nodes.push_back(nd);
-
- // Now check for possible optimizations in our list of child nodes. join as many as possible
- aiNode* join_master = NULL;
- aiMatrix4x4 inv;
-
- const LockedSetType::const_iterator end = locked.end();
-
- std::list<aiNode*> join;
- for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
- aiNode* child = *it;
- if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) {
-
- // There may be no instanced meshes
- unsigned int n = 0;
- for (; n < child->mNumMeshes;++n) {
- if (meshes[child->mMeshes[n]] > 1) {
- break;
- }
- }
- if (n == child->mNumMeshes) {
-
- if (!join_master) {
- join_master = child;
- inv = join_master->mTransformation;
- inv.Inverse();
- }
- else {
-
- child->mTransformation = inv * child->mTransformation ;
-
- join.push_back(child);
- it = child_nodes.erase(it);
- continue;
- }
- }
- }
- ++it;
- }
- if (join_master && join.size()) {
- join_master->mName.length = sprintf(join_master->mName.data,"$MergedNode_%i",count_merged++);
-
- unsigned int out_meshes = 0;
- for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
- out_meshes += (*it)->mNumMeshes;
- }
-
- // copy all mesh references in one array
- if (out_meshes) {
- unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes;
- for (unsigned int n = 0; n < join_master->mNumMeshes;++n) {
- *tmp++ = join_master->mMeshes[n];
- }
-
- for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
- for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
-
- *tmp = (*it)->mMeshes[n];
- aiMesh* mesh = mScene->mMeshes[*tmp++];
-
- // manually move the mesh into the right coordinate system
- const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose();
- for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
-
- mesh->mVertices[a] *= (*it)->mTransformation;
-
- if (mesh->HasNormals())
- mesh->mNormals[a] *= IT;
-
- if (mesh->HasTangentsAndBitangents()) {
- mesh->mTangents[a] *= IT;
- mesh->mBitangents[a] *= IT;
- }
- }
- }
- delete *it; // bye, node
- }
- delete[] join_master->mMeshes;
- join_master->mMeshes = meshes;
- join_master->mNumMeshes += out_meshes;
- }
- }
- }
- // reassign children if something changed
- if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) {
-
- delete[] nd->mChildren;
-
- if (child_nodes.size())
- nd->mChildren = new aiNode*[child_nodes.size()];
- else nd->mChildren = NULL;
- }
-
- nd->mNumChildren = child_nodes.size();
-
- aiNode** tmp = nd->mChildren;
- for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
- aiNode* node = *tmp++ = *it;
- node->mParent = nd;
- }
-
- nodes_out += child_nodes.size();
+ nodes_in += nd->mNumChildren;
+
+ // Process children
+ std::list<aiNode*> child_nodes;
+ for (unsigned int i = 0; i < nd->mNumChildren; ++i) {
+
+ CollectNewChildren(nd->mChildren[i],child_nodes);
+ nd->mChildren[i] = NULL;
+ }
+
+ // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest).
+ if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) {
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
+
+ if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) {
+ (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation;
+ nodes.push_back(*it);
+
+ it = child_nodes.erase(it);
+ continue;
+ }
+ ++it;
+ }
+
+ if (nd->mNumMeshes || !child_nodes.empty()) {
+ nodes.push_back(nd);
+ }
+ else {
+ delete nd; /* bye, node */
+ return;
+ }
+ }
+ else {
+
+ // Retain our current position in the hierarchy
+ nodes.push_back(nd);
+
+ // Now check for possible optimizations in our list of child nodes. join as many as possible
+ aiNode* join_master = NULL;
+ aiMatrix4x4 inv;
+
+ const LockedSetType::const_iterator end = locked.end();
+
+ std::list<aiNode*> join;
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) {
+ aiNode* child = *it;
+ if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) {
+
+ // There may be no instanced meshes
+ unsigned int n = 0;
+ for (; n < child->mNumMeshes;++n) {
+ if (meshes[child->mMeshes[n]] > 1) {
+ break;
+ }
+ }
+ if (n == child->mNumMeshes) {
+
+ if (!join_master) {
+ join_master = child;
+ inv = join_master->mTransformation;
+ inv.Inverse();
+ }
+ else {
+
+ child->mTransformation = inv * child->mTransformation ;
+
+ join.push_back(child);
+ it = child_nodes.erase(it);
+ continue;
+ }
+ }
+ }
+ ++it;
+ }
+ if (join_master && !join.empty()) {
+ join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i",count_merged++);
+
+ unsigned int out_meshes = 0;
+ for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
+ out_meshes += (*it)->mNumMeshes;
+ }
+
+ // copy all mesh references in one array
+ if (out_meshes) {
+ unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes;
+ for (unsigned int n = 0; n < join_master->mNumMeshes;++n) {
+ *tmp++ = join_master->mMeshes[n];
+ }
+
+ for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) {
+ for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) {
+
+ *tmp = (*it)->mMeshes[n];
+ aiMesh* mesh = mScene->mMeshes[*tmp++];
+
+ // manually move the mesh into the right coordinate system
+ const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose();
+ for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
+
+ mesh->mVertices[a] *= (*it)->mTransformation;
+
+ if (mesh->HasNormals())
+ mesh->mNormals[a] *= IT;
+
+ if (mesh->HasTangentsAndBitangents()) {
+ mesh->mTangents[a] *= IT;
+ mesh->mBitangents[a] *= IT;
+ }
+ }
+ }
+ delete *it; // bye, node
+ }
+ delete[] join_master->mMeshes;
+ join_master->mMeshes = meshes;
+ join_master->mNumMeshes += out_meshes;
+ }
+ }
+ }
+ // reassign children if something changed
+ if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) {
+
+ delete[] nd->mChildren;
+
+ if (!child_nodes.empty())
+ nd->mChildren = new aiNode*[child_nodes.size()];
+ else nd->mChildren = NULL;
+ }
+
+ nd->mNumChildren = child_nodes.size();
+
+ aiNode** tmp = nd->mChildren;
+ for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
+ aiNode* node = *tmp++ = *it;
+ node->mParent = nd;
+ }
+
+ nodes_out += child_nodes.size();
}
// ------------------------------------------------------------------------------------------------
// Execute the postprocessing step on the given scene
void OptimizeGraphProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("OptimizeGraphProcess begin");
- nodes_in = nodes_out = count_merged = 0;
- mScene = pScene;
+ DefaultLogger::get()->debug("OptimizeGraphProcess begin");
+ nodes_in = nodes_out = count_merged = 0;
+ mScene = pScene;
- meshes.resize(pScene->mNumMeshes,0);
- FindInstancedMeshes(pScene->mRootNode);
+ meshes.resize(pScene->mNumMeshes,0);
+ FindInstancedMeshes(pScene->mRootNode);
- // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it
- locked.clear();
- for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) {
+ // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it
+ locked.clear();
+ for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) {
#ifdef AI_OG_USE_HASHING
- locked.insert(SuperFastHash((*it).c_str()));
+ locked.insert(SuperFastHash((*it).c_str()));
#else
- locked.insert(*it);
+ locked.insert(*it);
#endif
- }
-
- for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
- for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) {
-
- aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a];
- locked.insert(AI_OG_GETKEY(anim->mNodeName));
- }
- }
-
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) {
-
- aiBone* bone = pScene->mMeshes[i]->mBones[a];
- locked.insert(AI_OG_GETKEY(bone->mName));
-
- // HACK: Meshes referencing bones may not be transformed; we need to look them.
- // The easiest way to do this is to increase their reference counters ...
- meshes[i] += 2;
- }
- }
-
- for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
- aiCamera* cam = pScene->mCameras[i];
- locked.insert(AI_OG_GETKEY(cam->mName));
- }
-
- for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
- aiLight* lgh = pScene->mLights[i];
- locked.insert(AI_OG_GETKEY(lgh->mName));
- }
-
- // Insert a dummy master node and make it read-only
- aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME);
- locked.insert(AI_OG_GETKEY(dummy_root->mName));
-
- const aiString prev = pScene->mRootNode->mName;
- pScene->mRootNode->mParent = dummy_root;
-
- dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1];
- dummy_root->mChildren[0] = pScene->mRootNode;
-
- // Do our recursive processing of scenegraph nodes. For each node collect
- // a fully new list of children and allow their children to place themselves
- // on the same hierarchy layer as their parents.
- std::list<aiNode*> nodes;
- CollectNewChildren (dummy_root,nodes);
-
- ai_assert(nodes.size() == 1);
-
- if (dummy_root->mNumChildren == 0) {
- pScene->mRootNode = NULL;
- throw DeadlyImportError("After optimizing the scene graph, no data remains");
- }
-
- if (dummy_root->mNumChildren > 1) {
- pScene->mRootNode = dummy_root;
-
- // Keep the dummy node but assign the name of the old root node to it
- pScene->mRootNode->mName = prev;
- }
- else {
-
- // Remove the dummy root node again.
- pScene->mRootNode = dummy_root->mChildren[0];
-
- dummy_root->mChildren[0] = NULL;
- delete dummy_root;
- }
-
- pScene->mRootNode->mParent = NULL;
- if (!DefaultLogger::isNullLogger()) {
- if ( nodes_in != nodes_out) {
-
- char buf[512];
- sprintf(buf,"OptimizeGraphProcess finished; Input nodes: %i, Output nodes: %i",nodes_in,nodes_out);
- DefaultLogger::get()->info(buf);
- }
- else DefaultLogger::get()->debug("OptimizeGraphProcess finished");
- }
- meshes.clear();
- locked.clear();
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
+ for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) {
+
+ aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a];
+ locked.insert(AI_OG_GETKEY(anim->mNodeName));
+ }
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) {
+
+ aiBone* bone = pScene->mMeshes[i]->mBones[a];
+ locked.insert(AI_OG_GETKEY(bone->mName));
+
+ // HACK: Meshes referencing bones may not be transformed; we need to look them.
+ // The easiest way to do this is to increase their reference counters ...
+ meshes[i] += 2;
+ }
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
+ aiCamera* cam = pScene->mCameras[i];
+ locked.insert(AI_OG_GETKEY(cam->mName));
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
+ aiLight* lgh = pScene->mLights[i];
+ locked.insert(AI_OG_GETKEY(lgh->mName));
+ }
+
+ // Insert a dummy master node and make it read-only
+ aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME);
+ locked.insert(AI_OG_GETKEY(dummy_root->mName));
+
+ const aiString prev = pScene->mRootNode->mName;
+ pScene->mRootNode->mParent = dummy_root;
+
+ dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1];
+ dummy_root->mChildren[0] = pScene->mRootNode;
+
+ // Do our recursive processing of scenegraph nodes. For each node collect
+ // a fully new list of children and allow their children to place themselves
+ // on the same hierarchy layer as their parents.
+ std::list<aiNode*> nodes;
+ CollectNewChildren (dummy_root,nodes);
+
+ ai_assert(nodes.size() == 1);
+
+ if (dummy_root->mNumChildren == 0) {
+ pScene->mRootNode = NULL;
+ throw DeadlyImportError("After optimizing the scene graph, no data remains");
+ }
+
+ if (dummy_root->mNumChildren > 1) {
+ pScene->mRootNode = dummy_root;
+
+ // Keep the dummy node but assign the name of the old root node to it
+ pScene->mRootNode->mName = prev;
+ }
+ else {
+
+ // Remove the dummy root node again.
+ pScene->mRootNode = dummy_root->mChildren[0];
+
+ dummy_root->mChildren[0] = NULL;
+ delete dummy_root;
+ }
+
+ pScene->mRootNode->mParent = NULL;
+ if (!DefaultLogger::isNullLogger()) {
+ if ( nodes_in != nodes_out) {
+
+ char buf[512];
+ ::ai_snprintf(buf,512,"OptimizeGraphProcess finished; Input nodes: %u, Output nodes: %u",nodes_in,nodes_out);
+ DefaultLogger::get()->info(buf);
+ }
+ else DefaultLogger::get()->debug("OptimizeGraphProcess finished");
+ }
+ meshes.clear();
+ locked.clear();
}
// ------------------------------------------------------------------------------------------------
// Buidl a LUT of all instanced meshes
void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode)
{
- for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
- ++meshes[pNode->mMeshes[i]];
- }
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
+ ++meshes[pNode->mMeshes[i]];
+ }
- for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
- FindInstancedMeshes(pNode->mChildren[i]);
+ for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
+ FindInstancedMeshes(pNode->mChildren[i]);
}
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
diff --git a/src/3rdparty/assimp/code/OptimizeGraph.h b/src/3rdparty/assimp/code/OptimizeGraph.h
index 949166c2b..7b3a1d0de 100644
--- a/src/3rdparty/assimp/code/OptimizeGraph.h
+++ b/src/3rdparty/assimp/code/OptimizeGraph.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,17 +46,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseProcess.h"
#include "ProcessHelper.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+#include <set>
struct aiMesh;
class OptimizeGraphProcessTest;
-namespace Assimp {
+namespace Assimp {
// -----------------------------------------------------------------------------
/** @brief Postprocessing step to optimize the scenegraph
*
* The implementation tries to merge nodes, even if they use different
- * transformations. Animations are preserved.
+ * transformations. Animations are preserved.
*
* @see aiProcess_OptimizeGraph for a detailed description of the
* algorithm being applied.
@@ -65,76 +66,76 @@ class OptimizeGraphProcess : public BaseProcess
{
public:
- OptimizeGraphProcess();
- ~OptimizeGraphProcess();
+ OptimizeGraphProcess();
+ ~OptimizeGraphProcess();
public:
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
-
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
-
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
-
-
- // -------------------------------------------------------------------
- /** @brief Add a list of node names to be locked and not modified.
- * @param in List of nodes. See #AI_CONFIG_PP_OG_EXCLUDE_LIST for
- * format explanations.
- */
- inline void AddLockedNodeList(std::string& in)
- {
- ConvertListToStrings (in,locked_nodes);
- }
-
- // -------------------------------------------------------------------
- /** @brief Add another node to be locked and not modified.
- * @param name Name to be locked
- */
- inline void AddLockedNode(std::string& name)
- {
- locked_nodes.push_back(name);
- }
-
- // -------------------------------------------------------------------
- /** @brief Rmeove a node from the list of locked nodes.
- * @param name Name to be unlocked
- */
- inline void RemoveLockedNode(std::string& name)
- {
- locked_nodes.remove(name);
- }
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Add a list of node names to be locked and not modified.
+ * @param in List of nodes. See #AI_CONFIG_PP_OG_EXCLUDE_LIST for
+ * format explanations.
+ */
+ inline void AddLockedNodeList(std::string& in)
+ {
+ ConvertListToStrings (in,locked_nodes);
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Add another node to be locked and not modified.
+ * @param name Name to be locked
+ */
+ inline void AddLockedNode(std::string& name)
+ {
+ locked_nodes.push_back(name);
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Rmeove a node from the list of locked nodes.
+ * @param name Name to be unlocked
+ */
+ inline void RemoveLockedNode(std::string& name)
+ {
+ locked_nodes.remove(name);
+ }
protected:
- void CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes);
- void FindInstancedMeshes (aiNode* pNode);
+ void CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes);
+ void FindInstancedMeshes (aiNode* pNode);
private:
#ifdef AI_OG_USE_HASHING
- typedef std::set<unsigned int> LockedSetType;
+ typedef std::set<unsigned int> LockedSetType;
#else
- typedef std::set<std::string> LockedSetType;
+ typedef std::set<std::string> LockedSetType;
#endif
- //! Scene we're working with
- aiScene* mScene;
+ //! Scene we're working with
+ aiScene* mScene;
- //! List of locked names. Stored is the hash of the name
- LockedSetType locked;
+ //! List of locked names. Stored is the hash of the name
+ LockedSetType locked;
- //! List of nodes to be locked in addition to those with animations, lights or cameras assigned.
- std::list<std::string> locked_nodes;
+ //! List of nodes to be locked in addition to those with animations, lights or cameras assigned.
+ std::list<std::string> locked_nodes;
- //! Node counters for logging purposes
- unsigned int nodes_in,nodes_out, count_merged;
+ //! Node counters for logging purposes
+ unsigned int nodes_in,nodes_out, count_merged;
- //! Reference counters for meshes
- std::vector<unsigned int> meshes;
+ //! Reference counters for meshes
+ std::vector<unsigned int> meshes;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/OptimizeMeshes.cpp b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
index 85961de0a..8d830bb9b 100644
--- a/src/3rdparty/assimp/code/OptimizeMeshes.cpp
+++ b/src/3rdparty/assimp/code/OptimizeMeshes.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,201 +43,217 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the aiProcess_OptimizeMeshes step
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
-using namespace Assimp;
+
#include "OptimizeMeshes.h"
#include "ProcessHelper.h"
#include "SceneCombiner.h"
+#include "Exceptional.h"
+
+using namespace Assimp;
+
+static const unsigned int NotSet = 0xffffffff;
+static const unsigned int DeadBeef = 0xdeadbeef;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OptimizeMeshesProcess::OptimizeMeshesProcess()
-: pts (false)
-, max_verts (0xffffffff)
-, max_faces (0xffffffff)
-{}
+ : mScene()
+ , pts(false)
+ , max_verts( NotSet )
+ , max_faces( NotSet ) {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
-OptimizeMeshesProcess::~OptimizeMeshesProcess()
-{}
+OptimizeMeshesProcess::~OptimizeMeshesProcess() {
+ // empty
+}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool OptimizeMeshesProcess::IsActive( unsigned int pFlags) const
{
- // Our behaviour needs to be different if the SortByPType or SplitLargeMeshes
- // steps are active. Thus we need to query their flags here and store the
- // information, although we're breaking const-correctness.
- // That's a serious design flaw, consider redesign.
- if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
- pts = (0 != (pFlags & aiProcess_SortByPType));
- max_verts = (0 != (pFlags & aiProcess_SplitLargeMeshes)) ? 0xdeadbeef : max_verts;
- return true;
- }
- return false;
+ // Our behaviour needs to be different if the SortByPType or SplitLargeMeshes
+ // steps are active. Thus we need to query their flags here and store the
+ // information, although we're breaking const-correctness.
+ // That's a serious design flaw, consider redesign.
+ if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
+ pts = (0 != (pFlags & aiProcess_SortByPType));
+ max_verts = ( 0 != ( pFlags & aiProcess_SplitLargeMeshes ) ) ? DeadBeef : max_verts;
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
-// Setup properties for the postprocessing step
+// Setup properties for the post-processing step
void OptimizeMeshesProcess::SetupProperties(const Importer* pImp)
{
- if (max_verts == 0xdeadbeef /* magic hack */) {
- max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
- max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
- }
+ if( max_verts == DeadBeef /* magic hack */ ) {
+ max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
+ max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
+ }
}
// ------------------------------------------------------------------------------------------------
// Execute step
void OptimizeMeshesProcess::Execute( aiScene* pScene)
{
- const unsigned int num_old = pScene->mNumMeshes;
- if (num_old <= 1) {
- DefaultLogger::get()->debug("Skipping OptimizeMeshesProcess");
- return;
- }
-
- DefaultLogger::get()->debug("OptimizeMeshesProcess begin");
- mScene = pScene;
-
- // need to clear persistent members from previous runs
- merge_list.clear();
- output.clear();
-
- merge_list.reserve(pScene->mNumMeshes);
- output.reserve(pScene->mNumMeshes);
-
- // Prepare lookup tables
- meshes.resize(pScene->mNumMeshes);
- FindInstancedMeshes(pScene->mRootNode);
- if (max_verts == 0xdeadbeef) /* undo the magic hack */
- max_verts = 0xffffffff;
-
- // ... instanced meshes are immediately processed and added to the output list
- for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) {
- meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]);
-
- if (meshes[i].instance_cnt > 1 && meshes[i].output_id == 0xffffffff) {
- meshes[i].output_id = n++;
- output.push_back(mScene->mMeshes[i]);
- }
- }
-
- // and process all nodes in the scenegraoh recursively
- ProcessNode(pScene->mRootNode);
- if (!output.size()) {
- throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
- }
-
- meshes.clear();
- ai_assert(output.size() <= num_old);
-
- mScene->mNumMeshes = output.size();
- std::copy(output.begin(),output.end(),mScene->mMeshes);
-
- if (output.size() != num_old) {
- char tmp[512];
- ::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes);
- DefaultLogger::get()->info(tmp);
- }
- else DefaultLogger::get()->debug("OptimizeMeshesProcess finished");
+ const unsigned int num_old = pScene->mNumMeshes;
+ if (num_old <= 1) {
+ DefaultLogger::get()->debug("Skipping OptimizeMeshesProcess");
+ return;
+ }
+
+ DefaultLogger::get()->debug("OptimizeMeshesProcess begin");
+ mScene = pScene;
+
+ // need to clear persistent members from previous runs
+ merge_list.resize( 0 );
+ output.resize( 0 );
+
+ // ensure we have the right sizes
+ merge_list.reserve(pScene->mNumMeshes);
+ output.reserve(pScene->mNumMeshes);
+
+ // Prepare lookup tables
+ meshes.resize(pScene->mNumMeshes);
+ FindInstancedMeshes(pScene->mRootNode);
+ if( max_verts == DeadBeef ) /* undo the magic hack */
+ max_verts = NotSet;
+
+ // ... instanced meshes are immediately processed and added to the output list
+ for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) {
+ meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]);
+
+ if (meshes[i].instance_cnt > 1 && meshes[i].output_id == NotSet ) {
+ meshes[i].output_id = n++;
+ output.push_back(mScene->mMeshes[i]);
+ }
+ }
+
+ // and process all nodes in the scenegraph recursively
+ ProcessNode(pScene->mRootNode);
+ if (!output.size()) {
+ throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
+ }
+
+ meshes.resize( 0 );
+ ai_assert(output.size() <= num_old);
+
+ mScene->mNumMeshes = output.size();
+ std::copy(output.begin(),output.end(),mScene->mMeshes);
+
+ if (output.size() != num_old) {
+ char tmp[512];
+ ::ai_snprintf(tmp,512,"OptimizeMeshesProcess finished. Input meshes: %u, Output meshes: %u",num_old,pScene->mNumMeshes);
+ DefaultLogger::get()->info(tmp);
+ } else {
+ DefaultLogger::get()->debug( "OptimizeMeshesProcess finished" );
+ }
}
// ------------------------------------------------------------------------------------------------
// Process meshes for a single node
void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
{
- for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
- unsigned int& im = pNode->mMeshes[i];
-
- if (meshes[im].instance_cnt > 1) {
- im = meshes[im].output_id;
- }
- else {
- merge_list.clear();
- unsigned int verts = 0, faces = 0;
-
- // Find meshes to merge with us
- for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) {
- unsigned int am = pNode->mMeshes[a];
- if (meshes[am].instance_cnt == 1 && CanJoin(im,am,verts,faces)) {
-
- merge_list.push_back(mScene->mMeshes[am]);
- verts += mScene->mMeshes[am]->mNumVertices;
- faces += mScene->mMeshes[am]->mNumFaces;
-
- --pNode->mNumMeshes;
- for (unsigned int n = a; n < pNode->mNumMeshes; ++n)
- pNode->mMeshes[n] = pNode->mMeshes[n+1];
-
- --a;
- }
- }
-
- // and merge all meshes which we found, replace the old ones
- if (!merge_list.empty()) {
- merge_list.push_back(mScene->mMeshes[im]);
-
- aiMesh* out;
- SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
- output.push_back(out);
- }
- else {
- output.push_back(mScene->mMeshes[im]);
- }
- im = output.size()-1;
- }
- }
-
-
- for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
- ProcessNode(pNode->mChildren[i]);
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i) {
+ unsigned int& im = pNode->mMeshes[i];
+
+ if (meshes[im].instance_cnt > 1) {
+ im = meshes[im].output_id;
+ }
+ else {
+ merge_list.resize( 0 );
+ unsigned int verts = 0, faces = 0;
+
+ // Find meshes to merge with us
+ for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) {
+ unsigned int am = pNode->mMeshes[a];
+ if (meshes[am].instance_cnt == 1 && CanJoin(im,am,verts,faces)) {
+
+ merge_list.push_back(mScene->mMeshes[am]);
+ verts += mScene->mMeshes[am]->mNumVertices;
+ faces += mScene->mMeshes[am]->mNumFaces;
+
+ --pNode->mNumMeshes;
+ for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
+ pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
+ }
+
+ --a;
+ }
+ }
+
+ // and merge all meshes which we found, replace the old ones
+ if (!merge_list.empty()) {
+ merge_list.push_back(mScene->mMeshes[im]);
+
+ aiMesh* out;
+ SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
+ output.push_back(out);
+ } else {
+ output.push_back(mScene->mMeshes[im]);
+ }
+ im = output.size()-1;
+ }
+ }
+
+
+ for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
+ ProcessNode( pNode->mChildren[ i ] );
+ }
}
// ------------------------------------------------------------------------------------------------
// Check whether two meshes can be joined
bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned int verts, unsigned int faces )
{
- if (meshes[a].vertex_format != meshes[b].vertex_format)
- return false;
-
- aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b];
-
- if ((0xffffffff != max_verts && verts+mb->mNumVertices > max_verts) ||
- (0xffffffff != max_faces && faces+mb->mNumFaces > max_faces)) {
- return false;
- }
-
- // Never merge unskinned meshes with skinned meshes
- if (ma->mMaterialIndex != mb->mMaterialIndex || ma->HasBones() != mb->HasBones())
- return false;
-
- // Never merge meshes with different kinds of primitives if SortByPType did already
- // do its work. We would destroy everything again ...
- if (pts && ma->mPrimitiveTypes != mb->mPrimitiveTypes)
- return false;
-
- // If both meshes are skinned, check whether we have many bones defined in both meshes.
- // If yes, we can savely join them.
- if (ma->HasBones()) {
- // TODO
- return false;
- }
- return true;
+ if (meshes[a].vertex_format != meshes[b].vertex_format)
+ return false;
+
+ aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b];
+
+ if ((NotSet != max_verts && verts+mb->mNumVertices > max_verts) ||
+ (NotSet != max_faces && faces+mb->mNumFaces > max_faces)) {
+ return false;
+ }
+
+ // Never merge unskinned meshes with skinned meshes
+ if (ma->mMaterialIndex != mb->mMaterialIndex || ma->HasBones() != mb->HasBones())
+ return false;
+
+ // Never merge meshes with different kinds of primitives if SortByPType did already
+ // do its work. We would destroy everything again ...
+ if (pts && ma->mPrimitiveTypes != mb->mPrimitiveTypes)
+ return false;
+
+ // If both meshes are skinned, check whether we have many bones defined in both meshes.
+ // If yes, we can join them.
+ if (ma->HasBones()) {
+ // TODO
+ return false;
+ }
+ return true;
}
// ------------------------------------------------------------------------------------------------
-// Buidl a LUT of all instanced meshes
+// Build a LUT of all instanced meshes
void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode)
{
- for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
- ++meshes[pNode->mMeshes[i]].instance_cnt;
+ for( unsigned int i = 0; i < pNode->mNumMeshes; ++i ) {
+ ++meshes[ pNode->mMeshes[ i ] ].instance_cnt;
+ }
- for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
- FindInstancedMeshes(pNode->mChildren[i]);
+ for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
+ FindInstancedMeshes( pNode->mChildren[ i ] );
+ }
}
+// ------------------------------------------------------------------------------------------------
+
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
diff --git a/src/3rdparty/assimp/code/OptimizeMeshes.h b/src/3rdparty/assimp/code/OptimizeMeshes.h
index 2b4d3c5cd..fc8b6a10b 100644
--- a/src/3rdparty/assimp/code/OptimizeMeshes.h
+++ b/src/3rdparty/assimp/code/OptimizeMeshes.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,33 +23,36 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file OptimizeMeshes.h
- * @brief Declares a post processing step to join meshes, if possible
+ * @brief Declares a post processing step to join meshes, if possible
*/
#ifndef AI_OPTIMIZEMESHESPROCESS_H_INC
#define AI_OPTIMIZEMESHESPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+#include <vector>
struct aiMesh;
+struct aiNode;
class OptimizeMeshesProcessTest;
-namespace Assimp {
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** @brief Postprocessing step to optimize mesh usage
@@ -63,118 +66,115 @@ class OptimizeMeshesProcess : public BaseProcess
{
public:
- OptimizeMeshesProcess();
- ~OptimizeMeshesProcess();
+ OptimizeMeshesProcess();
+ ~OptimizeMeshesProcess();
- /** @brief Internal utility to store additional mesh info
- */
- struct MeshInfo
- {
- MeshInfo()
- : instance_cnt (0)
- , vertex_format (0)
- , output_id (0xffffffff)
- {}
+ /** @brief Internal utility to store additional mesh info
+ */
+ struct MeshInfo
+ {
+ MeshInfo()
+ : instance_cnt (0)
+ , vertex_format (0)
+ , output_id (0xffffffff)
+ {}
- //! Number of times this mesh is referenced
- unsigned int instance_cnt;
+ //! Number of times this mesh is referenced
+ unsigned int instance_cnt;
- //! Vertex format id
- unsigned int vertex_format;
+ //! Vertex format id
+ unsigned int vertex_format;
- //! Output ID
- unsigned int output_id;
- };
+ //! Output ID
+ unsigned int output_id;
+ };
public:
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
-
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
-
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
-
-
- // -------------------------------------------------------------------
- /** @brief Specify whether you want meshes with different
- * primitive types to be merged as well.
- *
- * IsActive() sets this property automatically to true if the
- * aiProcess_SortByPType flag is found.
- */
- void EnablePrimitiveTypeSorting(bool enable) {
- pts = enable;
- }
-
- // Getter
- bool IsPrimitiveTypeSortingEnabled () const {
- return pts;
- }
-
-
- // -------------------------------------------------------------------
- /** @brief Specify a maximum size of a single output mesh.
- *
- * If a single input mesh already exceeds this limit, it won't
- * be split.
- * @param verts Maximum number of vertices per mesh
- * @param faces Maximum number of faces per mesh
- */
- void SetPreferredMeshSizeLimit (unsigned int verts, unsigned int faces)
- {
- max_verts = verts;
- max_faces = faces;
- }
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Specify whether you want meshes with different
+ * primitive types to be merged as well.
+ *
+ * IsActive() sets this property automatically to true if the
+ * aiProcess_SortByPType flag is found.
+ */
+ void EnablePrimitiveTypeSorting(bool enable) {
+ pts = enable;
+ }
+
+ // Getter
+ bool IsPrimitiveTypeSortingEnabled () const {
+ return pts;
+ }
+
+
+ // -------------------------------------------------------------------
+ /** @brief Specify a maximum size of a single output mesh.
+ *
+ * If a single input mesh already exceeds this limit, it won't
+ * be split.
+ * @param verts Maximum number of vertices per mesh
+ * @param faces Maximum number of faces per mesh
+ */
+ void SetPreferredMeshSizeLimit (unsigned int verts, unsigned int faces)
+ {
+ max_verts = verts;
+ max_faces = faces;
+ }
protected:
- // -------------------------------------------------------------------
- /** @brief Do the actual optimization on all meshes of this node
- * @param pNode Node we're working with
- */
- void ProcessNode( aiNode* pNode);
-
- // -------------------------------------------------------------------
- /** @brief Returns true if b can be joined with a
- *
- * @param verts Number of output verts up to now
- * @param faces Number of output faces up to now
- */
- bool CanJoin ( unsigned int a, unsigned int b,
- unsigned int verts, unsigned int faces );
-
- // -------------------------------------------------------------------
- /** @brief Find instanced meshes, for the moment we're excluding
- * them from all optimizations
- */
- void FindInstancedMeshes (aiNode* pNode);
+ // -------------------------------------------------------------------
+ /** @brief Do the actual optimization on all meshes of this node
+ * @param pNode Node we're working with
+ */
+ void ProcessNode( aiNode* pNode);
+
+ // -------------------------------------------------------------------
+ /** @brief Returns true if b can be joined with a
+ *
+ * @param verts Number of output verts up to now
+ * @param faces Number of output faces up to now
+ */
+ bool CanJoin ( unsigned int a, unsigned int b,
+ unsigned int verts, unsigned int faces );
+
+ // -------------------------------------------------------------------
+ /** @brief Find instanced meshes, for the moment we're excluding
+ * them from all optimizations
+ */
+ void FindInstancedMeshes (aiNode* pNode);
private:
- //! Scene we're working with
- aiScene* mScene;
-
- //! Per mesh info
- std::vector<MeshInfo> meshes;
+ //! Scene we're working with
+ aiScene* mScene;
- //! Next output mesh
- aiMesh* mesh;
+ //! Per mesh info
+ std::vector<MeshInfo> meshes;
- //! Output meshes
- std::vector<aiMesh*> output;
+ //! Output meshes
+ std::vector<aiMesh*> output;
- //! @see EnablePrimitiveTypeSorting
- mutable bool pts;
+ //! @see EnablePrimitiveTypeSorting
+ mutable bool pts;
- //! @see SetPreferredMeshSizeLimit
- mutable unsigned int max_verts,max_faces;
+ //! @see SetPreferredMeshSizeLimit
+ mutable unsigned int max_verts,max_faces;
- //! Temporary storage
- std::vector<aiMesh*> merge_list;
+ //! Temporary storage
+ std::vector<aiMesh*> merge_list;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ParsingUtils.h b/src/3rdparty/assimp/code/ParsingUtils.h
index 0c34e70ca..2371ee606 100644
--- a/src/3rdparty/assimp/code/ParsingUtils.h
+++ b/src/3rdparty/assimp/code/ParsingUtils.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,142 +40,179 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file ParsingUtils.h
- * @brief Defines helper functions for text parsing
+ * @brief Defines helper functions for text parsing
*/
#ifndef AI_PARSING_UTILS_H_INC
#define AI_PARSING_UTILS_H_INC
#include "StringComparison.h"
+#include "StringUtils.h"
+#include <assimp/defs.h>
+
namespace Assimp {
- // NOTE: the functions below are mostly intended as replacement for
- // std::upper, std::lower, std::isupper, std::islower, std::isspace.
- // we don't bother of locales. We don't want them. We want reliable
- // (i.e. identical) results across all locales.
+// NOTE: the functions below are mostly intended as replacement for
+// std::upper, std::lower, std::isupper, std::islower, std::isspace.
+// we don't bother of locales. We don't want them. We want reliable
+// (i.e. identical) results across all locales.
+
+// The functions below accept any character type, but know only
+// about ASCII. However, UTF-32 is the only safe ASCII superset to
+// use since it doesn't have multi-byte sequences.
- // The functions below accept any character type, but know only
- // about ASCII. However, UTF-32 is the only safe ASCII superset to
- // use since it doesn't have multibyte sequences.
+static const unsigned int BufferSize = 4096;
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE char_t ToLower( char_t in)
{
- return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
+ return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
-AI_FORCE_INLINE char_t ToUpper( char_t in)
-{
- return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
+AI_FORCE_INLINE char_t ToUpper( char_t in) {
+ return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in)
{
- return (in >= (char_t)'A' && in <= (char_t)'Z');
+ return (in >= (char_t)'A' && in <= (char_t)'Z');
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in)
{
- return (in >= (char_t)'a' && in <= (char_t)'z');
+ return (in >= (char_t)'a' && in <= (char_t)'z');
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in)
{
- return (in == (char_t)' ' || in == (char_t)'\t');
+ return (in == (char_t)' ' || in == (char_t)'\t');
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( char_t in)
{
- return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0');
+ return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{
- return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
+ return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
{
- while (*in == (char_t)' ' || *in == (char_t)'\t')in++;
- *out = in;
- return !IsLineEnd<char_t>(*in);
+ while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
+ ++in;
+ }
+ *out = in;
+ return !IsLineEnd<char_t>(*in);
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
{
- return SkipSpaces<char_t>(*inout,inout);
+ return SkipSpaces<char_t>(*inout,inout);
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
{
- while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
+ while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
+ ++in;
+ }
- // files are opened in binary mode. Ergo there are both NL and CR
- while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
- *out = in;
- return *in != (char_t)'\0';
+ // files are opened in binary mode. Ergo there are both NL and CR
+ while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+ ++in;
+ }
+ *out = in;
+ return *in != (char_t)'\0';
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t** inout)
{
- return SkipLine<char_t>(*inout,inout);
+ return SkipLine<char_t>(*inout,inout);
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
{
- while (*in == (char_t)' ' || *in == (char_t)'\t' ||
- *in == (char_t)'\r' || *in == (char_t)'\n')in++;
- *out = in;
- return *in != '\0';
+ while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
+ ++in;
+ }
+ *out = in;
+ return *in != '\0';
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
{
- return SkipSpacesAndLineEnd<char_t>(*inout,inout);
+ return SkipSpacesAndLineEnd<char_t>(*inout,inout);
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
-AI_FORCE_INLINE bool GetNextLine(const char_t*& buffer, char_t out[4096])
+AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] )
{
- if ((char_t)'\0' == *buffer)return false;
+ if( ( char_t )'\0' == *buffer ) {
+ return false;
+ }
+
+ char* _out = out;
+ char* const end = _out + BufferSize;
+ while( !IsLineEnd( *buffer ) && _out < end ) {
+ *_out++ = *buffer++;
+ }
+ *_out = (char_t)'\0';
- char* _out = out;
- char* const end = _out+4096;
- while (!IsLineEnd( *buffer ) && _out < end)
- *_out++ = *buffer++;
- *_out = (char_t)'\0';
+ while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
+ ++buffer;
+ }
- while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
- return true;
+ return true;
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool IsNumeric( char_t in)
{
- return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
+ return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
}
+
// ---------------------------------------------------------------------------------
template <class char_t>
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
{
- if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len]))
- {
- in += len+1;
- return true;
- }
- return false;
+ if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
+ if (in[len] != '\0') {
+ in += len+1;
+ } else {
+ // If EOF after the token make sure we don't go past end of buffer
+ in += len;
+ }
+ return true;
+ }
+
+ return false;
}
// ---------------------------------------------------------------------------------
/** @brief Case-ignoring version of TokenMatch
@@ -185,26 +222,29 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
*/
AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
{
- if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len]))
- {
- in += len+1;
- return true;
- }
- return false;
+ if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
+ in += len+1;
+ return true;
+ }
+ return false;
}
// ---------------------------------------------------------------------------------
AI_FORCE_INLINE void SkipToken(const char*& in)
{
- SkipSpaces(&in);
- while (!IsSpaceOrNewLine(*in))++in;
+ SkipSpaces(&in);
+ while (!IsSpaceOrNewLine(*in))++in;
}
// ---------------------------------------------------------------------------------
AI_FORCE_INLINE std::string GetNextToken(const char*& in)
{
- SkipSpacesAndLineEnd(&in);
- const char* cur = in;
- while (!IsSpaceOrNewLine(*in))++in;
- return std::string(cur,(size_t)(in-cur));
+ SkipSpacesAndLineEnd(&in);
+ const char* cur = in;
+ while (!IsSpaceOrNewLine(*in))++in;
+ return std::string(cur,(size_t)(in-cur));
}
+
+// ---------------------------------------------------------------------------------
+
} // ! namespace Assimp
+
#endif // ! AI_PARSING_UTILS_H_INC
diff --git a/src/3rdparty/assimp/code/PlyExporter.cpp b/src/3rdparty/assimp/code/PlyExporter.cpp
index b2e0b352a..e69c5e386 100644
--- a/src/3rdparty/assimp/code/PlyExporter.cpp
+++ b/src/3rdparty/assimp/code/PlyExporter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,48 +23,68 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#if !defined(ASSIMP_BUILD_NO_EXPORT) && !defined(ASSIMP_BUILD_NO_PLY_EXPORTER)
#include "PlyExporter.h"
-#include "../include/assimp/version.h"
+#include <memory>
+#include <cmath>
+#include "Exceptional.h"
+#include <assimp/scene.h>
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include "qnan.h"
+
-using namespace Assimp;
-namespace Assimp {
+//using namespace Assimp;
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp
-void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
- // invoke the exporter
- PlyExporter exporter(pFile, pScene);
+ // invoke the exporter
+ PlyExporter exporter(pFile, pScene);
- // we're still here - export successfully completed. Write the file.
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
- }
+ // we're still here - export successfully completed. Write the file.
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
+ }
- outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+ outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
-} // end of namespace Assimp
+void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ // invoke the exporter
+ PlyExporter exporter(pFile, pScene, true);
+
+ // we're still here - export successfully completed. Write the file.
+ std::unique_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb"));
+ if (outfile == NULL) {
+ throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
+ }
+
+ outfile->Write(exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()), 1);
+}
#define PLY_EXPORT_HAS_NORMALS 0x1
#define PLY_EXPORT_HAS_TANGENTS_BITANGENTS 0x2
@@ -72,180 +92,285 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
#define PLY_EXPORT_HAS_COLORS (PLY_EXPORT_HAS_TEXCOORDS << AI_MAX_NUMBER_OF_TEXTURECOORDS)
// ------------------------------------------------------------------------------------------------
-PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
+PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool binary)
: filename(_filename)
-, pScene(pScene)
-, endl("\n")
+, endl("\n")
{
- // make sure that all formatting happens using the standard, C locale and not the user's current locale
- const std::locale& l = std::locale("C");
- mOutput.imbue(l);
-
- unsigned int faces = 0u, vertices = 0u, components = 0u;
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- const aiMesh& m = *pScene->mMeshes[i];
- faces += m.mNumFaces;
- vertices += m.mNumVertices;
-
- if (m.HasNormals()) {
- components |= PLY_EXPORT_HAS_NORMALS;
- }
- if (m.HasTangentsAndBitangents()) {
- components |= PLY_EXPORT_HAS_TANGENTS_BITANGENTS;
- }
- for (unsigned int t = 0; m.HasTextureCoords(t); ++t) {
- components |= PLY_EXPORT_HAS_TEXCOORDS << t;
- }
- for (unsigned int t = 0; m.HasVertexColors(t); ++t) {
- components |= PLY_EXPORT_HAS_COLORS << t;
- }
- }
-
- mOutput << "ply" << endl;
- mOutput << "format ascii 1.0" << endl;
- mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
- << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
- << aiGetVersionRevision() << ")" << endl;
-
- mOutput << "element vertex " << vertices << endl;
- mOutput << "property float x" << endl;
- mOutput << "property float y" << endl;
- mOutput << "property float z" << endl;
-
- if(components & PLY_EXPORT_HAS_NORMALS) {
- mOutput << "property float nx" << endl;
- mOutput << "property float ny" << endl;
- mOutput << "property float nz" << endl;
- }
-
- // write texcoords first, just in case an importer does not support tangents
- // bitangents and just skips over the rest of the line upon encountering
- // unknown fields (Ply leaves pretty much every vertex component open,
- // but in reality most importers only know about vertex positions, normals
- // and texture coordinates).
- for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
- if (!c) {
- mOutput << "property float s" << endl;
- mOutput << "property float t" << endl;
- }
- else {
- mOutput << "property float s" << c << endl;
- mOutput << "property float t" << c << endl;
- }
- }
-
- for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
- if (!c) {
- mOutput << "property float r" << endl;
- mOutput << "property float g" << endl;
- mOutput << "property float b" << endl;
- mOutput << "property float a" << endl;
- }
- else {
- mOutput << "property float r" << c << endl;
- mOutput << "property float g" << c << endl;
- mOutput << "property float b" << c << endl;
- mOutput << "property float a" << c << endl;
- }
- }
-
- if(components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
- mOutput << "property float tx" << endl;
- mOutput << "property float ty" << endl;
- mOutput << "property float tz" << endl;
- mOutput << "property float bx" << endl;
- mOutput << "property float by" << endl;
- mOutput << "property float bz" << endl;
- }
-
- mOutput << "element face " << faces << endl;
- mOutput << "property list uint uint vertex_index" << endl;
- mOutput << "end_header" << endl;
-
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- WriteMeshVerts(pScene->mMeshes[i],components);
- }
- for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) {
- WriteMeshIndices(pScene->mMeshes[i],ofs);
- ofs += pScene->mMeshes[i]->mNumVertices;
- }
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ const std::locale& l = std::locale("C");
+ mOutput.imbue(l);
+ mOutput.precision(16);
+
+ unsigned int faces = 0u, vertices = 0u, components = 0u;
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ const aiMesh& m = *pScene->mMeshes[i];
+ faces += m.mNumFaces;
+ vertices += m.mNumVertices;
+
+ if (m.HasNormals()) {
+ components |= PLY_EXPORT_HAS_NORMALS;
+ }
+ if (m.HasTangentsAndBitangents()) {
+ components |= PLY_EXPORT_HAS_TANGENTS_BITANGENTS;
+ }
+ for (unsigned int t = 0; m.HasTextureCoords(t); ++t) {
+ components |= PLY_EXPORT_HAS_TEXCOORDS << t;
+ }
+ for (unsigned int t = 0; m.HasVertexColors(t); ++t) {
+ components |= PLY_EXPORT_HAS_COLORS << t;
+ }
+ }
+
+ mOutput << "ply" << endl;
+ if (binary) {
+#if (defined AI_BUILD_BIG_ENDIAN)
+ mOutput << "format binary_big_endian 1.0" << endl;
+#else
+ mOutput << "format binary_little_endian 1.0" << endl;
+#endif
+ }
+ else {
+ mOutput << "format ascii 1.0" << endl;
+ }
+ mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
+ << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
+ << aiGetVersionRevision() << ")" << endl;
+
+ mOutput << "element vertex " << vertices << endl;
+ mOutput << "property float x" << endl;
+ mOutput << "property float y" << endl;
+ mOutput << "property float z" << endl;
+
+ if(components & PLY_EXPORT_HAS_NORMALS) {
+ mOutput << "property float nx" << endl;
+ mOutput << "property float ny" << endl;
+ mOutput << "property float nz" << endl;
+ }
+
+ // write texcoords first, just in case an importer does not support tangents
+ // bitangents and just skips over the rest of the line upon encountering
+ // unknown fields (Ply leaves pretty much every vertex component open,
+ // but in reality most importers only know about vertex positions, normals
+ // and texture coordinates).
+ for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
+ if (!c) {
+ mOutput << "property float s" << endl;
+ mOutput << "property float t" << endl;
+ }
+ else {
+ mOutput << "property float s" << c << endl;
+ mOutput << "property float t" << c << endl;
+ }
+ }
+
+ for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
+ if (!c) {
+ mOutput << "property float r" << endl;
+ mOutput << "property float g" << endl;
+ mOutput << "property float b" << endl;
+ mOutput << "property float a" << endl;
+ }
+ else {
+ mOutput << "property float r" << c << endl;
+ mOutput << "property float g" << c << endl;
+ mOutput << "property float b" << c << endl;
+ mOutput << "property float a" << c << endl;
+ }
+ }
+
+ if(components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
+ mOutput << "property float tx" << endl;
+ mOutput << "property float ty" << endl;
+ mOutput << "property float tz" << endl;
+ mOutput << "property float bx" << endl;
+ mOutput << "property float by" << endl;
+ mOutput << "property float bz" << endl;
+ }
+
+ mOutput << "element face " << faces << endl;
+
+ // uchar seems to be the most common type for the number of indices per polygon and int seems to be most common for the vertex indices.
+ // For instance, MeshLab fails to load meshes in which both types are uint. Houdini seems to have problems as well.
+ // Obviously, using uchar will not work for meshes with polygons with more than 255 indices, but how realistic is this case?
+ mOutput << "property list uchar int vertex_index" << endl;
+
+ mOutput << "end_header" << endl;
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ if (binary) {
+ WriteMeshVertsBinary(pScene->mMeshes[i], components);
+ }
+ else {
+ WriteMeshVerts(pScene->mMeshes[i], components);
+ }
+ }
+ for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) {
+ if (binary) {
+ WriteMeshIndicesBinary(pScene->mMeshes[i], ofs);
+ }
+ else {
+ WriteMeshIndices(pScene->mMeshes[i], ofs);
+ }
+ ofs += pScene->mMeshes[i]->mNumVertices;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+PlyExporter::~PlyExporter() {
+ // empty
}
// ------------------------------------------------------------------------------------------------
-void PlyExporter :: WriteMeshVerts(const aiMesh* m, unsigned int components)
+void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components)
{
- for (unsigned int i = 0; i < m->mNumVertices; ++i) {
- mOutput <<
- m->mVertices[i].x << " " <<
- m->mVertices[i].y << " " <<
- m->mVertices[i].z
- ;
- if(components & PLY_EXPORT_HAS_NORMALS) {
- if (m->HasNormals()) {
- mOutput <<
- " " << m->mNormals[i].x <<
- " " << m->mNormals[i].y <<
- " " << m->mNormals[i].z;
- }
- else {
- mOutput << " 0.0 0.0 0.0";
- }
- }
-
- for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
- if (m->HasTextureCoords(c)) {
- mOutput <<
- " " << m->mTextureCoords[c][i].x <<
- " " << m->mTextureCoords[c][i].y;
- }
- else {
- mOutput << " -1.0 -1.0";
- }
- }
-
- for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
- if (m->HasVertexColors(c)) {
- mOutput <<
- " " << m->mColors[c][i].r <<
- " " << m->mColors[c][i].g <<
- " " << m->mColors[c][i].b <<
- " " << m->mColors[c][i].a;
- }
- else {
- mOutput << " -1.0 -1.0 -1.0 -1.0";
- }
- }
-
- if(components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
- if (m->HasTangentsAndBitangents()) {
- mOutput <<
- " " << m->mTangents[i].x <<
- " " << m->mTangents[i].y <<
- " " << m->mTangents[i].z <<
- " " << m->mBitangents[i].x <<
- " " << m->mBitangents[i].y <<
- " " << m->mBitangents[i].z
- ;
- }
- else {
- mOutput << " 0.0 0.0 0.0 0.0 0.0 0.0";
- }
- }
-
- mOutput << endl;
- }
+ static const float inf = std::numeric_limits<float>::infinity();
+
+ // If a component (for instance normal vectors) is present in at least one mesh in the scene,
+ // then default values are written for meshes that do not contain this component.
+ for (unsigned int i = 0; i < m->mNumVertices; ++i) {
+ mOutput <<
+ m->mVertices[i].x << " " <<
+ m->mVertices[i].y << " " <<
+ m->mVertices[i].z
+ ;
+ if(components & PLY_EXPORT_HAS_NORMALS) {
+ if (m->HasNormals() && is_not_qnan(m->mNormals[i].x) && std::fabs(m->mNormals[i].x) != inf) {
+ mOutput <<
+ " " << m->mNormals[i].x <<
+ " " << m->mNormals[i].y <<
+ " " << m->mNormals[i].z;
+ }
+ else {
+ mOutput << " 0.0 0.0 0.0";
+ }
+ }
+
+ for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
+ if (m->HasTextureCoords(c)) {
+ mOutput <<
+ " " << m->mTextureCoords[c][i].x <<
+ " " << m->mTextureCoords[c][i].y;
+ }
+ else {
+ mOutput << " -1.0 -1.0";
+ }
+ }
+
+ for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
+ if (m->HasVertexColors(c)) {
+ mOutput <<
+ " " << m->mColors[c][i].r <<
+ " " << m->mColors[c][i].g <<
+ " " << m->mColors[c][i].b <<
+ " " << m->mColors[c][i].a;
+ }
+ else {
+ mOutput << " -1.0 -1.0 -1.0 -1.0";
+ }
+ }
+
+ if(components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
+ if (m->HasTangentsAndBitangents()) {
+ mOutput <<
+ " " << m->mTangents[i].x <<
+ " " << m->mTangents[i].y <<
+ " " << m->mTangents[i].z <<
+ " " << m->mBitangents[i].x <<
+ " " << m->mBitangents[i].y <<
+ " " << m->mBitangents[i].z
+ ;
+ }
+ else {
+ mOutput << " 0.0 0.0 0.0 0.0 0.0 0.0";
+ }
+ }
+
+ mOutput << endl;
+ }
}
// ------------------------------------------------------------------------------------------------
-void PlyExporter :: WriteMeshIndices(const aiMesh* m, unsigned int offset)
+void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components)
{
- for (unsigned int i = 0; i < m->mNumFaces; ++i) {
- const aiFace& f = m->mFaces[i];
- mOutput << f.mNumIndices << " ";
- for(unsigned int c = 0; c < f.mNumIndices; ++c) {
- mOutput << (f.mIndices[c] + offset) << (c == f.mNumIndices-1 ? endl : " ");
- }
- }
+ // If a component (for instance normal vectors) is present in at least one mesh in the scene,
+ // then default values are written for meshes that do not contain this component.
+ aiVector3D defaultNormal(0, 0, 0);
+ aiVector2D defaultUV(-1, -1);
+ aiColor4D defaultColor(-1, -1, -1, -1);
+ for (unsigned int i = 0; i < m->mNumVertices; ++i) {
+ mOutput.write(reinterpret_cast<const char*>(&m->mVertices[i].x), 12);
+ if (components & PLY_EXPORT_HAS_NORMALS) {
+ if (m->HasNormals()) {
+ mOutput.write(reinterpret_cast<const char*>(&m->mNormals[i].x), 12);
+ }
+ else {
+ mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
+ }
+ }
+
+ for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
+ if (m->HasTextureCoords(c)) {
+ mOutput.write(reinterpret_cast<const char*>(&m->mTextureCoords[c][i].x), 8);
+ }
+ else {
+ mOutput.write(reinterpret_cast<const char*>(&defaultUV.x), 8);
+ }
+ }
+
+ for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
+ if (m->HasVertexColors(c)) {
+ mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16);
+ }
+ else {
+ mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16);
+ }
+ }
+
+ if (components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
+ if (m->HasTangentsAndBitangents()) {
+ mOutput.write(reinterpret_cast<const char*>(&m->mTangents[i].x), 12);
+ mOutput.write(reinterpret_cast<const char*>(&m->mBitangents[i].x), 12);
+ }
+ else {
+ mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
+ mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
+ }
+ }
+ }
}
-#endif
+// ------------------------------------------------------------------------------------------------
+void PlyExporter::WriteMeshIndices(const aiMesh* m, unsigned int offset)
+{
+ for (unsigned int i = 0; i < m->mNumFaces; ++i) {
+ const aiFace& f = m->mFaces[i];
+ mOutput << f.mNumIndices << " ";
+ for(unsigned int c = 0; c < f.mNumIndices; ++c) {
+ mOutput << (f.mIndices[c] + offset) << (c == f.mNumIndices-1 ? endl : " ");
+ }
+ }
+}
+
+// Generic method in case we want to use different data types for the indices or make this configurable.
+template<typename NumIndicesType, typename IndexType>
+void WriteMeshIndicesBinary_Generic(const aiMesh* m, unsigned int offset, std::ostringstream& output)
+{
+ for (unsigned int i = 0; i < m->mNumFaces; ++i) {
+ const aiFace& f = m->mFaces[i];
+ NumIndicesType numIndices = static_cast<NumIndicesType>(f.mNumIndices);
+ output.write(reinterpret_cast<const char*>(&numIndices), sizeof(NumIndicesType));
+ for (unsigned int c = 0; c < f.mNumIndices; ++c) {
+ IndexType index = f.mIndices[c] + offset;
+ output.write(reinterpret_cast<const char*>(&index), sizeof(IndexType));
+ }
+ }
+}
+
+void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset)
+{
+ WriteMeshIndicesBinary_Generic<unsigned char, int>(m, offset, mOutput);
+}
+
+} // end of namespace Assimp
+
+#endif // !defined(ASSIMP_BUILD_NO_EXPORT) && !defined(ASSIMP_BUILD_NO_PLY_EXPORTER)
diff --git a/src/3rdparty/assimp/code/PlyExporter.h b/src/3rdparty/assimp/code/PlyExporter.h
index acc922cc3..be4fa466f 100644
--- a/src/3rdparty/assimp/code/PlyExporter.h
+++ b/src/3rdparty/assimp/code/PlyExporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,8 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene;
struct aiNode;
+struct aiMesh;
-namespace Assimp
+namespace Assimp
{
// ------------------------------------------------------------------------------------------------
@@ -58,28 +59,30 @@ namespace Assimp
class PlyExporter
{
public:
- /// Constructor for a specific scene to export
- PlyExporter(const char* filename, const aiScene* pScene);
+ /// The class constructor for a specific scene to export
+ PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);
+ /// The class destructor, empty.
+ ~PlyExporter();
public:
-
- /// public stringstreams to write all output into
- std::ostringstream mOutput;
+ /// public string-streams to write all output into:
+ std::ostringstream mOutput;
private:
-
- void WriteMeshVerts(const aiMesh* m, unsigned int components);
- void WriteMeshIndices(const aiMesh* m, unsigned int ofs);
+ void WriteMeshVerts(const aiMesh* m, unsigned int components);
+ void WriteMeshIndices(const aiMesh* m, unsigned int ofs);
+ void WriteMeshVertsBinary(const aiMesh* m, unsigned int components);
+ void WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset);
private:
+ const std::string filename; // tHE FILENAME
+ const std::string endl; // obviously, this endl() doesn't flush() the stream
- const std::string filename;
- const aiScene* const pScene;
-
- // obviously, this endl() doesn't flush() the stream
- const std::string endl;
+private:
+ PlyExporter( const PlyExporter & );
+ PlyExporter &operator = ( const PlyExporter & );
};
-}
+} // Namespace Assimp
-#endif
+#endif // AI_PLYEXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/PlyLoader.cpp b/src/3rdparty/assimp/code/PlyLoader.cpp
index 9aa5d9d71..d4dc2f864 100644
--- a/src/3rdparty/assimp/code/PlyLoader.cpp
+++ b/src/3rdparty/assimp/code/PlyLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,1020 +43,1070 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the PLY importer class
*/
-#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
// internal headers
#include "PlyLoader.h"
+#include "Macros.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Stanford Polygon Library (PLY) Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "ply"
+ "Stanford Polygon Library (PLY) Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ply"
};
+
+// ------------------------------------------------------------------------------------------------
+// Internal stuff
+namespace
+{
+ // ------------------------------------------------------------------------------------------------
+ // Checks that property index is within range
+ template <class T>
+ const T &GetProperty(const std::vector<T> &props, int idx)
+ {
+ if( static_cast< size_t >( idx ) >= props.size() ) {
+ throw DeadlyImportError( "Invalid .ply file: Property index is out of range." );
+ }
+
+ return props[idx];
+ }
+}
+
+
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
PLYImporter::PLYImporter()
+ : mBuffer(),
+ pcDOM()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
PLYImporter::~PLYImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- if (extension == "ply")
- return true;
- else if (!extension.length() || checkSig)
- {
- if (!pIOHandler)return true;
- const char* tokens[] = {"ply"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "ply")
+ return true;
+ else if (!extension.length() || checkSig)
+ {
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"ply"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* PLYImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void PLYImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
-{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open PLY file " + pFile + ".");
- }
-
- // allocate storage and copy the contents of the file to a memory buffer
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
- mBuffer = (unsigned char*)&mBuffer2[0];
-
- // the beginning of the file must be PLY - magic, magic
- if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') ||
- (mBuffer[1] != 'L' && mBuffer[1] != 'l') ||
- (mBuffer[2] != 'Y' && mBuffer[2] != 'y')) {
- throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there");
- }
-
- char* szMe = (char*)&this->mBuffer[3];
- SkipSpacesAndLineEnd(szMe,(const char**)&szMe);
-
- // determine the format of the file data
- PLY::DOM sPlyDom;
- if (TokenMatch(szMe,"format",6))
- {
- if (TokenMatch(szMe,"ascii",5))
- {
- SkipLine(szMe,(const char**)&szMe);
- if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
- throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)");
- }
- else if (!::strncmp(szMe,"binary_",7))
- {
- bool bIsBE = false;
- szMe+=7;
-
- // binary_little_endian
- // binary_big_endian
+static bool isBigEndian( const char* szMe ) {
+ ai_assert( NULL != szMe );
+
+ // binary_little_endian
+ // binary_big_endian
+ bool isBigEndian( false );
#if (defined AI_BUILD_BIG_ENDIAN)
- if ('l' == *szMe || 'L' == *szMe)bIsBE = true;
+ if ( 'l' == *szMe || 'L' == *szMe ) {
+ isBigEndian = true;
+}
#else
- if ('b' == *szMe || 'B' == *szMe)bIsBE = true;
+ if ( 'b' == *szMe || 'B' == *szMe ) {
+ isBigEndian = true;
+ }
#endif // ! AI_BUILD_BIG_ENDIAN
- // skip the line, parse the rest of the header and build the DOM
- SkipLine(szMe,(const char**)&szMe);
- if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE))
- throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)");
- }
- else throw DeadlyImportError( "Invalid .ply file: Unknown file format");
- }
- else
- {
- delete[] this->mBuffer;
- AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
- throw DeadlyImportError( "Invalid .ply file: Missing format specification");
- }
- this->pcDOM = &sPlyDom;
-
- // now load a list of vertices. This must be sucessfull in order to procede
- std::vector<aiVector3D> avPositions;
- this->LoadVertices(&avPositions,false);
-
- if (avPositions.empty())
- throw DeadlyImportError( "Invalid .ply file: No vertices found. "
- "Unable to parse the data format of the PLY file.");
-
- // now load a list of normals.
- std::vector<aiVector3D> avNormals;
- LoadVertices(&avNormals,true);
-
- // load the face list
- std::vector<PLY::Face> avFaces;
- LoadFaces(&avFaces);
-
- // if no face list is existing we assume that the vertex
- // list is containing a list of triangles
- if (avFaces.empty())
- {
- if (avPositions.size() < 3)
- {
- throw DeadlyImportError( "Invalid .ply file: Not enough "
- "vertices to build a proper face list. ");
- }
-
- const unsigned int iNum = (unsigned int)avPositions.size() / 3;
- for (unsigned int i = 0; i< iNum;++i)
- {
- PLY::Face sFace;
- sFace.mIndices.push_back((iNum*3));
- sFace.mIndices.push_back((iNum*3)+1);
- sFace.mIndices.push_back((iNum*3)+2);
- avFaces.push_back(sFace);
- }
- }
-
- // now load a list of all materials
- std::vector<aiMaterial*> avMaterials;
- LoadMaterial(&avMaterials);
-
- // now load a list of all vertex color channels
- std::vector<aiColor4D> avColors;
- avColors.reserve(avPositions.size());
- LoadVertexColor(&avColors);
-
- // now try to load texture coordinates
- std::vector<aiVector2D> avTexCoords;
- avTexCoords.reserve(avPositions.size());
- LoadTextureCoordinates(&avTexCoords);
-
- // now replace the default material in all faces and validate all material indices
- ReplaceDefaultMaterial(&avFaces,&avMaterials);
-
- // now convert this to a list of aiMesh instances
- std::vector<aiMesh*> avMeshes;
- avMeshes.reserve(avMaterials.size()+1);
- ConvertMeshes(&avFaces,&avPositions,&avNormals,
- &avColors,&avTexCoords,&avMaterials,&avMeshes);
-
- if (avMeshes.empty())
- throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data ");
-
- // now generate the output scene object. Fill the material list
- pScene->mNumMaterials = (unsigned int)avMaterials.size();
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- pScene->mMaterials[i] = avMaterials[i];
-
- // fill the mesh list
- pScene->mNumMeshes = (unsigned int)avMeshes.size();
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mMeshes[i] = avMeshes[i];
-
- // generate a simple node structure
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
-
- for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes;++i)
- pScene->mRootNode->mMeshes[i] = i;
+ return isBigEndian;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void PLYImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
+{
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open PLY file " + pFile + ".");
+ }
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ mBuffer = (unsigned char*)&mBuffer2[0];
+
+ // the beginning of the file must be PLY - magic, magic
+ if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') ||
+ (mBuffer[1] != 'L' && mBuffer[1] != 'l') ||
+ (mBuffer[2] != 'Y' && mBuffer[2] != 'y')) {
+ throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there");
+ }
+
+ char* szMe = (char*)&this->mBuffer[3];
+ SkipSpacesAndLineEnd(szMe,(const char**)&szMe);
+
+ // determine the format of the file data
+ PLY::DOM sPlyDom;
+ if (TokenMatch(szMe,"format",6)) {
+ if (TokenMatch(szMe,"ascii",5)) {
+ SkipLine(szMe,(const char**)&szMe);
+ if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
+ throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)");
+ } else if (!::strncmp(szMe,"binary_",7))
+ {
+ szMe += 7;
+ const bool bIsBE( isBigEndian( szMe ) );
+
+ // skip the line, parse the rest of the header and build the DOM
+ SkipLine(szMe,(const char**)&szMe);
+ if ( !PLY::DOM::ParseInstanceBinary( szMe, &sPlyDom, bIsBE ) ) {
+ throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)" );
+ }
+ } else {
+ throw DeadlyImportError( "Invalid .ply file: Unknown file format" );
+ }
+ }
+ else
+ {
+ AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+ throw DeadlyImportError( "Invalid .ply file: Missing format specification");
+ }
+ this->pcDOM = &sPlyDom;
+
+ // now load a list of vertices. This must be successfully in order to procedure
+ std::vector<aiVector3D> avPositions;
+ this->LoadVertices(&avPositions,false);
+
+ if ( avPositions.empty() ) {
+ throw DeadlyImportError( "Invalid .ply file: No vertices found. "
+ "Unable to parse the data format of the PLY file." );
+ }
+
+ // now load a list of normals.
+ std::vector<aiVector3D> avNormals;
+ LoadVertices(&avNormals,true);
+
+ // load the face list
+ std::vector<PLY::Face> avFaces;
+ LoadFaces(&avFaces);
+
+ // if no face list is existing we assume that the vertex
+ // list is containing a list of triangles
+ if (avFaces.empty())
+ {
+ if (avPositions.size() < 3)
+ {
+ throw DeadlyImportError( "Invalid .ply file: Not enough "
+ "vertices to build a proper face list. ");
+ }
+
+ const unsigned int iNum = (unsigned int)avPositions.size() / 3;
+ for (unsigned int i = 0; i< iNum;++i)
+ {
+ PLY::Face sFace;
+ sFace.mIndices.push_back((iNum*3));
+ sFace.mIndices.push_back((iNum*3)+1);
+ sFace.mIndices.push_back((iNum*3)+2);
+ avFaces.push_back(sFace);
+ }
+ }
+
+ // now load a list of all materials
+ std::vector<aiMaterial*> avMaterials;
+ LoadMaterial(&avMaterials);
+
+ // now load a list of all vertex color channels
+ std::vector<aiColor4D> avColors;
+ avColors.reserve(avPositions.size());
+ LoadVertexColor(&avColors);
+
+ // now try to load texture coordinates
+ std::vector<aiVector2D> avTexCoords;
+ avTexCoords.reserve(avPositions.size());
+ LoadTextureCoordinates(&avTexCoords);
+
+ // now replace the default material in all faces and validate all material indices
+ ReplaceDefaultMaterial(&avFaces,&avMaterials);
+
+ // now convert this to a list of aiMesh instances
+ std::vector<aiMesh*> avMeshes;
+ avMeshes.reserve(avMaterials.size()+1);
+ ConvertMeshes(&avFaces,&avPositions,&avNormals,
+ &avColors,&avTexCoords,&avMaterials,&avMeshes);
+
+ if ( avMeshes.empty() ) {
+ throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " );
+ }
+
+ // now generate the output scene object. Fill the material list
+ pScene->mNumMaterials = (unsigned int)avMaterials.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) {
+ pScene->mMaterials[ i ] = avMaterials[ i ];
+ }
+
+ // fill the mesh list
+ pScene->mNumMeshes = (unsigned int)avMeshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for ( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) {
+ pScene->mMeshes[ i ] = avMeshes[ i ];
+ }
+
+ // generate a simple node structure
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+
+ for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) {
+ pScene->mRootNode->mMeshes[ i ] = i;
+ }
}
// ------------------------------------------------------------------------------------------------
// Split meshes by material IDs
void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces,
- const std::vector<aiVector3D>* avPositions,
- const std::vector<aiVector3D>* avNormals,
- const std::vector<aiColor4D>* avColors,
- const std::vector<aiVector2D>* avTexCoords,
- const std::vector<aiMaterial*>* avMaterials,
- std::vector<aiMesh*>* avOut)
+ const std::vector<aiVector3D>* avPositions,
+ const std::vector<aiVector3D>* avNormals,
+ const std::vector<aiColor4D>* avColors,
+ const std::vector<aiVector2D>* avTexCoords,
+ const std::vector<aiMaterial*>* avMaterials,
+ std::vector<aiMesh*>* avOut)
{
- ai_assert(NULL != avFaces);
- ai_assert(NULL != avPositions);
- ai_assert(NULL != avMaterials);
-
- // split by materials
- std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
-
- unsigned int iNum = 0;
- for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum)
- aiSplit[(*i).iMaterialIndex].push_back(iNum);
-
- // now generate submeshes
- for (unsigned int p = 0; p < avMaterials->size();++p)
- {
- if (aiSplit[p].size() != 0)
- {
- // allocate the mesh object
- aiMesh* p_pcOut = new aiMesh();
- p_pcOut->mMaterialIndex = p;
-
- p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
- p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
-
- // at first we need to determine the size of the output vector array
- unsigned int iNum = 0;
- for (unsigned int i = 0; i < aiSplit[p].size();++i)
- {
- iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
- }
- p_pcOut->mNumVertices = iNum;
- p_pcOut->mVertices = new aiVector3D[iNum];
-
- if (!avColors->empty())
- p_pcOut->mColors[0] = new aiColor4D[iNum];
- if (!avTexCoords->empty())
- {
- p_pcOut->mNumUVComponents[0] = 2;
- p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
- }
- if (!avNormals->empty())
- p_pcOut->mNormals = new aiVector3D[iNum];
-
- // add all faces
- iNum = 0;
- unsigned int iVertex = 0;
- for (std::vector<unsigned int>::const_iterator i = aiSplit[p].begin();
- i != aiSplit[p].end();++i,++iNum)
- {
- p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size();
- p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
-
- // build an unique set of vertices/colors for this face
- for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q)
- {
- p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
- p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]];
-
- if (!avColors->empty())
- p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]];
-
- if (!avTexCoords->empty())
- {
- const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]];
- p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
- p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
- }
-
- if (!avNormals->empty())
- p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]];
- iVertex++;
- }
-
- }
- // add the mesh to the output list
- avOut->push_back(p_pcOut);
- }
- }
- delete[] aiSplit; // cleanup
+ ai_assert(NULL != avFaces);
+ ai_assert(NULL != avPositions);
+ ai_assert(NULL != avMaterials);
+
+ // split by materials
+ std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()];
+
+ unsigned int iNum = 0;
+ for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum)
+ aiSplit[(*i).iMaterialIndex].push_back(iNum);
+
+ // now generate sub-meshes
+ for (unsigned int p = 0; p < avMaterials->size();++p)
+ {
+ if (aiSplit[p].size() != 0)
+ {
+ // allocate the mesh object
+ aiMesh* p_pcOut = new aiMesh();
+ p_pcOut->mMaterialIndex = p;
+
+ p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
+ p_pcOut->mFaces = new aiFace[aiSplit[p].size()];
+
+ // at first we need to determine the size of the output vector array
+ unsigned int iNum = 0;
+ for (unsigned int i = 0; i < aiSplit[p].size();++i)
+ {
+ iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size();
+ }
+ p_pcOut->mNumVertices = iNum;
+ if( 0 == iNum ) { // nothing to do
+ delete[] aiSplit; // cleanup
+ delete p_pcOut;
+ return;
+ }
+ p_pcOut->mVertices = new aiVector3D[iNum];
+
+ if (!avColors->empty())
+ p_pcOut->mColors[0] = new aiColor4D[iNum];
+ if (!avTexCoords->empty())
+ {
+ p_pcOut->mNumUVComponents[0] = 2;
+ p_pcOut->mTextureCoords[0] = new aiVector3D[iNum];
+ }
+ if (!avNormals->empty())
+ p_pcOut->mNormals = new aiVector3D[iNum];
+
+ // add all faces
+ iNum = 0;
+ unsigned int iVertex = 0;
+ for (std::vector<unsigned int>::const_iterator i = aiSplit[p].begin();
+ i != aiSplit[p].end();++i,++iNum)
+ {
+ p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size();
+ p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices];
+
+ // build an unique set of vertices/colors for this face
+ for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q)
+ {
+ p_pcOut->mFaces[iNum].mIndices[q] = iVertex;
+ const size_t idx = ( *avFaces )[ *i ].mIndices[ q ];
+ if( idx >= ( *avPositions ).size() ) {
+ // out of border
+ continue;
+ }
+ p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ];
+
+ if (!avColors->empty())
+ p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ];
+
+ if (!avTexCoords->empty())
+ {
+ const aiVector2D& vec = ( *avTexCoords )[ idx ];
+ p_pcOut->mTextureCoords[0][iVertex].x = vec.x;
+ p_pcOut->mTextureCoords[0][iVertex].y = vec.y;
+ }
+
+ if (!avNormals->empty())
+ p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ];
+ iVertex++;
+ }
+
+ }
+ // add the mesh to the output list
+ avOut->push_back(p_pcOut);
+ }
+ }
+ delete[] aiSplit; // cleanup
}
// ------------------------------------------------------------------------------------------------
// Generate a default material if none was specified and apply it to all vanilla faces
void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
- std::vector<aiMaterial*>* avMaterials)
+ std::vector<aiMaterial*>* avMaterials)
{
- bool bNeedDefaultMat = false;
-
- for (std::vector<PLY::Face>::iterator i = avFaces->begin();i != avFaces->end();++i) {
- if (0xFFFFFFFF == (*i).iMaterialIndex) {
- bNeedDefaultMat = true;
- (*i).iMaterialIndex = (unsigned int)avMaterials->size();
- }
- else if ((*i).iMaterialIndex >= avMaterials->size() ) {
- // clamp the index
- (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
- }
- }
-
- if (bNeedDefaultMat) {
- // generate a default material
- aiMaterial* pcHelper = new aiMaterial();
-
- // fill in a default material
- int iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- // The face order is absolutely undefined for PLY, so we have to
- // use two-sided rendering to be sure it's ok.
- const int two_sided = 1;
- pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
-
- avMaterials->push_back(pcHelper);
- }
+ bool bNeedDefaultMat = false;
+
+ for (std::vector<PLY::Face>::iterator i = avFaces->begin();i != avFaces->end();++i) {
+ if (0xFFFFFFFF == (*i).iMaterialIndex) {
+ bNeedDefaultMat = true;
+ (*i).iMaterialIndex = (unsigned int)avMaterials->size();
+ }
+ else if ((*i).iMaterialIndex >= avMaterials->size() ) {
+ // clamp the index
+ (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1;
+ }
+ }
+
+ if (bNeedDefaultMat) {
+ // generate a default material
+ aiMaterial* pcHelper = new aiMaterial();
+
+ // fill in a default material
+ int iMode = (int)aiShadingMode_Gouraud;
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.6f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ // The face order is absolutely undefined for PLY, so we have to
+ // use two-sided rendering to be sure it's ok.
+ const int two_sided = 1;
+ pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
+
+ avMaterials->push_back(pcHelper);
+ }
}
// ------------------------------------------------------------------------------------------------
void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut)
{
- ai_assert(NULL != pvOut);
-
- unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
- PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char};
- PLY::ElementInstanceList* pcList = NULL;
- unsigned int cnt = 0;
-
- // serach in the DOM for a vertex entry
- unsigned int _i = 0;
- for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
- i != pcDOM->alElements.end();++i,++_i)
- {
- if (PLY::EEST_Vertex == (*i).eSemantic)
- {
- pcList = &this->pcDOM->alElementData[_i];
-
- // now check whether which normal components are available
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if ((*a).bIsList)continue;
- if (PLY::EST_UTextureCoord == (*a).Semantic)
- {
- cnt++;
- aiPositions[0] = _a;
- aiTypes[0] = (*a).eType;
- }
- else if (PLY::EST_VTextureCoord == (*a).Semantic)
- {
- cnt++;
- aiPositions[1] = _a;
- aiTypes[1] = (*a).eType;
- }
- }
- }
- }
- // check whether we have a valid source for the texture coordinates data
- if (NULL != pcList && 0 != cnt)
- {
- pvOut->reserve(pcList->alInstances.size());
- for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
- i != pcList->alInstances.end();++i)
- {
- // convert the vertices to sp floats
- aiVector2D vOut;
-
- if (0xFFFFFFFF != aiPositions[0])
- {
- vOut.x = PLY::PropertyInstance::ConvertTo<float>(
- (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
- }
-
- if (0xFFFFFFFF != aiPositions[1])
- {
- vOut.y = PLY::PropertyInstance::ConvertTo<float>(
- (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
- }
- // and add them to our nice list
- pvOut->push_back(vOut);
- }
- }
+ ai_assert(NULL != pvOut);
+
+ unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF};
+ PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char};
+ PLY::ElementInstanceList* pcList = NULL;
+ unsigned int cnt = 0;
+
+ // serach in the DOM for a vertex entry
+ unsigned int _i = 0;
+ for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
+ i != pcDOM->alElements.end();++i,++_i)
+ {
+ if (PLY::EEST_Vertex == (*i).eSemantic)
+ {
+ pcList = &this->pcDOM->alElementData[_i];
+
+ // now check whether which normal components are available
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if ((*a).bIsList)continue;
+ if (PLY::EST_UTextureCoord == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[0] = _a;
+ aiTypes[0] = (*a).eType;
+ }
+ else if (PLY::EST_VTextureCoord == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[1] = _a;
+ aiTypes[1] = (*a).eType;
+ }
+ }
+ }
+ }
+ // check whether we have a valid source for the texture coordinates data
+ if (NULL != pcList && 0 != cnt)
+ {
+ pvOut->reserve(pcList->alInstances.size());
+ for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
+ i != pcList->alInstances.end();++i)
+ {
+ // convert the vertices to sp floats
+ aiVector2D vOut;
+
+ if (0xFFFFFFFF != aiPositions[0])
+ {
+ vOut.x = PLY::PropertyInstance::ConvertTo<float>(
+ GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
+ }
+
+ if (0xFFFFFFFF != aiPositions[1])
+ {
+ vOut.y = PLY::PropertyInstance::ConvertTo<float>(
+ GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
+ }
+ // and add them to our nice list
+ pvOut->push_back(vOut);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Try to extract vertices from the PLY DOM
void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals)
{
- ai_assert(NULL != pvOut);
-
- unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
- PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char};
- PLY::ElementInstanceList* pcList = NULL;
- unsigned int cnt = 0;
-
- // serach in the DOM for a vertex entry
- unsigned int _i = 0;
- for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
- i != pcDOM->alElements.end();++i,++_i)
- {
- if (PLY::EEST_Vertex == (*i).eSemantic)
- {
- pcList = &pcDOM->alElementData[_i];
-
- // load normal vectors?
- if (p_bNormals)
- {
- // now check whether which normal components are available
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if ((*a).bIsList)continue;
- if (PLY::EST_XNormal == (*a).Semantic)
- {
- cnt++;
- aiPositions[0] = _a;
- aiTypes[0] = (*a).eType;
- }
- else if (PLY::EST_YNormal == (*a).Semantic)
- {
- cnt++;
- aiPositions[1] = _a;
- aiTypes[1] = (*a).eType;
- }
- else if (PLY::EST_ZNormal == (*a).Semantic)
- {
- cnt++;
- aiPositions[2] = _a;
- aiTypes[2] = (*a).eType;
- }
- }
- }
- // load vertex coordinates
- else
- {
- // now check whether which coordinate sets are available
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if ((*a).bIsList)continue;
- if (PLY::EST_XCoord == (*a).Semantic)
- {
- cnt++;
- aiPositions[0] = _a;
- aiTypes[0] = (*a).eType;
- }
- else if (PLY::EST_YCoord == (*a).Semantic)
- {
- cnt++;
- aiPositions[1] = _a;
- aiTypes[1] = (*a).eType;
- }
- else if (PLY::EST_ZCoord == (*a).Semantic)
- {
- cnt++;
- aiPositions[2] = _a;
- aiTypes[2] = (*a).eType;
- }
- if (3 == cnt)break;
- }
- }
- break;
- }
- }
- // check whether we have a valid source for the vertex data
- if (NULL != pcList && 0 != cnt)
- {
- pvOut->reserve(pcList->alInstances.size());
- for (std::vector<ElementInstance>::const_iterator
- i = pcList->alInstances.begin();
- i != pcList->alInstances.end();++i)
- {
- // convert the vertices to sp floats
- aiVector3D vOut;
-
- if (0xFFFFFFFF != aiPositions[0])
- {
- vOut.x = PLY::PropertyInstance::ConvertTo<float>(
- (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]);
- }
-
- if (0xFFFFFFFF != aiPositions[1])
- {
- vOut.y = PLY::PropertyInstance::ConvertTo<float>(
- (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]);
- }
-
- if (0xFFFFFFFF != aiPositions[2])
- {
- vOut.z = PLY::PropertyInstance::ConvertTo<float>(
- (*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]);
- }
-
- // and add them to our nice list
- pvOut->push_back(vOut);
- }
- }
+ ai_assert(NULL != pvOut);
+
+ unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+ PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char};
+ PLY::ElementInstanceList* pcList = NULL;
+ unsigned int cnt = 0;
+
+ // search in the DOM for a vertex entry
+ unsigned int _i = 0;
+ for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
+ i != pcDOM->alElements.end();++i,++_i)
+ {
+ if (PLY::EEST_Vertex == (*i).eSemantic)
+ {
+ pcList = &pcDOM->alElementData[_i];
+
+ // load normal vectors?
+ if (p_bNormals)
+ {
+ // now check whether which normal components are available
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if ((*a).bIsList)continue;
+ if (PLY::EST_XNormal == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[0] = _a;
+ aiTypes[0] = (*a).eType;
+ }
+ else if (PLY::EST_YNormal == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[1] = _a;
+ aiTypes[1] = (*a).eType;
+ }
+ else if (PLY::EST_ZNormal == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[2] = _a;
+ aiTypes[2] = (*a).eType;
+ }
+ }
+ }
+ // load vertex coordinates
+ else
+ {
+ // now check whether which coordinate sets are available
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if ((*a).bIsList)continue;
+ if (PLY::EST_XCoord == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[0] = _a;
+ aiTypes[0] = (*a).eType;
+ }
+ else if (PLY::EST_YCoord == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[1] = _a;
+ aiTypes[1] = (*a).eType;
+ }
+ else if (PLY::EST_ZCoord == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[2] = _a;
+ aiTypes[2] = (*a).eType;
+ }
+ if (3 == cnt)break;
+ }
+ }
+ break;
+ }
+ }
+ // check whether we have a valid source for the vertex data
+ if (NULL != pcList && 0 != cnt)
+ {
+ pvOut->reserve(pcList->alInstances.size());
+ for (std::vector<ElementInstance>::const_iterator
+ i = pcList->alInstances.begin();
+ i != pcList->alInstances.end();++i)
+ {
+ // convert the vertices to sp floats
+ aiVector3D vOut;
+
+ if (0xFFFFFFFF != aiPositions[0])
+ {
+ vOut.x = PLY::PropertyInstance::ConvertTo<float>(
+ GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]);
+ }
+
+ if (0xFFFFFFFF != aiPositions[1])
+ {
+ vOut.y = PLY::PropertyInstance::ConvertTo<float>(
+ GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]);
+ }
+
+ if (0xFFFFFFFF != aiPositions[2])
+ {
+ vOut.z = PLY::PropertyInstance::ConvertTo<float>(
+ GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]);
+ }
+
+ // and add them to our nice list
+ pvOut->push_back(vOut);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Convert a color component to [0...1]
float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val,
- PLY::EDataType eType)
+ PLY::EDataType eType)
{
- switch (eType)
- {
- case EDT_Float:
- return val.fFloat;
- case EDT_Double:
- return (float)val.fDouble;
-
- case EDT_UChar:
- return (float)val.iUInt / (float)0xFF;
- case EDT_Char:
- return (float)(val.iInt+(0xFF/2)) / (float)0xFF;
- case EDT_UShort:
- return (float)val.iUInt / (float)0xFFFF;
- case EDT_Short:
- return (float)(val.iInt+(0xFFFF/2)) / (float)0xFFFF;
- case EDT_UInt:
- return (float)val.iUInt / (float)0xFFFF;
- case EDT_Int:
- return ((float)val.iInt / (float)0xFF) + 0.5f;
- default: ;
- };
- return 0.0f;
+ switch (eType)
+ {
+ case EDT_Float:
+ return val.fFloat;
+ case EDT_Double:
+ return (float)val.fDouble;
+
+ case EDT_UChar:
+ return (float)val.iUInt / (float)0xFF;
+ case EDT_Char:
+ return (float)(val.iInt+(0xFF/2)) / (float)0xFF;
+ case EDT_UShort:
+ return (float)val.iUInt / (float)0xFFFF;
+ case EDT_Short:
+ return (float)(val.iInt+(0xFFFF/2)) / (float)0xFFFF;
+ case EDT_UInt:
+ return (float)val.iUInt / (float)0xFFFF;
+ case EDT_Int:
+ return ((float)val.iInt / (float)0xFF) + 0.5f;
+ default: ;
+ };
+ return 0.0f;
}
// ------------------------------------------------------------------------------------------------
// Try to extract proper vertex colors from the PLY DOM
void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut)
{
- ai_assert(NULL != pvOut);
-
- unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
- PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc
- unsigned int cnt = 0;
- PLY::ElementInstanceList* pcList = NULL;
-
- // serach in the DOM for a vertex entry
- unsigned int _i = 0;
- for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
- i != pcDOM->alElements.end();++i,++_i)
- {
- if (PLY::EEST_Vertex == (*i).eSemantic)
- {
- pcList = &this->pcDOM->alElementData[_i];
-
- // now check whether which coordinate sets are available
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator
- a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if ((*a).bIsList)continue;
- if (PLY::EST_Red == (*a).Semantic)
- {
- cnt++;
- aiPositions[0] = _a;
- aiTypes[0] = (*a).eType;
- }
- else if (PLY::EST_Green == (*a).Semantic)
- {
- cnt++;
- aiPositions[1] = _a;
- aiTypes[1] = (*a).eType;
- }
- else if (PLY::EST_Blue == (*a).Semantic)
- {
- cnt++;
- aiPositions[2] = _a;
- aiTypes[2] = (*a).eType;
- }
- else if (PLY::EST_Alpha == (*a).Semantic)
- {
- cnt++;
- aiPositions[3] = _a;
- aiTypes[3] = (*a).eType;
- }
- if (4 == cnt)break;
- }
- break;
- }
- }
- // check whether we have a valid source for the vertex data
- if (NULL != pcList && 0 != cnt)
- {
- pvOut->reserve(pcList->alInstances.size());
- for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
- i != pcList->alInstances.end();++i)
- {
- // convert the vertices to sp floats
- aiColor4D vOut;
-
- if (0xFFFFFFFF != aiPositions[0])
- {
- vOut.r = NormalizeColorValue((*i).alProperties[
- aiPositions[0]].avList.front(),aiTypes[0]);
- }
-
- if (0xFFFFFFFF != aiPositions[1])
- {
- vOut.g = NormalizeColorValue((*i).alProperties[
- aiPositions[1]].avList.front(),aiTypes[1]);
- }
-
- if (0xFFFFFFFF != aiPositions[2])
- {
- vOut.b = NormalizeColorValue((*i).alProperties[
- aiPositions[2]].avList.front(),aiTypes[2]);
- }
-
- // assume 1.0 for the alpha channel ifit is not set
- if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
- else
- {
- vOut.a = NormalizeColorValue((*i).alProperties[
- aiPositions[3]].avList.front(),aiTypes[3]);
- }
-
- // and add them to our nice list
- pvOut->push_back(vOut);
- }
- }
+ ai_assert(NULL != pvOut);
+
+ unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
+ PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc
+ unsigned int cnt = 0;
+ PLY::ElementInstanceList* pcList = NULL;
+
+ // serach in the DOM for a vertex entry
+ unsigned int _i = 0;
+ for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
+ i != pcDOM->alElements.end();++i,++_i)
+ {
+ if (PLY::EEST_Vertex == (*i).eSemantic)
+ {
+ pcList = &this->pcDOM->alElementData[_i];
+
+ // now check whether which coordinate sets are available
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator
+ a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if ((*a).bIsList)continue;
+ if (PLY::EST_Red == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[0] = _a;
+ aiTypes[0] = (*a).eType;
+ }
+ else if (PLY::EST_Green == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[1] = _a;
+ aiTypes[1] = (*a).eType;
+ }
+ else if (PLY::EST_Blue == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[2] = _a;
+ aiTypes[2] = (*a).eType;
+ }
+ else if (PLY::EST_Alpha == (*a).Semantic)
+ {
+ cnt++;
+ aiPositions[3] = _a;
+ aiTypes[3] = (*a).eType;
+ }
+ if (4 == cnt)break;
+ }
+ break;
+ }
+ }
+ // check whether we have a valid source for the vertex data
+ if (NULL != pcList && 0 != cnt)
+ {
+ pvOut->reserve(pcList->alInstances.size());
+ for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
+ i != pcList->alInstances.end();++i)
+ {
+ // convert the vertices to sp floats
+ aiColor4D vOut;
+
+ if (0xFFFFFFFF != aiPositions[0])
+ {
+ vOut.r = NormalizeColorValue(GetProperty((*i).alProperties,
+ aiPositions[0]).avList.front(),aiTypes[0]);
+ }
+
+ if (0xFFFFFFFF != aiPositions[1])
+ {
+ vOut.g = NormalizeColorValue(GetProperty((*i).alProperties,
+ aiPositions[1]).avList.front(),aiTypes[1]);
+ }
+
+ if (0xFFFFFFFF != aiPositions[2])
+ {
+ vOut.b = NormalizeColorValue(GetProperty((*i).alProperties,
+ aiPositions[2]).avList.front(),aiTypes[2]);
+ }
+
+ // assume 1.0 for the alpha channel ifit is not set
+ if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f;
+ else
+ {
+ vOut.a = NormalizeColorValue(GetProperty((*i).alProperties,
+ aiPositions[3]).avList.front(),aiTypes[3]);
+ }
+
+ // and add them to our nice list
+ pvOut->push_back(vOut);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Try to extract proper faces from the PLY DOM
void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut)
{
- ai_assert(NULL != pvOut);
-
- PLY::ElementInstanceList* pcList = NULL;
- bool bOne = false;
-
- // index of the vertex index list
- unsigned int iProperty = 0xFFFFFFFF;
- PLY::EDataType eType = EDT_Char;
- bool bIsTristrip = false;
-
- // index of the material index property
- unsigned int iMaterialIndex = 0xFFFFFFFF;
- PLY::EDataType eType2 = EDT_Char;
-
- // serach in the DOM for a face entry
- unsigned int _i = 0;
- for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
- i != pcDOM->alElements.end();++i,++_i)
- {
- // face = unique number of vertex indices
- if (PLY::EEST_Face == (*i).eSemantic)
- {
- pcList = &pcDOM->alElementData[_i];
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if (PLY::EST_VertexIndex == (*a).Semantic)
- {
- // must be a dynamic list!
- if (!(*a).bIsList)continue;
- iProperty = _a;
- bOne = true;
- eType = (*a).eType;
- }
- else if (PLY::EST_MaterialIndex == (*a).Semantic)
- {
- if ((*a).bIsList)continue;
- iMaterialIndex = _a;
- bOne = true;
- eType2 = (*a).eType;
- }
- }
- break;
- }
- // triangle strip
- // TODO: triangle strip and material index support???
- else if (PLY::EEST_TriStrip == (*i).eSemantic)
- {
- // find a list property in this ...
- pcList = &this->pcDOM->alElementData[_i];
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- // must be a dynamic list!
- if (!(*a).bIsList)continue;
- iProperty = _a;
- bOne = true;
- bIsTristrip = true;
- eType = (*a).eType;
- break;
- }
- break;
- }
- }
- // check whether we have at least one per-face information set
- if (pcList && bOne)
- {
- if (!bIsTristrip)
- {
- pvOut->reserve(pcList->alInstances.size());
- for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
- i != pcList->alInstances.end();++i)
- {
- PLY::Face sFace;
-
- // parse the list of vertex indices
- if (0xFFFFFFFF != iProperty)
- {
- const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size();
- sFace.mIndices.resize(iNum);
-
- std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
- (*i).alProperties[iProperty].avList.begin();
-
- for (unsigned int a = 0; a < iNum;++a,++p)
- {
- sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType);
- }
- }
-
- // parse the material index
- if (0xFFFFFFFF != iMaterialIndex)
- {
- sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
- (*i).alProperties[iMaterialIndex].avList.front(),eType2);
- }
- pvOut->push_back(sFace);
- }
- }
- else // triangle strips
- {
- // normally we have only one triangle strip instance where
- // a value of -1 indicates a restart of the strip
- bool flip = false;
- for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
- const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList;
- pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
-
- int aiTable[2] = {-1,-1};
- for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin();a != quak.end();++a) {
- const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
-
- if (-1 == p) {
- // restart the strip ...
- aiTable[0] = aiTable[1] = -1;
- flip = false;
- continue;
- }
- if (-1 == aiTable[0]) {
- aiTable[0] = p;
- continue;
- }
- if (-1 == aiTable[1]) {
- aiTable[1] = p;
- continue;
- }
-
- pvOut->push_back(PLY::Face());
- PLY::Face& sFace = pvOut->back();
- sFace.mIndices[0] = aiTable[0];
- sFace.mIndices[1] = aiTable[1];
- sFace.mIndices[2] = p;
- if ((flip = !flip)) {
- std::swap(sFace.mIndices[0],sFace.mIndices[1]);
- }
-
- aiTable[0] = aiTable[1];
- aiTable[1] = p;
- }
- }
- }
- }
+ ai_assert(NULL != pvOut);
+
+ PLY::ElementInstanceList* pcList = NULL;
+ bool bOne = false;
+
+ // index of the vertex index list
+ unsigned int iProperty = 0xFFFFFFFF;
+ PLY::EDataType eType = EDT_Char;
+ bool bIsTristrip = false;
+
+ // index of the material index property
+ unsigned int iMaterialIndex = 0xFFFFFFFF;
+ PLY::EDataType eType2 = EDT_Char;
+
+ // serach in the DOM for a face entry
+ unsigned int _i = 0;
+ for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin();
+ i != pcDOM->alElements.end();++i,++_i)
+ {
+ // face = unique number of vertex indices
+ if (PLY::EEST_Face == (*i).eSemantic)
+ {
+ pcList = &pcDOM->alElementData[_i];
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if (PLY::EST_VertexIndex == (*a).Semantic)
+ {
+ // must be a dynamic list!
+ if (!(*a).bIsList)continue;
+ iProperty = _a;
+ bOne = true;
+ eType = (*a).eType;
+ }
+ else if (PLY::EST_MaterialIndex == (*a).Semantic)
+ {
+ if ((*a).bIsList)continue;
+ iMaterialIndex = _a;
+ bOne = true;
+ eType2 = (*a).eType;
+ }
+ }
+ break;
+ }
+ // triangle strip
+ // TODO: triangle strip and material index support???
+ else if (PLY::EEST_TriStrip == (*i).eSemantic)
+ {
+ // find a list property in this ...
+ pcList = &this->pcDOM->alElementData[_i];
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ // must be a dynamic list!
+ if (!(*a).bIsList)continue;
+ iProperty = _a;
+ bOne = true;
+ bIsTristrip = true;
+ eType = (*a).eType;
+ break;
+ }
+ break;
+ }
+ }
+ // check whether we have at least one per-face information set
+ if (pcList && bOne)
+ {
+ if (!bIsTristrip)
+ {
+ pvOut->reserve(pcList->alInstances.size());
+ for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();
+ i != pcList->alInstances.end();++i)
+ {
+ PLY::Face sFace;
+
+ // parse the list of vertex indices
+ if (0xFFFFFFFF != iProperty)
+ {
+ const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size();
+ sFace.mIndices.resize(iNum);
+
+ std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
+ GetProperty((*i).alProperties, iProperty).avList.begin();
+
+ for (unsigned int a = 0; a < iNum;++a,++p)
+ {
+ sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType);
+ }
+ }
+
+ // parse the material index
+ if (0xFFFFFFFF != iMaterialIndex)
+ {
+ sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>(
+ GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2);
+ }
+ pvOut->push_back(sFace);
+ }
+ }
+ else // triangle strips
+ {
+ // normally we have only one triangle strip instance where
+ // a value of -1 indicates a restart of the strip
+ bool flip = false;
+ for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
+ const std::vector<PLY::PropertyInstance::ValueUnion>& quak = GetProperty((*i).alProperties, iProperty).avList;
+ pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u));
+
+ int aiTable[2] = {-1,-1};
+ for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin();a != quak.end();++a) {
+ const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType);
+
+ if (-1 == p) {
+ // restart the strip ...
+ aiTable[0] = aiTable[1] = -1;
+ flip = false;
+ continue;
+ }
+ if (-1 == aiTable[0]) {
+ aiTable[0] = p;
+ continue;
+ }
+ if (-1 == aiTable[1]) {
+ aiTable[1] = p;
+ continue;
+ }
+
+ pvOut->push_back(PLY::Face());
+ PLY::Face& sFace = pvOut->back();
+ sFace.mIndices[0] = aiTable[0];
+ sFace.mIndices[1] = aiTable[1];
+ sFace.mIndices[2] = p;
+ if ((flip = !flip)) {
+ std::swap(sFace.mIndices[0],sFace.mIndices[1]);
+ }
+
+ aiTable[0] = aiTable[1];
+ aiTable[1] = p;
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Get a RGBA color in [0...1] range
void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList,
- unsigned int aiPositions[4],
- PLY::EDataType aiTypes[4],
- aiColor4D* clrOut)
+ unsigned int aiPositions[4],
+ PLY::EDataType aiTypes[4],
+ aiColor4D* clrOut)
{
- ai_assert(NULL != clrOut);
-
- if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
- else
- {
- clrOut->r = NormalizeColorValue(avList[
- aiPositions[0]].avList.front(),aiTypes[0]);
- }
-
- if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
- else
- {
- clrOut->g = NormalizeColorValue(avList[
- aiPositions[1]].avList.front(),aiTypes[1]);
- }
-
- if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
- else
- {
- clrOut->b = NormalizeColorValue(avList[
- aiPositions[2]].avList.front(),aiTypes[2]);
- }
-
- // assume 1.0 for the alpha channel ifit is not set
- if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
- else
- {
- clrOut->a = NormalizeColorValue(avList[
- aiPositions[3]].avList.front(),aiTypes[3]);
- }
+ ai_assert(NULL != clrOut);
+
+ if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f;
+ else
+ {
+ clrOut->r = NormalizeColorValue(GetProperty(avList,
+ aiPositions[0]).avList.front(),aiTypes[0]);
+ }
+
+ if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f;
+ else
+ {
+ clrOut->g = NormalizeColorValue(GetProperty(avList,
+ aiPositions[1]).avList.front(),aiTypes[1]);
+ }
+
+ if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f;
+ else
+ {
+ clrOut->b = NormalizeColorValue(GetProperty(avList,
+ aiPositions[2]).avList.front(),aiTypes[2]);
+ }
+
+ // assume 1.0 for the alpha channel ifit is not set
+ if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f;
+ else
+ {
+ clrOut->a = NormalizeColorValue(GetProperty(avList,
+ aiPositions[3]).avList.front(),aiTypes[3]);
+ }
}
// ------------------------------------------------------------------------------------------------
// Extract a material from the PLY DOM
void PLYImporter::LoadMaterial(std::vector<aiMaterial*>* pvOut)
{
- ai_assert(NULL != pvOut);
-
- // diffuse[4], specular[4], ambient[4]
- // rgba order
- unsigned int aaiPositions[3][4] = {
-
- {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
- {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
- {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
- };
-
- PLY::EDataType aaiTypes[3][4] = {
- {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
- {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
- {EDT_Char,EDT_Char,EDT_Char,EDT_Char}
- };
- PLY::ElementInstanceList* pcList = NULL;
-
- unsigned int iPhong = 0xFFFFFFFF;
- PLY::EDataType ePhong = EDT_Char;
-
- unsigned int iOpacity = 0xFFFFFFFF;
- PLY::EDataType eOpacity = EDT_Char;
-
- // serach in the DOM for a vertex entry
- unsigned int _i = 0;
- for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
- i != this->pcDOM->alElements.end();++i,++_i)
- {
- if (PLY::EEST_Material == (*i).eSemantic)
- {
- pcList = &this->pcDOM->alElementData[_i];
-
- // now check whether which coordinate sets are available
- unsigned int _a = 0;
- for (std::vector<PLY::Property>::const_iterator
- a = (*i).alProperties.begin();
- a != (*i).alProperties.end();++a,++_a)
- {
- if ((*a).bIsList)continue;
-
- // pohng specularity -----------------------------------
- if (PLY::EST_PhongPower == (*a).Semantic)
- {
- iPhong = _a;
- ePhong = (*a).eType;
- }
-
- // general opacity -----------------------------------
- if (PLY::EST_Opacity == (*a).Semantic)
- {
- iOpacity = _a;
- eOpacity = (*a).eType;
- }
-
- // diffuse color channels -----------------------------------
- if (PLY::EST_DiffuseRed == (*a).Semantic)
- {
- aaiPositions[0][0] = _a;
- aaiTypes[0][0] = (*a).eType;
- }
- else if (PLY::EST_DiffuseGreen == (*a).Semantic)
- {
- aaiPositions[0][1] = _a;
- aaiTypes[0][1] = (*a).eType;
- }
- else if (PLY::EST_DiffuseBlue == (*a).Semantic)
- {
- aaiPositions[0][2] = _a;
- aaiTypes[0][2] = (*a).eType;
- }
- else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
- {
- aaiPositions[0][3] = _a;
- aaiTypes[0][3] = (*a).eType;
- }
- // specular color channels -----------------------------------
- else if (PLY::EST_SpecularRed == (*a).Semantic)
- {
- aaiPositions[1][0] = _a;
- aaiTypes[1][0] = (*a).eType;
- }
- else if (PLY::EST_SpecularGreen == (*a).Semantic)
- {
- aaiPositions[1][1] = _a;
- aaiTypes[1][1] = (*a).eType;
- }
- else if (PLY::EST_SpecularBlue == (*a).Semantic)
- {
- aaiPositions[1][2] = _a;
- aaiTypes[1][2] = (*a).eType;
- }
- else if (PLY::EST_SpecularAlpha == (*a).Semantic)
- {
- aaiPositions[1][3] = _a;
- aaiTypes[1][3] = (*a).eType;
- }
- // ambient color channels -----------------------------------
- else if (PLY::EST_AmbientRed == (*a).Semantic)
- {
- aaiPositions[2][0] = _a;
- aaiTypes[2][0] = (*a).eType;
- }
- else if (PLY::EST_AmbientGreen == (*a).Semantic)
- {
- aaiPositions[2][1] = _a;
- aaiTypes[2][1] = (*a).eType;
- }
- else if (PLY::EST_AmbientBlue == (*a).Semantic)
- {
- aaiPositions[2][2] = _a;
- aaiTypes[2][2] = (*a).eType;
- }
- else if (PLY::EST_AmbientAlpha == (*a).Semantic)
- {
- aaiPositions[2][3] = _a;
- aaiTypes[2][3] = (*a).eType;
- }
- }
- break;
- }
- }
- // check whether we have a valid source for the material data
- if (NULL != pcList) {
- for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
- aiColor4D clrOut;
- aiMaterial* pcHelper = new aiMaterial();
-
- // build the diffuse material color
- GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
- pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
-
- // build the specular material color
- GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
- pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
-
- // build the ambient material color
- GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
- pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
-
- // handle phong power and shading mode
- int iMode;
- if (0xFFFFFFFF != iPhong) {
- float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong);
-
- // if shininess is 0 (and the pow() calculation would therefore always
- // become 1, not depending on the angle), use gouraud lighting
- if (fSpec) {
- // scale this with 15 ... hopefully this is correct
- fSpec *= 15;
- pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS);
-
- iMode = (int)aiShadingMode_Phong;
- }
- else iMode = (int)aiShadingMode_Gouraud;
- }
- else iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- // handle opacity
- if (0xFFFFFFFF != iOpacity) {
- float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity);
- pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
- }
-
- // The face order is absolutely undefined for PLY, so we have to
- // use two-sided rendering to be sure it's ok.
- const int two_sided = 1;
- pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
-
- // add the newly created material instance to the list
- pvOut->push_back(pcHelper);
- }
- }
+ ai_assert(NULL != pvOut);
+
+ // diffuse[4], specular[4], ambient[4]
+ // rgba order
+ unsigned int aaiPositions[3][4] = {
+
+ {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+ {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+ {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF},
+ };
+
+ PLY::EDataType aaiTypes[3][4] = {
+ {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
+ {EDT_Char,EDT_Char,EDT_Char,EDT_Char},
+ {EDT_Char,EDT_Char,EDT_Char,EDT_Char}
+ };
+ PLY::ElementInstanceList* pcList = NULL;
+
+ unsigned int iPhong = 0xFFFFFFFF;
+ PLY::EDataType ePhong = EDT_Char;
+
+ unsigned int iOpacity = 0xFFFFFFFF;
+ PLY::EDataType eOpacity = EDT_Char;
+
+ // serach in the DOM for a vertex entry
+ unsigned int _i = 0;
+ for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin();
+ i != this->pcDOM->alElements.end();++i,++_i)
+ {
+ if (PLY::EEST_Material == (*i).eSemantic)
+ {
+ pcList = &this->pcDOM->alElementData[_i];
+
+ // now check whether which coordinate sets are available
+ unsigned int _a = 0;
+ for (std::vector<PLY::Property>::const_iterator
+ a = (*i).alProperties.begin();
+ a != (*i).alProperties.end();++a,++_a)
+ {
+ if ((*a).bIsList)continue;
+
+ // pohng specularity -----------------------------------
+ if (PLY::EST_PhongPower == (*a).Semantic)
+ {
+ iPhong = _a;
+ ePhong = (*a).eType;
+ }
+
+ // general opacity -----------------------------------
+ if (PLY::EST_Opacity == (*a).Semantic)
+ {
+ iOpacity = _a;
+ eOpacity = (*a).eType;
+ }
+
+ // diffuse color channels -----------------------------------
+ if (PLY::EST_DiffuseRed == (*a).Semantic)
+ {
+ aaiPositions[0][0] = _a;
+ aaiTypes[0][0] = (*a).eType;
+ }
+ else if (PLY::EST_DiffuseGreen == (*a).Semantic)
+ {
+ aaiPositions[0][1] = _a;
+ aaiTypes[0][1] = (*a).eType;
+ }
+ else if (PLY::EST_DiffuseBlue == (*a).Semantic)
+ {
+ aaiPositions[0][2] = _a;
+ aaiTypes[0][2] = (*a).eType;
+ }
+ else if (PLY::EST_DiffuseAlpha == (*a).Semantic)
+ {
+ aaiPositions[0][3] = _a;
+ aaiTypes[0][3] = (*a).eType;
+ }
+ // specular color channels -----------------------------------
+ else if (PLY::EST_SpecularRed == (*a).Semantic)
+ {
+ aaiPositions[1][0] = _a;
+ aaiTypes[1][0] = (*a).eType;
+ }
+ else if (PLY::EST_SpecularGreen == (*a).Semantic)
+ {
+ aaiPositions[1][1] = _a;
+ aaiTypes[1][1] = (*a).eType;
+ }
+ else if (PLY::EST_SpecularBlue == (*a).Semantic)
+ {
+ aaiPositions[1][2] = _a;
+ aaiTypes[1][2] = (*a).eType;
+ }
+ else if (PLY::EST_SpecularAlpha == (*a).Semantic)
+ {
+ aaiPositions[1][3] = _a;
+ aaiTypes[1][3] = (*a).eType;
+ }
+ // ambient color channels -----------------------------------
+ else if (PLY::EST_AmbientRed == (*a).Semantic)
+ {
+ aaiPositions[2][0] = _a;
+ aaiTypes[2][0] = (*a).eType;
+ }
+ else if (PLY::EST_AmbientGreen == (*a).Semantic)
+ {
+ aaiPositions[2][1] = _a;
+ aaiTypes[2][1] = (*a).eType;
+ }
+ else if (PLY::EST_AmbientBlue == (*a).Semantic)
+ {
+ aaiPositions[2][2] = _a;
+ aaiTypes[2][2] = (*a).eType;
+ }
+ else if (PLY::EST_AmbientAlpha == (*a).Semantic)
+ {
+ aaiPositions[2][3] = _a;
+ aaiTypes[2][3] = (*a).eType;
+ }
+ }
+ break;
+ }
+ }
+ // check whether we have a valid source for the material data
+ if (NULL != pcList) {
+ for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) {
+ aiColor4D clrOut;
+ aiMaterial* pcHelper = new aiMaterial();
+
+ // build the diffuse material color
+ GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut);
+ pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ // build the specular material color
+ GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut);
+ pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR);
+
+ // build the ambient material color
+ GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut);
+ pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT);
+
+ // handle phong power and shading mode
+ int iMode;
+ if (0xFFFFFFFF != iPhong) {
+ float fSpec = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong);
+
+ // if shininess is 0 (and the pow() calculation would therefore always
+ // become 1, not depending on the angle), use gouraud lighting
+ if (fSpec) {
+ // scale this with 15 ... hopefully this is correct
+ fSpec *= 15;
+ pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS);
+
+ iMode = (int)aiShadingMode_Phong;
+ }
+ else iMode = (int)aiShadingMode_Gouraud;
+ }
+ else iMode = (int)aiShadingMode_Gouraud;
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ // handle opacity
+ if (0xFFFFFFFF != iOpacity) {
+ float fOpacity = PLY::PropertyInstance::ConvertTo<float>(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity);
+ pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY);
+ }
+
+ // The face order is absolutely undefined for PLY, so we have to
+ // use two-sided rendering to be sure it's ok.
+ const int two_sided = 1;
+ pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED);
+
+ // add the newly created material instance to the list
+ pvOut->push_back(pcHelper);
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
diff --git a/src/3rdparty/assimp/code/PlyLoader.h b/src/3rdparty/assimp/code/PlyLoader.h
index 8cac1eb0b..71b483c57 100644
--- a/src/3rdparty/assimp/code/PlyLoader.h
+++ b/src/3rdparty/assimp/code/PlyLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,13 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_PLYLOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+#include "PlyParser.h"
+#include <vector>
struct aiNode;
+struct aiMaterial;
+struct aiMesh;
-#include "PlyParser.h"
-
-namespace Assimp {
+namespace Assimp {
using namespace PLY;
@@ -62,107 +64,107 @@ using namespace PLY;
class PLYImporter : public BaseImporter
{
public:
- PLYImporter();
- ~PLYImporter();
+ PLYImporter();
+ ~PLYImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Extract vertices from the DOM
- */
- void LoadVertices(std::vector<aiVector3D>* pvOut,
- bool p_bNormals = false);
-
- // -------------------------------------------------------------------
- /** Extract vertex color channels from the DOM
- */
- void LoadVertexColor(std::vector<aiColor4D>* pvOut);
-
- // -------------------------------------------------------------------
- /** Extract texture coordinate channels from the DOM
- */
- void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
-
- // -------------------------------------------------------------------
- /** Extract a face list from the DOM
- */
- void LoadFaces(std::vector<PLY::Face>* pvOut);
-
- // -------------------------------------------------------------------
- /** Extract a material list from the DOM
- */
- void LoadMaterial(std::vector<aiMaterial*>* pvOut);
-
-
- // -------------------------------------------------------------------
- /** Validate material indices, replace default material identifiers
- */
- void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
- std::vector<aiMaterial*>* avMaterials);
-
-
- // -------------------------------------------------------------------
- /** Convert all meshes into our ourer representation
- */
- void ConvertMeshes(std::vector<PLY::Face>* avFaces,
- const std::vector<aiVector3D>* avPositions,
- const std::vector<aiVector3D>* avNormals,
- const std::vector<aiColor4D>* avColors,
- const std::vector<aiVector2D>* avTexCoords,
- const std::vector<aiMaterial*>* avMaterials,
- std::vector<aiMesh*>* avOut);
-
-
- // -------------------------------------------------------------------
- /** Static helper to parse a color from four single channels in
- */
- static void GetMaterialColor(
- const std::vector<PLY::PropertyInstance>& avList,
- unsigned int aiPositions[4],
- PLY::EDataType aiTypes[4],
- aiColor4D* clrOut);
-
-
- // -------------------------------------------------------------------
- /** Static helper to parse a color channel value. The input value
- * is normalized to 0-1.
- */
- static float NormalizeColorValue (
- PLY::PropertyInstance::ValueUnion val,
- PLY::EDataType eType);
-
-
- /** Buffer to hold the loaded file */
- unsigned char* mBuffer;
-
- /** Document object model representation extracted from the file */
- PLY::DOM* pcDOM;
+ // -------------------------------------------------------------------
+ /** Extract vertices from the DOM
+ */
+ void LoadVertices(std::vector<aiVector3D>* pvOut,
+ bool p_bNormals = false);
+
+ // -------------------------------------------------------------------
+ /** Extract vertex color channels from the DOM
+ */
+ void LoadVertexColor(std::vector<aiColor4D>* pvOut);
+
+ // -------------------------------------------------------------------
+ /** Extract texture coordinate channels from the DOM
+ */
+ void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
+
+ // -------------------------------------------------------------------
+ /** Extract a face list from the DOM
+ */
+ void LoadFaces(std::vector<PLY::Face>* pvOut);
+
+ // -------------------------------------------------------------------
+ /** Extract a material list from the DOM
+ */
+ void LoadMaterial(std::vector<aiMaterial*>* pvOut);
+
+
+ // -------------------------------------------------------------------
+ /** Validate material indices, replace default material identifiers
+ */
+ void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
+ std::vector<aiMaterial*>* avMaterials);
+
+
+ // -------------------------------------------------------------------
+ /** Convert all meshes into our ourer representation
+ */
+ void ConvertMeshes(std::vector<PLY::Face>* avFaces,
+ const std::vector<aiVector3D>* avPositions,
+ const std::vector<aiVector3D>* avNormals,
+ const std::vector<aiColor4D>* avColors,
+ const std::vector<aiVector2D>* avTexCoords,
+ const std::vector<aiMaterial*>* avMaterials,
+ std::vector<aiMesh*>* avOut);
+
+
+ // -------------------------------------------------------------------
+ /** Static helper to parse a color from four single channels in
+ */
+ static void GetMaterialColor(
+ const std::vector<PLY::PropertyInstance>& avList,
+ unsigned int aiPositions[4],
+ PLY::EDataType aiTypes[4],
+ aiColor4D* clrOut);
+
+
+ // -------------------------------------------------------------------
+ /** Static helper to parse a color channel value. The input value
+ * is normalized to 0-1.
+ */
+ static float NormalizeColorValue (
+ PLY::PropertyInstance::ValueUnion val,
+ PLY::EDataType eType);
+
+
+ /** Buffer to hold the loaded file */
+ unsigned char* mBuffer;
+
+ /** Document object model representation extracted from the file */
+ PLY::DOM* pcDOM;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/PlyParser.cpp b/src/3rdparty/assimp/code/PlyParser.cpp
index a16853583..06e4038f4 100644
--- a/src/3rdparty/assimp/code/PlyParser.cpp
+++ b/src/3rdparty/assimp/code/PlyParser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,898 +25,904 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the PLY parser class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER
#include "PlyLoader.h"
#include "fast_atof.h"
+#include <assimp/DefaultLogger.hpp>
+#include "ByteSwapper.h"
+
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
- PLY::EDataType eOut = PLY::EDT_INVALID;
-
- if (TokenMatch(pCur,"char",4) ||
- TokenMatch(pCur,"int8",4))
- {
- eOut = PLY::EDT_Char;
- }
- else if (TokenMatch(pCur,"uchar",5) ||
- TokenMatch(pCur,"uint8",5))
- {
- eOut = PLY::EDT_UChar;
- }
- else if (TokenMatch(pCur,"short",5) ||
- TokenMatch(pCur,"int16",5))
- {
- eOut = PLY::EDT_Short;
- }
- else if (TokenMatch(pCur,"ushort",6) ||
- TokenMatch(pCur,"uint16",6))
- {
- eOut = PLY::EDT_UShort;
- }
- else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3))
- {
- eOut = PLY::EDT_Int;
- }
- else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4))
- {
- eOut = PLY::EDT_UInt;
- }
- else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7))
- {
- eOut = PLY::EDT_Float;
- }
- else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) ||
- TokenMatch(pCur,"float64",7))
- {
- eOut = PLY::EDT_Double;
- }
- if (PLY::EDT_INVALID == eOut)
- {
- DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
- }
- *pCurOut = pCur;
- return eOut;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+ PLY::EDataType eOut = PLY::EDT_INVALID;
+
+ if (TokenMatch(pCur,"char",4) ||
+ TokenMatch(pCur,"int8",4))
+ {
+ eOut = PLY::EDT_Char;
+ }
+ else if (TokenMatch(pCur,"uchar",5) ||
+ TokenMatch(pCur,"uint8",5))
+ {
+ eOut = PLY::EDT_UChar;
+ }
+ else if (TokenMatch(pCur,"short",5) ||
+ TokenMatch(pCur,"int16",5))
+ {
+ eOut = PLY::EDT_Short;
+ }
+ else if (TokenMatch(pCur,"ushort",6) ||
+ TokenMatch(pCur,"uint16",6))
+ {
+ eOut = PLY::EDT_UShort;
+ }
+ else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3))
+ {
+ eOut = PLY::EDT_Int;
+ }
+ else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4))
+ {
+ eOut = PLY::EDT_UInt;
+ }
+ else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7))
+ {
+ eOut = PLY::EDT_Float;
+ }
+ else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) ||
+ TokenMatch(pCur,"float64",7))
+ {
+ eOut = PLY::EDT_Double;
+ }
+ if (PLY::EDT_INVALID == eOut)
+ {
+ DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
+ }
+ *pCurOut = pCur;
+ return eOut;
}
// ------------------------------------------------------------------------------------------------
PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
-
- PLY::ESemantic eOut = PLY::EST_INVALID;
- if (TokenMatch(pCur,"red",3))
- {
- eOut = PLY::EST_Red;
- }
- else if (TokenMatch(pCur,"green",5))
- {
- eOut = PLY::EST_Green;
- }
- else if (TokenMatch(pCur,"blue",4))
- {
- eOut = PLY::EST_Blue;
- }
- else if (TokenMatch(pCur,"alpha",5))
- {
- eOut = PLY::EST_Alpha;
- }
- else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14))
- {
- eOut = PLY::EST_VertexIndex;
- }
- else if (TokenMatch(pCur,"material_index",14))
- {
- eOut = PLY::EST_MaterialIndex;
- }
- else if (TokenMatch(pCur,"ambient_red",11))
- {
- eOut = PLY::EST_AmbientRed;
- }
- else if (TokenMatch(pCur,"ambient_green",13))
- {
- eOut = PLY::EST_AmbientGreen;
- }
- else if (TokenMatch(pCur,"ambient_blue",12))
- {
- eOut = PLY::EST_AmbientBlue;
- }
- else if (TokenMatch(pCur,"ambient_alpha",13))
- {
- eOut = PLY::EST_AmbientAlpha;
- }
- else if (TokenMatch(pCur,"diffuse_red",11))
- {
- eOut = PLY::EST_DiffuseRed;
- }
- else if (TokenMatch(pCur,"diffuse_green",13))
- {
- eOut = PLY::EST_DiffuseGreen;
- }
- else if (TokenMatch(pCur,"diffuse_blue",12))
- {
- eOut = PLY::EST_DiffuseBlue;
- }
- else if (TokenMatch(pCur,"diffuse_alpha",13))
- {
- eOut = PLY::EST_DiffuseAlpha;
- }
- else if (TokenMatch(pCur,"specular_red",12))
- {
- eOut = PLY::EST_SpecularRed;
- }
- else if (TokenMatch(pCur,"specular_green",14))
- {
- eOut = PLY::EST_SpecularGreen;
- }
- else if (TokenMatch(pCur,"specular_blue",13))
- {
- eOut = PLY::EST_SpecularBlue;
- }
- else if (TokenMatch(pCur,"specular_alpha",14))
- {
- eOut = PLY::EST_SpecularAlpha;
- }
- else if (TokenMatch(pCur,"opacity",7))
- {
- eOut = PLY::EST_Opacity;
- }
- else if (TokenMatch(pCur,"specular_power",6))
- {
- eOut = PLY::EST_PhongPower;
- }
- else if (TokenMatch(pCur,"r",1))
- {
- eOut = PLY::EST_Red;
- }
- else if (TokenMatch(pCur,"g",1))
- {
- eOut = PLY::EST_Green;
- }
- else if (TokenMatch(pCur,"b",1))
- {
- eOut = PLY::EST_Blue;
- }
- // NOTE: Blender3D exports texture coordinates as s,t tuples
- else if (TokenMatch(pCur,"u",1) || TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2))
- {
- eOut = PLY::EST_UTextureCoord;
- }
- else if (TokenMatch(pCur,"v",1) || TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2))
- {
- eOut = PLY::EST_VTextureCoord;
- }
- else if (TokenMatch(pCur,"x",1))
- {
- eOut = PLY::EST_XCoord;
- }
- else if (TokenMatch(pCur,"y",1))
- {
- eOut = PLY::EST_YCoord;
- }
- else if (TokenMatch(pCur,"z",1))
- {
- eOut = PLY::EST_ZCoord;
- }
- else if (TokenMatch(pCur,"nx",2))
- {
- eOut = PLY::EST_XNormal;
- }
- else if (TokenMatch(pCur,"ny",2))
- {
- eOut = PLY::EST_YNormal;
- }
- else if (TokenMatch(pCur,"nz",2))
- {
- eOut = PLY::EST_ZNormal;
- }
- else
- {
- DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
- SkipLine(&pCur);
- }
- *pCurOut = pCur;
- return eOut;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+
+ PLY::ESemantic eOut = PLY::EST_INVALID;
+ if (TokenMatch(pCur,"red",3))
+ {
+ eOut = PLY::EST_Red;
+ }
+ else if (TokenMatch(pCur,"green",5))
+ {
+ eOut = PLY::EST_Green;
+ }
+ else if (TokenMatch(pCur,"blue",4))
+ {
+ eOut = PLY::EST_Blue;
+ }
+ else if (TokenMatch(pCur,"alpha",5))
+ {
+ eOut = PLY::EST_Alpha;
+ }
+ else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14))
+ {
+ eOut = PLY::EST_VertexIndex;
+ }
+ else if (TokenMatch(pCur,"material_index",14))
+ {
+ eOut = PLY::EST_MaterialIndex;
+ }
+ else if (TokenMatch(pCur,"ambient_red",11))
+ {
+ eOut = PLY::EST_AmbientRed;
+ }
+ else if (TokenMatch(pCur,"ambient_green",13))
+ {
+ eOut = PLY::EST_AmbientGreen;
+ }
+ else if (TokenMatch(pCur,"ambient_blue",12))
+ {
+ eOut = PLY::EST_AmbientBlue;
+ }
+ else if (TokenMatch(pCur,"ambient_alpha",13))
+ {
+ eOut = PLY::EST_AmbientAlpha;
+ }
+ else if (TokenMatch(pCur,"diffuse_red",11))
+ {
+ eOut = PLY::EST_DiffuseRed;
+ }
+ else if (TokenMatch(pCur,"diffuse_green",13))
+ {
+ eOut = PLY::EST_DiffuseGreen;
+ }
+ else if (TokenMatch(pCur,"diffuse_blue",12))
+ {
+ eOut = PLY::EST_DiffuseBlue;
+ }
+ else if (TokenMatch(pCur,"diffuse_alpha",13))
+ {
+ eOut = PLY::EST_DiffuseAlpha;
+ }
+ else if (TokenMatch(pCur,"specular_red",12))
+ {
+ eOut = PLY::EST_SpecularRed;
+ }
+ else if (TokenMatch(pCur,"specular_green",14))
+ {
+ eOut = PLY::EST_SpecularGreen;
+ }
+ else if (TokenMatch(pCur,"specular_blue",13))
+ {
+ eOut = PLY::EST_SpecularBlue;
+ }
+ else if (TokenMatch(pCur,"specular_alpha",14))
+ {
+ eOut = PLY::EST_SpecularAlpha;
+ }
+ else if (TokenMatch(pCur,"opacity",7))
+ {
+ eOut = PLY::EST_Opacity;
+ }
+ else if (TokenMatch(pCur,"specular_power",14))
+ {
+ eOut = PLY::EST_PhongPower;
+ }
+ else if (TokenMatch(pCur,"r",1))
+ {
+ eOut = PLY::EST_Red;
+ }
+ else if (TokenMatch(pCur,"g",1))
+ {
+ eOut = PLY::EST_Green;
+ }
+ else if (TokenMatch(pCur,"b",1))
+ {
+ eOut = PLY::EST_Blue;
+ }
+ // NOTE: Blender3D exports texture coordinates as s,t tuples
+ else if (TokenMatch(pCur,"u",1) || TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2))
+ {
+ eOut = PLY::EST_UTextureCoord;
+ }
+ else if (TokenMatch(pCur,"v",1) || TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2))
+ {
+ eOut = PLY::EST_VTextureCoord;
+ }
+ else if (TokenMatch(pCur,"x",1))
+ {
+ eOut = PLY::EST_XCoord;
+ }
+ else if (TokenMatch(pCur,"y",1))
+ {
+ eOut = PLY::EST_YCoord;
+ }
+ else if (TokenMatch(pCur,"z",1))
+ {
+ eOut = PLY::EST_ZCoord;
+ }
+ else if (TokenMatch(pCur,"nx",2))
+ {
+ eOut = PLY::EST_XNormal;
+ }
+ else if (TokenMatch(pCur,"ny",2))
+ {
+ eOut = PLY::EST_YNormal;
+ }
+ else if (TokenMatch(pCur,"nz",2))
+ {
+ eOut = PLY::EST_ZNormal;
+ }
+ else
+ {
+ DefaultLogger::get()->info("Found unknown property semantic in file. This is ok");
+ SkipLine(&pCur);
+ }
+ *pCurOut = pCur;
+ return eOut;
}
// ------------------------------------------------------------------------------------------------
bool PLY::Property::ParseProperty (const char* pCur,
- const char** pCurOut,
- PLY::Property* pOut)
+ const char** pCurOut,
+ PLY::Property* pOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
-
- // Forms supported:
- // "property float x"
- // "property list uchar int vertex_index"
- *pCurOut = pCur;
-
- // skip leading spaces
- if (!SkipSpaces(pCur,&pCur))return false;
-
- // skip the "property" string at the beginning
- if (!TokenMatch(pCur,"property",8))
- {
- // seems not to be a valid property entry
- return false;
- }
- // get next word
- if (!SkipSpaces(pCur,&pCur))return false;
- if (TokenMatch(pCur,"list",4))
- {
- pOut->bIsList = true;
-
- // seems to be a list.
- if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur)))
- {
- // unable to parse list size data type
- SkipLine(pCur,&pCur);
- *pCurOut = pCur;
- return false;
- }
- if (!SkipSpaces(pCur,&pCur))return false;
- if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
- {
- // unable to parse list data type
- SkipLine(pCur,&pCur);
- *pCurOut = pCur;
- return false;
- }
- }
- else
- {
- if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
- {
- // unable to parse data type. Skip the property
- SkipLine(pCur,&pCur);
- *pCurOut = pCur;
- return false;
- }
- }
-
- if (!SkipSpaces(pCur,&pCur))return false;
- const char* szCur = pCur;
- pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
-
- if (PLY::EST_INVALID == pOut->Semantic)
- {
- // store the name of the semantic
- uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
-
- DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
- pOut->szName = std::string(szCur,iDiff);
- }
-
- SkipSpacesAndLineEnd(pCur,&pCur);
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+
+ // Forms supported:
+ // "property float x"
+ // "property list uchar int vertex_index"
+ *pCurOut = pCur;
+
+ // skip leading spaces
+ if (!SkipSpaces(pCur,&pCur))return false;
+
+ // skip the "property" string at the beginning
+ if (!TokenMatch(pCur,"property",8))
+ {
+ // seems not to be a valid property entry
+ return false;
+ }
+ // get next word
+ if (!SkipSpaces(pCur,&pCur))return false;
+ if (TokenMatch(pCur,"list",4))
+ {
+ pOut->bIsList = true;
+
+ // seems to be a list.
+ if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur)))
+ {
+ // unable to parse list size data type
+ SkipLine(pCur,&pCur);
+ *pCurOut = pCur;
+ return false;
+ }
+ if (!SkipSpaces(pCur,&pCur))return false;
+ if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
+ {
+ // unable to parse list data type
+ SkipLine(pCur,&pCur);
+ *pCurOut = pCur;
+ return false;
+ }
+ }
+ else
+ {
+ if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur)))
+ {
+ // unable to parse data type. Skip the property
+ SkipLine(pCur,&pCur);
+ *pCurOut = pCur;
+ return false;
+ }
+ }
+
+ if (!SkipSpaces(pCur,&pCur))return false;
+ const char* szCur = pCur;
+ pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur);
+
+ if (PLY::EST_INVALID == pOut->Semantic)
+ {
+ // store the name of the semantic
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+
+ DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK");
+ pOut->szName = std::string(szCur,iDiff);
+ }
+
+ SkipSpacesAndLineEnd(pCur,&pCur);
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur,
- const char** pCurOut)
+ const char** pCurOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
- PLY::EElementSemantic eOut = PLY::EEST_INVALID;
- if (TokenMatch(pCur,"vertex",6))
- {
- eOut = PLY::EEST_Vertex;
- }
- else if (TokenMatch(pCur,"face",4))
- {
- eOut = PLY::EEST_Face;
- }
+ ai_assert(NULL != pCur && NULL != pCurOut);
+ PLY::EElementSemantic eOut = PLY::EEST_INVALID;
+ if (TokenMatch(pCur,"vertex",6))
+ {
+ eOut = PLY::EEST_Vertex;
+ }
+ else if (TokenMatch(pCur,"face",4))
+ {
+ eOut = PLY::EEST_Face;
+ }
#if 0
- // TODO: maybe implement this?
- else if (TokenMatch(pCur,"range_grid",10))
- {
- eOut = PLY::EEST_Face;
- }
+ // TODO: maybe implement this?
+ else if (TokenMatch(pCur,"range_grid",10))
+ {
+ eOut = PLY::EEST_Face;
+ }
#endif
- else if (TokenMatch(pCur,"tristrips",9))
- {
- eOut = PLY::EEST_TriStrip;
- }
- else if (TokenMatch(pCur,"edge",4))
- {
- eOut = PLY::EEST_Edge;
- }
- else if (TokenMatch(pCur,"material",8))
- {
- eOut = PLY::EEST_Material;
- }
- *pCurOut = pCur;
- return eOut;
+ else if (TokenMatch(pCur,"tristrips",9))
+ {
+ eOut = PLY::EEST_TriStrip;
+ }
+ else if (TokenMatch(pCur,"edge",4))
+ {
+ eOut = PLY::EEST_Edge;
+ }
+ else if (TokenMatch(pCur,"material",8))
+ {
+ eOut = PLY::EEST_Material;
+ }
+ *pCurOut = pCur;
+ return eOut;
}
// ------------------------------------------------------------------------------------------------
-bool PLY::Element::ParseElement (const char* pCur,
- const char** pCurOut,
- PLY::Element* pOut)
+bool PLY::Element::ParseElement (const char* pCur,
+ const char** pCurOut,
+ PLY::Element* pOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut);
-
- // Example format: "element vertex 8"
- *pCurOut = pCur;
-
- // skip leading spaces
- if (!SkipSpaces(&pCur))return false;
-
- // skip the "element" string at the beginning
- if (!TokenMatch(pCur,"element",7))
- {
- // seems not to be a valid property entry
- return false;
- }
- // get next word
- if (!SkipSpaces(&pCur))return false;
-
- // parse the semantic of the element
- const char* szCur = pCur;
- pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur);
- if (PLY::EEST_INVALID == pOut->eSemantic)
- {
- // if the exact semantic can't be determined, just store
- // the original string identifier
- uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
- pOut->szName = std::string(szCur,iDiff);
- }
-
- if (!SkipSpaces(&pCur))return false;
-
- //parse the number of occurences of this element
- pOut->NumOccur = strtoul10(pCur,&pCur);
-
- // go to the next line
- SkipSpacesAndLineEnd(pCur,&pCur);
-
- // now parse all properties of the element
- while(true)
- {
- // skip all comments
- PLY::DOM::SkipComments(pCur,&pCur);
-
- PLY::Property prop;
- if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break;
- pOut->alProperties.push_back(prop);
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut);
+
+ // Example format: "element vertex 8"
+ *pCurOut = pCur;
+
+ // skip leading spaces
+ if (!SkipSpaces(&pCur))return false;
+
+ // skip the "element" string at the beginning
+ if (!TokenMatch(pCur,"element",7))
+ {
+ // seems not to be a valid property entry
+ return false;
+ }
+ // get next word
+ if (!SkipSpaces(&pCur))return false;
+
+ // parse the semantic of the element
+ const char* szCur = pCur;
+ pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur);
+ if (PLY::EEST_INVALID == pOut->eSemantic)
+ {
+ // if the exact semantic can't be determined, just store
+ // the original string identifier
+ uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur;
+ pOut->szName = std::string(szCur,iDiff);
+ }
+
+ if (!SkipSpaces(&pCur))return false;
+
+ //parse the number of occurrences of this element
+ pOut->NumOccur = strtoul10(pCur,&pCur);
+
+ // go to the next line
+ SkipSpacesAndLineEnd(pCur,&pCur);
+
+ // now parse all properties of the element
+ while(true)
+ {
+ // skip all comments
+ PLY::DOM::SkipComments(pCur,&pCur);
+
+ PLY::Property prop;
+ if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break;
+ pOut->alProperties.push_back(prop);
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::SkipComments (const char* pCur,
- const char** pCurOut)
+ const char** pCurOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
- *pCurOut = pCur;
-
- // skip spaces
- if (!SkipSpaces(pCur,&pCur))return false;
-
- if (TokenMatch(pCur,"comment",7))
- {
- SkipLine(pCur,&pCur);
- SkipComments(pCur,&pCur);
- *pCurOut = pCur;
- return true;
- }
- *pCurOut = pCur;
- return false;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+ *pCurOut = pCur;
+
+ // skip spaces
+ if (!SkipSpaces(pCur,&pCur))return false;
+
+ if (TokenMatch(pCur,"comment",7))
+ {
+ if ( !IsLineEnd(pCur[-1]) )
+ {
+ SkipLine(pCur,&pCur);
+ }
+ SkipComments(pCur,&pCur);
+ *pCurOut = pCur;
+ return true;
+ }
+ *pCurOut = pCur;
+ return false;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut,bool isBinary)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
- DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
-
- // after ply and format line
- *pCurOut = pCur;
-
- // parse all elements
- while (true)
- {
- // skip all comments
- PLY::DOM::SkipComments(pCur,&pCur);
-
- PLY::Element out;
- if(PLY::Element::ParseElement(pCur,&pCur,&out))
- {
- // add the element to the list of elements
- alElements.push_back(out);
- }
- else if (TokenMatch(pCur,"end_header",10))
- {
- // we have reached the end of the header
- break;
- }
- else
- {
- // ignore unknown header elements
- SkipLine(&pCur);
- }
- }
- if(!isBinary)
- { // it would occur an error, if binary data start with values as space or line end.
- SkipSpacesAndLineEnd(pCur,&pCur);
- }
- *pCurOut = pCur;
-
- DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+ DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin");
+
+ // after ply and format line
+ *pCurOut = pCur;
+
+ // parse all elements
+ while ((*pCur) != '\0')
+ {
+ // skip all comments
+ PLY::DOM::SkipComments(pCur,&pCur);
+
+ PLY::Element out;
+ if(PLY::Element::ParseElement(pCur,&pCur,&out))
+ {
+ // add the element to the list of elements
+ alElements.push_back(out);
+ }
+ else if (TokenMatch(pCur,"end_header",10))
+ {
+ // we have reached the end of the header
+ break;
+ }
+ else
+ {
+ // ignore unknown header elements
+ SkipLine(&pCur);
+ }
+ }
+ if(!isBinary)
+ { // it would occur an error, if binary data start with values as space or line end.
+ SkipSpacesAndLineEnd(pCur,&pCur);
+ }
+ *pCurOut = pCur;
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseElementInstanceLists (
- const char* pCur,
- const char** pCurOut)
+ const char* pCur,
+ const char** pCurOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
+ ai_assert(NULL != pCur && NULL != pCurOut);
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
- *pCurOut = pCur;
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin");
+ *pCurOut = pCur;
- alElementData.resize(alElements.size());
+ alElementData.resize(alElements.size());
- std::vector<PLY::Element>::const_iterator i = alElements.begin();
- std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+ std::vector<PLY::Element>::const_iterator i = alElements.begin();
+ std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
- // parse all element instances
- for (;i != alElements.end();++i,++a)
- {
- (*a).alInstances.resize((*i).NumOccur);
- PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
- }
+ // parse all element instances
+ for (;i != alElements.end();++i,++a)
+ {
+ (*a).alInstances.resize((*i).NumOccur);
+ PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a));
+ }
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
- *pCurOut = pCur;
- return true;
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseElementInstanceListsBinary (
- const char* pCur,
- const char** pCurOut,
- bool p_bBE)
+ const char* pCur,
+ const char** pCurOut,
+ bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != pCurOut);
-
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
- *pCurOut = pCur;
-
- alElementData.resize(alElements.size());
-
- std::vector<PLY::Element>::const_iterator i = alElements.begin();
- std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
-
- // parse all element instances
- for (;i != alElements.end();++i,++a)
- {
- (*a).alInstances.resize((*i).NumOccur);
- PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
- }
-
- DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut);
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
+ *pCurOut = pCur;
+
+ alElementData.resize(alElements.size());
+
+ std::vector<PLY::Element>::const_iterator i = alElements.begin();
+ std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin();
+
+ // parse all element instances
+ for (;i != alElements.end();++i,++a)
+ {
+ (*a).alInstances.resize((*i).NumOccur);
+ PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE);
+ }
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != p_pcOut);
-
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
-
- if(!p_pcOut->ParseHeader(pCur,&pCur,true))
- {
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
- return false;
- }
- if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
- {
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
- return false;
- }
- DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
- return true;
+ ai_assert(NULL != pCur && NULL != p_pcOut);
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
+
+ if(!p_pcOut->ParseHeader(pCur,&pCur,true))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+ return false;
+ }
+ if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
+ return false;
+ }
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut)
{
- ai_assert(NULL != pCur);
- ai_assert(NULL != p_pcOut);
-
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
-
-
- if(!p_pcOut->ParseHeader(pCur,&pCur,false))
- {
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
- return false;
- }
- if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
- {
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
- return false;
- }
- DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
- return true;
+ ai_assert(NULL != pCur);
+ ai_assert(NULL != p_pcOut);
+
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
+
+
+ if(!p_pcOut->ParseHeader(pCur,&pCur,false))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+ return false;
+ }
+ if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur))
+ {
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
+ return false;
+ }
+ DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded");
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::ElementInstanceList::ParseInstanceList (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstanceList* p_pcOut)
+ const char* pCur,
+ const char** pCurOut,
+ const PLY::Element* pcElement,
+ PLY::ElementInstanceList* p_pcOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
-
- if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
- {
- // if the element has an unknown semantic we can skip all lines
- // However, there could be comments
- for (unsigned int i = 0; i < pcElement->NumOccur;++i)
- {
- PLY::DOM::SkipComments(pCur,&pCur);
- SkipLine(pCur,&pCur);
- }
- }
- else
- {
- // be sure to have enough storage
- for (unsigned int i = 0; i < pcElement->NumOccur;++i)
- {
- PLY::DOM::SkipComments(pCur,&pCur);
- PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement,
- &p_pcOut->alInstances[i]);
- }
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+
+ if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
+ {
+ // if the element has an unknown semantic we can skip all lines
+ // However, there could be comments
+ for (unsigned int i = 0; i < pcElement->NumOccur;++i)
+ {
+ PLY::DOM::SkipComments(pCur,&pCur);
+ SkipLine(pCur,&pCur);
+ }
+ }
+ else
+ {
+ // be sure to have enough storage
+ for (unsigned int i = 0; i < pcElement->NumOccur;++i)
+ {
+ PLY::DOM::SkipComments(pCur,&pCur);
+ PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement,
+ &p_pcOut->alInstances[i]);
+ }
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::ElementInstanceList::ParseInstanceListBinary (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstanceList* p_pcOut,
- bool p_bBE /* = false */)
+ const char* pCur,
+ const char** pCurOut,
+ const PLY::Element* pcElement,
+ PLY::ElementInstanceList* p_pcOut,
+ bool p_bBE /* = false */)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
-
- // we can add special handling code for unknown element semantics since
- // we can't skip it as a whole block (we don't know its exact size
- // due to the fact that lists could be contained in the property list
- // of the unknown element)
- for (unsigned int i = 0; i < pcElement->NumOccur;++i)
- {
- PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement,
- &p_pcOut->alInstances[i], p_bBE);
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+
+ // we can add special handling code for unknown element semantics since
+ // we can't skip it as a whole block (we don't know its exact size
+ // due to the fact that lists could be contained in the property list
+ // of the unknown element)
+ for (unsigned int i = 0; i < pcElement->NumOccur;++i)
+ {
+ PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement,
+ &p_pcOut->alInstances[i], p_bBE);
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::ElementInstance::ParseInstance (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstance* p_pcOut)
+ const char* pCur,
+ const char** pCurOut,
+ const PLY::Element* pcElement,
+ PLY::ElementInstance* p_pcOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
-
- if (!SkipSpaces(pCur, &pCur))return false;
-
- // allocate enough storage
- p_pcOut->alProperties.resize(pcElement->alProperties.size());
-
- std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
- std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
- for (;i != p_pcOut->alProperties.end();++i,++a)
- {
- if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i))))
- {
- DefaultLogger::get()->warn("Unable to parse property instance. "
- "Skipping this element instance");
-
- // skip the rest of the instance
- SkipLine(pCur, &pCur);
-
- PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
- (*i).avList.push_back(v);
- }
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+
+ if (!SkipSpaces(pCur, &pCur))return false;
+
+ // allocate enough storage
+ p_pcOut->alProperties.resize(pcElement->alProperties.size());
+
+ std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+ std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+ for (;i != p_pcOut->alProperties.end();++i,++a)
+ {
+ if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i))))
+ {
+ DefaultLogger::get()->warn("Unable to parse property instance. "
+ "Skipping this element instance");
+
+ // skip the rest of the instance
+ SkipLine(pCur, &pCur);
+
+ PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType);
+ (*i).avList.push_back(v);
+ }
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::ElementInstance::ParseInstanceBinary (
- const char* pCur,
- const char** pCurOut,
- const PLY::Element* pcElement,
- PLY::ElementInstance* p_pcOut,
- bool p_bBE /* = false */)
+ const char* pCur,
+ const char** pCurOut,
+ const PLY::Element* pcElement,
+ PLY::ElementInstance* p_pcOut,
+ bool p_bBE /* = false */)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
-
- // allocate enough storage
- p_pcOut->alProperties.resize(pcElement->alProperties.size());
-
- std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
- std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
- for (;i != p_pcOut->alProperties.end();++i,++a)
- {
- if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE)))
- {
- DefaultLogger::get()->warn("Unable to parse binary property instance. "
- "Skipping this element instance");
-
- (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
- }
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut);
+
+ // allocate enough storage
+ p_pcOut->alProperties.resize(pcElement->alProperties.size());
+
+ std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
+ std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
+ for (;i != p_pcOut->alProperties.end();++i,++a)
+ {
+ if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE)))
+ {
+ DefaultLogger::get()->warn("Unable to parse binary property instance. "
+ "Skipping this element instance");
+
+ (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType));
+ }
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut,
- const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
+ const PLY::Property* prop, PLY::PropertyInstance* p_pcOut)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
-
- *pCurOut = pCur;
-
- // skip spaces at the beginning
- if (!SkipSpaces(pCur, &pCur))return false;
-
- if (prop->bIsList)
- {
- // parse the number of elements in the list
- PLY::PropertyInstance::ValueUnion v;
- PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v);
-
- // convert to unsigned int
- unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
- // parse all list elements
- p_pcOut->avList.resize(iNum);
- for (unsigned int i = 0; i < iNum;++i)
- {
- if (!SkipSpaces(pCur, &pCur))return false;
- PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
- }
- }
- else
- {
- // parse the property
- PLY::PropertyInstance::ValueUnion v;
-
- PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
- p_pcOut->avList.push_back(v);
- }
- SkipSpacesAndLineEnd(pCur, &pCur);
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
+
+ *pCurOut = pCur;
+
+ // skip spaces at the beginning
+ if (!SkipSpaces(pCur, &pCur))return false;
+
+ if (prop->bIsList)
+ {
+ // parse the number of elements in the list
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v);
+
+ // convert to unsigned int
+ unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
+
+ // parse all list elements
+ p_pcOut->avList.resize(iNum);
+ for (unsigned int i = 0; i < iNum;++i)
+ {
+ if (!SkipSpaces(pCur, &pCur))return false;
+ PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]);
+ }
+ }
+ else
+ {
+ // parse the property
+ PLY::PropertyInstance::ValueUnion v;
+
+ PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v);
+ p_pcOut->avList.push_back(v);
+ }
+ SkipSpacesAndLineEnd(pCur, &pCur);
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool PLY::PropertyInstance::ParseInstanceBinary (
- const char* pCur,
- const char** pCurOut,
- const PLY::Property* prop,
- PLY::PropertyInstance* p_pcOut,
- bool p_bBE)
+ const char* pCur,
+ const char** pCurOut,
+ const PLY::Property* prop,
+ PLY::PropertyInstance* p_pcOut,
+ bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
-
- if (prop->bIsList)
- {
- // parse the number of elements in the list
- PLY::PropertyInstance::ValueUnion v;
- PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE);
-
- // convert to unsigned int
- unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
-
- // parse all list elements
- p_pcOut->avList.resize(iNum);
- for (unsigned int i = 0; i < iNum;++i){
- PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE);
- }
- }
- else
- {
- // parse the property
- PLY::PropertyInstance::ValueUnion v;
- PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE);
- p_pcOut->avList.push_back(v);
- }
- *pCurOut = pCur;
- return true;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut);
+
+ if (prop->bIsList)
+ {
+ // parse the number of elements in the list
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE);
+
+ // convert to unsigned int
+ unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
+
+ // parse all list elements
+ p_pcOut->avList.resize(iNum);
+ for (unsigned int i = 0; i < iNum;++i){
+ PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE);
+ }
+ }
+ else
+ {
+ // parse the property
+ PLY::PropertyInstance::ValueUnion v;
+ PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE);
+ p_pcOut->avList.push_back(v);
+ }
+ *pCurOut = pCur;
+ return true;
}
// ------------------------------------------------------------------------------------------------
PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(
- PLY::EDataType eType)
+ PLY::EDataType eType)
{
- PLY::PropertyInstance::ValueUnion out;
-
- switch (eType)
- {
- case EDT_Float:
- out.fFloat = 0.f;
- return out;
-
- case EDT_Double:
- out.fDouble = 0.;
- return out;
-
- default: ;
- };
- out.iUInt = 0;
- return out;
+ PLY::PropertyInstance::ValueUnion out;
+
+ switch (eType)
+ {
+ case EDT_Float:
+ out.fFloat = 0.f;
+ return out;
+
+ case EDT_Double:
+ out.fDouble = 0.;
+ return out;
+
+ default: ;
+ };
+ out.iUInt = 0;
+ return out;
}
// ------------------------------------------------------------------------------------------------
bool PLY::PropertyInstance::ParseValue(
- const char* pCur,
- const char** pCurOut,
- PLY::EDataType eType,
- PLY::PropertyInstance::ValueUnion* out)
+ const char* pCur,
+ const char** pCurOut,
+ PLY::EDataType eType,
+ PLY::PropertyInstance::ValueUnion* out)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
- bool ret = true;
- *pCurOut = pCur;
- switch (eType)
- {
- case EDT_UInt:
- case EDT_UShort:
- case EDT_UChar:
+ bool ret = true;
+ *pCurOut = pCur;
+ switch (eType)
+ {
+ case EDT_UInt:
+ case EDT_UShort:
+ case EDT_UChar:
- out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
- break;
+ out->iUInt = (uint32_t)strtoul10(pCur, &pCur);
+ break;
- case EDT_Int:
- case EDT_Short:
- case EDT_Char:
+ case EDT_Int:
+ case EDT_Short:
+ case EDT_Char:
- out->iInt = (int32_t)strtol10(pCur, &pCur);
- break;
+ out->iInt = (int32_t)strtol10(pCur, &pCur);
+ break;
- case EDT_Float:
+ case EDT_Float:
- pCur = fast_atoreal_move<float>(pCur,out->fFloat);
- break;
+ pCur = fast_atoreal_move<float>(pCur,out->fFloat);
+ break;
- case EDT_Double:
+ case EDT_Double:
- float f;
- pCur = fast_atoreal_move<float>(pCur,f);
- out->fDouble = (double)f;
- break;
+ float f;
+ pCur = fast_atoreal_move<float>(pCur,f);
+ out->fDouble = (double)f;
+ break;
- default:
- ret = false;
- }
- *pCurOut = pCur;
- return ret;
+ default:
+ ret = false;
+ }
+ *pCurOut = pCur;
+ return ret;
}
// ------------------------------------------------------------------------------------------------
bool PLY::PropertyInstance::ParseValueBinary(
- const char* pCur,
- const char** pCurOut,
- PLY::EDataType eType,
- PLY::PropertyInstance::ValueUnion* out,
- bool p_bBE)
+ const char* pCur,
+ const char** pCurOut,
+ PLY::EDataType eType,
+ PLY::PropertyInstance::ValueUnion* out,
+ bool p_bBE)
{
- ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
-
- bool ret = true;
- switch (eType)
- {
- case EDT_UInt:
- out->iUInt = (uint32_t)*((uint32_t*)pCur);
- pCur += 4;
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
- break;
-
- case EDT_UShort:
- {
- int16_t i = *((uint16_t*)pCur);
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap(&i);
- out->iUInt = (uint32_t)i;
- pCur += 2;
- break;
- }
-
- case EDT_UChar:
- {
- out->iUInt = (uint32_t)(*((uint8_t*)pCur));
- pCur ++;
- break;
- }
-
- case EDT_Int:
- out->iInt = *((int32_t*)pCur);
- pCur += 4;
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap(&out->iInt);
- break;
-
- case EDT_Short:
- {
- int16_t i = *((int16_t*)pCur);
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap(&i);
- out->iInt = (int32_t)i;
- pCur += 2;
- break;
- }
-
- case EDT_Char:
- out->iInt = (int32_t)*((int8_t*)pCur);
- pCur ++;
- break;
-
- case EDT_Float:
- {
- out->fFloat = *((float*)pCur);
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
- pCur += 4;
- break;
- }
- case EDT_Double:
- {
- out->fDouble = *((double*)pCur);
-
- // Swap endianess
- if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
- pCur += 8;
- break;
- }
- default:
- ret = false;
- }
- *pCurOut = pCur;
- return ret;
+ ai_assert(NULL != pCur && NULL != pCurOut && NULL != out);
+
+ bool ret = true;
+ switch (eType)
+ {
+ case EDT_UInt:
+ out->iUInt = (uint32_t)*((uint32_t*)pCur);
+ pCur += 4;
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt);
+ break;
+
+ case EDT_UShort:
+ {
+ uint16_t i = *((uint16_t*)pCur);
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap(&i);
+ out->iUInt = (uint32_t)i;
+ pCur += 2;
+ break;
+ }
+
+ case EDT_UChar:
+ {
+ out->iUInt = (uint32_t)(*((uint8_t*)pCur));
+ pCur ++;
+ break;
+ }
+
+ case EDT_Int:
+ out->iInt = *((int32_t*)pCur);
+ pCur += 4;
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap(&out->iInt);
+ break;
+
+ case EDT_Short:
+ {
+ int16_t i = *((int16_t*)pCur);
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap(&i);
+ out->iInt = (int32_t)i;
+ pCur += 2;
+ break;
+ }
+
+ case EDT_Char:
+ out->iInt = (int32_t)*((int8_t*)pCur);
+ pCur ++;
+ break;
+
+ case EDT_Float:
+ {
+ out->fFloat = *((float*)pCur);
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat);
+ pCur += 4;
+ break;
+ }
+ case EDT_Double:
+ {
+ out->fDouble = *((double*)pCur);
+
+ // Swap endianness
+ if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble);
+ pCur += 8;
+ break;
+ }
+ default:
+ ret = false;
+ }
+ *pCurOut = pCur;
+ return ret;
}
#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER
diff --git a/src/3rdparty/assimp/code/PlyParser.h b/src/3rdparty/assimp/code/PlyParser.h
index 9120c20b0..2753c1004 100644
--- a/src/3rdparty/assimp/code/PlyParser.h
+++ b/src/3rdparty/assimp/code/PlyParser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
+#include <vector>
namespace Assimp
@@ -76,17 +77,17 @@ uint8 ... forms are also used
*/
enum EDataType
{
- EDT_Char = 0x0u,
- EDT_UChar,
- EDT_Short,
- EDT_UShort,
- EDT_Int,
- EDT_UInt,
- EDT_Float,
- EDT_Double,
-
- // Marks invalid entries
- EDT_INVALID
+ EDT_Char = 0x0u,
+ EDT_UChar,
+ EDT_Short,
+ EDT_UShort,
+ EDT_Int,
+ EDT_UInt,
+ EDT_Float,
+ EDT_Double,
+
+ // Marks invalid entries
+ EDT_INVALID
};
// ---------------------------------------------------------------------------------
@@ -96,81 +97,81 @@ enum EDataType
*/
enum ESemantic
{
- //! vertex position x coordinate
- EST_XCoord = 0x0u,
- //! vertex position x coordinate
- EST_YCoord,
- //! vertex position x coordinate
- EST_ZCoord,
-
- //! vertex normal x coordinate
- EST_XNormal,
- //! vertex normal y coordinate
- EST_YNormal,
- //! vertex normal z coordinate
- EST_ZNormal,
-
- //! u texture coordinate
- EST_UTextureCoord,
- //! v texture coordinate
- EST_VTextureCoord,
-
- //! vertex colors, red channel
- EST_Red,
- //! vertex colors, green channel
- EST_Green,
- //! vertex colors, blue channel
- EST_Blue,
- //! vertex colors, alpha channel
- EST_Alpha,
-
- //! vertex index list
- EST_VertexIndex,
-
- //! texture index
- EST_TextureIndex,
-
- //! texture coordinates (stored as element of a face)
- EST_TextureCoordinates,
-
- //! material index
- EST_MaterialIndex,
-
- //! ambient color, red channel
- EST_AmbientRed,
- //! ambient color, green channel
- EST_AmbientGreen,
- //! ambient color, blue channel
- EST_AmbientBlue,
- //! ambient color, alpha channel
- EST_AmbientAlpha,
-
- //! diffuse color, red channel
- EST_DiffuseRed,
- //! diffuse color, green channel
- EST_DiffuseGreen,
- //! diffuse color, blue channel
- EST_DiffuseBlue,
- //! diffuse color, alpha channel
- EST_DiffuseAlpha,
-
- //! specular color, red channel
- EST_SpecularRed,
- //! specular color, green channel
- EST_SpecularGreen,
- //! specular color, blue channel
- EST_SpecularBlue,
- //! specular color, alpha channel
- EST_SpecularAlpha,
-
- //! specular power for phong shading
- EST_PhongPower,
-
- //! opacity between 0 and 1
- EST_Opacity,
-
- //! Marks invalid entries
- EST_INVALID
+ //! vertex position x coordinate
+ EST_XCoord = 0x0u,
+ //! vertex position x coordinate
+ EST_YCoord,
+ //! vertex position x coordinate
+ EST_ZCoord,
+
+ //! vertex normal x coordinate
+ EST_XNormal,
+ //! vertex normal y coordinate
+ EST_YNormal,
+ //! vertex normal z coordinate
+ EST_ZNormal,
+
+ //! u texture coordinate
+ EST_UTextureCoord,
+ //! v texture coordinate
+ EST_VTextureCoord,
+
+ //! vertex colors, red channel
+ EST_Red,
+ //! vertex colors, green channel
+ EST_Green,
+ //! vertex colors, blue channel
+ EST_Blue,
+ //! vertex colors, alpha channel
+ EST_Alpha,
+
+ //! vertex index list
+ EST_VertexIndex,
+
+ //! texture index
+ EST_TextureIndex,
+
+ //! texture coordinates (stored as element of a face)
+ EST_TextureCoordinates,
+
+ //! material index
+ EST_MaterialIndex,
+
+ //! ambient color, red channel
+ EST_AmbientRed,
+ //! ambient color, green channel
+ EST_AmbientGreen,
+ //! ambient color, blue channel
+ EST_AmbientBlue,
+ //! ambient color, alpha channel
+ EST_AmbientAlpha,
+
+ //! diffuse color, red channel
+ EST_DiffuseRed,
+ //! diffuse color, green channel
+ EST_DiffuseGreen,
+ //! diffuse color, blue channel
+ EST_DiffuseBlue,
+ //! diffuse color, alpha channel
+ EST_DiffuseAlpha,
+
+ //! specular color, red channel
+ EST_SpecularRed,
+ //! specular color, green channel
+ EST_SpecularGreen,
+ //! specular color, blue channel
+ EST_SpecularBlue,
+ //! specular color, alpha channel
+ EST_SpecularAlpha,
+
+ //! specular power for phong shading
+ EST_PhongPower,
+
+ //! opacity between 0 and 1
+ EST_Opacity,
+
+ //! Marks invalid entries
+ EST_INVALID
};
// ---------------------------------------------------------------------------------
@@ -180,23 +181,23 @@ enum ESemantic
*/
enum EElementSemantic
{
- //! The element is a vertex
- EEST_Vertex = 0x0u,
+ //! The element is a vertex
+ EEST_Vertex = 0x0u,
- //! The element is a face description (index table)
- EEST_Face,
+ //! The element is a face description (index table)
+ EEST_Face,
- //! The element is a tristrip description (index table)
- EEST_TriStrip,
+ //! The element is a tristrip description (index table)
+ EEST_TriStrip,
- //! The element is an edge description (ignored)
- EEST_Edge,
+ //! The element is an edge description (ignored)
+ EEST_Edge,
- //! The element is a material description
- EEST_Material,
+ //! The element is a material description
+ EEST_Material,
- //! Marks invalid entries
- EEST_INVALID
+ //! Marks invalid entries
+ EEST_INVALID
};
// ---------------------------------------------------------------------------------
@@ -208,41 +209,44 @@ class Property
{
public:
- //! Default constructor
- Property()
- : eType (EDT_Int), bIsList(false), eFirstType(EDT_UChar)
- {}
-
- //! Data type of the property
- EDataType eType;
-
- //! Semantical meaning of the property
- ESemantic Semantic;
-
- //! Of the semantic of the property could not be parsed:
- //! Contains the semantic specified in the file
- std::string szName;
-
- //! Specifies whether the data type is a list where
- //! the first element specifies the size of the list
- bool bIsList;
- EDataType eFirstType;
-
- // -------------------------------------------------------------------
- //! Parse a property from a string. The end of the
- //! string is either '\n', '\r' or '\0'. Return valie is false
- //! if the input string is NOT a valid property (E.g. does
- //! not start with the "property" keyword)
- static bool ParseProperty (const char* pCur, const char** pCurOut,
- Property* pOut);
-
- // -------------------------------------------------------------------
- //! Parse a data type from a string
- static EDataType ParseDataType(const char* pCur,const char** pCurOut);
-
- // -------------------------------------------------------------------
- //! Parse a semantic from a string
- static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
+ //! Default constructor
+ Property()
+ : eType (EDT_Int),
+ Semantic(),
+ bIsList(false),
+ eFirstType(EDT_UChar)
+ {}
+
+ //! Data type of the property
+ EDataType eType;
+
+ //! Semantical meaning of the property
+ ESemantic Semantic;
+
+ //! Of the semantic of the property could not be parsed:
+ //! Contains the semantic specified in the file
+ std::string szName;
+
+ //! Specifies whether the data type is a list where
+ //! the first element specifies the size of the list
+ bool bIsList;
+ EDataType eFirstType;
+
+ // -------------------------------------------------------------------
+ //! Parse a property from a string. The end of the
+ //! string is either '\n', '\r' or '\0'. Return valie is false
+ //! if the input string is NOT a valid property (E.g. does
+ //! not start with the "property" keyword)
+ static bool ParseProperty (const char* pCur, const char** pCurOut,
+ Property* pOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a data type from a string
+ static EDataType ParseDataType(const char* pCur,const char** pCurOut);
+
+ // -------------------------------------------------------------------
+ //! Parse a semantic from a string
+ static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
};
// ---------------------------------------------------------------------------------
@@ -255,195 +259,195 @@ class Element
{
public:
- //! Default constructor
- Element()
- : eSemantic (EEST_INVALID)
- , NumOccur(0)
- {}
+ //! Default constructor
+ Element()
+ : eSemantic (EEST_INVALID)
+ , NumOccur(0)
+ {}
- //! List of properties assigned to the element
- //! std::vector to support operator[]
- std::vector<Property> alProperties;
+ //! List of properties assigned to the element
+ //! std::vector to support operator[]
+ std::vector<Property> alProperties;
- //! Semantic of the element
- EElementSemantic eSemantic;
+ //! Semantic of the element
+ EElementSemantic eSemantic;
- //! Of the semantic of the element could not be parsed:
- //! Contains the semantic specified in the file
- std::string szName;
+ //! Of the semantic of the element could not be parsed:
+ //! Contains the semantic specified in the file
+ std::string szName;
- //! How many times will the element occur?
- unsigned int NumOccur;
+ //! How many times will the element occur?
+ unsigned int NumOccur;
- // -------------------------------------------------------------------
- //! Parse an element from a string.
- //! The function will parse all properties contained in the
- //! element, too.
- static bool ParseElement (const char* pCur, const char** pCurOut,
- Element* pOut);
+ // -------------------------------------------------------------------
+ //! Parse an element from a string.
+ //! The function will parse all properties contained in the
+ //! element, too.
+ static bool ParseElement (const char* pCur, const char** pCurOut,
+ Element* pOut);
- // -------------------------------------------------------------------
- //! Parse a semantic from a string
- static EElementSemantic ParseSemantic(const char* pCur,
- const char** pCurOut);
+ // -------------------------------------------------------------------
+ //! Parse a semantic from a string
+ static EElementSemantic ParseSemantic(const char* pCur,
+ const char** pCurOut);
};
// ---------------------------------------------------------------------------------
/** \brief Instance of a property in a PLY file
*/
-class PropertyInstance
+class PropertyInstance
{
public:
- //! Default constructor
- PropertyInstance ()
- {}
+ //! Default constructor
+ PropertyInstance ()
+ {}
- union ValueUnion
- {
+ union ValueUnion
+ {
- //! uInt32 representation of the property. All
- // uint types are automatically converted to uint32
- uint32_t iUInt;
+ //! uInt32 representation of the property. All
+ // uint types are automatically converted to uint32
+ uint32_t iUInt;
- //! Int32 representation of the property. All
- // int types are automatically converted to int32
- int32_t iInt;
+ //! Int32 representation of the property. All
+ // int types are automatically converted to int32
+ int32_t iInt;
- //! Float32 representation of the property
- float fFloat;
+ //! Float32 representation of the property
+ float fFloat;
- //! Float64 representation of the property
- double fDouble;
+ //! Float64 representation of the property
+ double fDouble;
- };
+ };
- // -------------------------------------------------------------------
- //! List of all values parsed. Contains only one value
- // for non-list properties
- std::vector<ValueUnion> avList;
+ // -------------------------------------------------------------------
+ //! List of all values parsed. Contains only one value
+ // for non-list properties
+ std::vector<ValueUnion> avList;
- // -------------------------------------------------------------------
- //! Parse a property instance
- static bool ParseInstance (const char* pCur,const char** pCurOut,
- const Property* prop, PropertyInstance* p_pcOut);
+ // -------------------------------------------------------------------
+ //! Parse a property instance
+ static bool ParseInstance (const char* pCur,const char** pCurOut,
+ const Property* prop, PropertyInstance* p_pcOut);
- // -------------------------------------------------------------------
- //! Parse a property instance in binary format
- static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
- const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Parse a property instance in binary format
+ static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
+ const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
- // -------------------------------------------------------------------
- //! Get the default value for a given data type
- static ValueUnion DefaultValue(EDataType eType);
+ // -------------------------------------------------------------------
+ //! Get the default value for a given data type
+ static ValueUnion DefaultValue(EDataType eType);
- // -------------------------------------------------------------------
- //! Parse a value
- static bool ParseValue(const char* pCur,const char** pCurOut,
- EDataType eType,ValueUnion* out);
+ // -------------------------------------------------------------------
+ //! Parse a value
+ static bool ParseValue(const char* pCur,const char** pCurOut,
+ EDataType eType,ValueUnion* out);
- // -------------------------------------------------------------------
- //! Parse a binary value
- static bool ParseValueBinary(const char* pCur,const char** pCurOut,
- EDataType eType,ValueUnion* out,bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Parse a binary value
+ static bool ParseValueBinary(const char* pCur,const char** pCurOut,
+ EDataType eType,ValueUnion* out,bool p_bBE);
- // -------------------------------------------------------------------
- //! Convert a property value to a given type TYPE
- template <typename TYPE>
- static TYPE ConvertTo(ValueUnion v, EDataType eType);
+ // -------------------------------------------------------------------
+ //! Convert a property value to a given type TYPE
+ template <typename TYPE>
+ static TYPE ConvertTo(ValueUnion v, EDataType eType);
};
// ---------------------------------------------------------------------------------
/** \brief Class for an element instance in a PLY file
*/
-class ElementInstance
+class ElementInstance
{
public:
- //! Default constructor
- ElementInstance ()
- {}
+ //! Default constructor
+ ElementInstance ()
+ {}
- //! List of all parsed properties
- std::vector< PropertyInstance > alProperties;
+ //! List of all parsed properties
+ std::vector< PropertyInstance > alProperties;
- // -------------------------------------------------------------------
- //! Parse an element instance
- static bool ParseInstance (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstance* p_pcOut);
+ // -------------------------------------------------------------------
+ //! Parse an element instance
+ static bool ParseInstance (const char* pCur,const char** pCurOut,
+ const Element* pcElement, ElementInstance* p_pcOut);
- // -------------------------------------------------------------------
- //! Parse a binary element instance
- static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Parse a binary element instance
+ static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
+ const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
};
// ---------------------------------------------------------------------------------
/** \brief Class for an element instance list in a PLY file
*/
-class ElementInstanceList
+class ElementInstanceList
{
public:
- //! Default constructor
- ElementInstanceList ()
- {}
+ //! Default constructor
+ ElementInstanceList ()
+ {}
- //! List of all element instances
- std::vector< ElementInstance > alInstances;
+ //! List of all element instances
+ std::vector< ElementInstance > alInstances;
- // -------------------------------------------------------------------
- //! Parse an element instance list
- static bool ParseInstanceList (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstanceList* p_pcOut);
+ // -------------------------------------------------------------------
+ //! Parse an element instance list
+ static bool ParseInstanceList (const char* pCur,const char** pCurOut,
+ const Element* pcElement, ElementInstanceList* p_pcOut);
- // -------------------------------------------------------------------
- //! Parse a binary element instance list
- static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
- const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Parse a binary element instance list
+ static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
+ const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
};
// ---------------------------------------------------------------------------------
-/** \brief Class to represent the document object model of an ASCII or binary
+/** \brief Class to represent the document object model of an ASCII or binary
* (both little and big-endian) PLY file
*/
class DOM
{
public:
- //! Default constructor
- DOM()
- {}
+ //! Default constructor
+ DOM()
+ {}
- //! Contains all elements of the file format
- std::vector<Element> alElements;
- //! Contains the real data of each element's instance list
- std::vector<ElementInstanceList> alElementData;
+ //! Contains all elements of the file format
+ std::vector<Element> alElements;
+ //! Contains the real data of each element's instance list
+ std::vector<ElementInstanceList> alElementData;
- //! Parse the DOM for a PLY file. The input string is assumed
- //! to be terminated with zero
- static bool ParseInstance (const char* pCur,DOM* p_pcOut);
- static bool ParseInstanceBinary (const char* pCur,
- DOM* p_pcOut,bool p_bBE);
+ //! Parse the DOM for a PLY file. The input string is assumed
+ //! to be terminated with zero
+ static bool ParseInstance (const char* pCur,DOM* p_pcOut);
+ static bool ParseInstanceBinary (const char* pCur,
+ DOM* p_pcOut,bool p_bBE);
- //! Skip all comment lines after this
- static bool SkipComments (const char* pCur,const char** pCurOut);
+ //! Skip all comment lines after this
+ static bool SkipComments (const char* pCur,const char** pCurOut);
private:
- // -------------------------------------------------------------------
- //! Handle the file header and read all element descriptions
- bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Handle the file header and read all element descriptions
+ bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
- // -------------------------------------------------------------------
- //! Read in all element instance lists
- bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
+ // -------------------------------------------------------------------
+ //! Read in all element instance lists
+ bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
- // -------------------------------------------------------------------
- //! Read in all element instance lists for a binary file format
- bool ParseElementInstanceListsBinary (const char* pCur,
- const char** pCurOut,bool p_bBE);
+ // -------------------------------------------------------------------
+ //! Read in all element instance lists for a binary file format
+ bool ParseElementInstanceListsBinary (const char* pCur,
+ const char** pCurOut,bool p_bBE);
};
// ---------------------------------------------------------------------------------
@@ -453,46 +457,46 @@ class Face
{
public:
- Face()
- : iMaterialIndex(0xFFFFFFFF)
- {
- // set all indices to zero by default
- mIndices.resize(3,0);
- }
+ Face()
+ : iMaterialIndex(0xFFFFFFFF)
+ {
+ // set all indices to zero by default
+ mIndices.resize(3,0);
+ }
public:
- //! List of vertex indices
- std::vector<unsigned int> mIndices;
+ //! List of vertex indices
+ std::vector<unsigned int> mIndices;
- //! Material index
- unsigned int iMaterialIndex;
+ //! Material index
+ unsigned int iMaterialIndex;
};
// ---------------------------------------------------------------------------------
template <typename TYPE>
inline TYPE PLY::PropertyInstance::ConvertTo(
- PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType)
+ PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType)
{
- switch (eType)
- {
- case EDT_Float:
- return (TYPE)v.fFloat;
- case EDT_Double:
- return (TYPE)v.fDouble;
-
- case EDT_UInt:
- case EDT_UShort:
- case EDT_UChar:
- return (TYPE)v.iUInt;
-
- case EDT_Int:
- case EDT_Short:
- case EDT_Char:
- return (TYPE)v.iInt;
- default: ;
- };
- return (TYPE)0;
+ switch (eType)
+ {
+ case EDT_Float:
+ return (TYPE)v.fFloat;
+ case EDT_Double:
+ return (TYPE)v.fDouble;
+
+ case EDT_UInt:
+ case EDT_UShort:
+ case EDT_UChar:
+ return (TYPE)v.iUInt;
+
+ case EDT_Int:
+ case EDT_Short:
+ case EDT_Char:
+ return (TYPE)v.iInt;
+ default: ;
+ };
+ return (TYPE)0;
}
} // Namespace PLY
diff --git a/src/3rdparty/assimp/code/PolyTools.h b/src/3rdparty/assimp/code/PolyTools.h
index 79759595c..80e1dd173 100644
--- a/src/3rdparty/assimp/code/PolyTools.h
+++ b/src/3rdparty/assimp/code/PolyTools.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,6 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_POLYTOOLS_H_INCLUDED
#define AI_POLYTOOLS_H_INCLUDED
+#include <assimp/material.h>
+#include <assimp/ai_assert.h>
+
namespace Assimp {
// -------------------------------------------------------------------------------
@@ -50,9 +53,9 @@ namespace Assimp {
* 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)
+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));
+ return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
}
// -------------------------------------------------------------------------------
@@ -62,7 +65,7 @@ inline double GetArea2D(const T& v1, const T& v2, const T& v3)
template <typename T>
inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
{
- return GetArea2D(p0,p2,p1) > 0;
+ return GetArea2D(p0,p2,p1) > 0;
}
// -------------------------------------------------------------------------------
@@ -72,96 +75,96 @@ inline bool OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2)
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);
+ // 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
+ * 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);
+ 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);
}
@@ -173,9 +176,9 @@ inline bool IsCCW(T* in, size_t npoints) {
*
* @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
+ * @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()
@@ -183,40 +186,40 @@ inline bool IsCCW(T* in, size_t npoints) {
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];
+ // 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];
+ 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];
+ 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 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;
+ 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) );
+ 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;
+ xptr += ofs_x;
+ xlow += ofs_x;
+ xhigh += ofs_x;
- yptr += ofs_y;
- ylow += ofs_y;
- yhigh += ofs_y;
+ 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);
+ zptr += ofs_z;
+ zlow += ofs_z;
+ zhigh += ofs_z;
+ }
+ out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
}
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/PostStepRegistry.cpp b/src/3rdparty/assimp/code/PostStepRegistry.cpp
index 579b48c13..31518c132 100644
--- a/src/3rdparty/assimp/code/PostStepRegistry.cpp
+++ b/src/3rdparty/assimp/code/PostStepRegistry.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -46,80 +46,79 @@ directly (unless you are adding new steps), instead use the
corresponding preprocessor flag to selectively disable steps.
*/
-#include "AssimpPCH.h"
#include "ProcessHelper.h"
#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
-# include "CalcTangentsProcess.h"
+# include "CalcTangentsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS
-# include "JoinVerticesProcess.h"
+# include "JoinVerticesProcess.h"
#endif
#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
-# include "ConvertToLHProcess.h"
+# include "ConvertToLHProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
-# include "TriangulateProcess.h"
+# include "TriangulateProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS
-# include "GenFaceNormalsProcess.h"
+# include "GenFaceNormalsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS
-# include "GenVertexNormalsProcess.h"
+# include "GenVertexNormalsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS
-# include "RemoveVCProcess.h"
+# include "RemoveVCProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS
-# include "SplitLargeMeshes.h"
+# include "SplitLargeMeshes.h"
#endif
#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS
-# include "PretransformVertices.h"
+# include "PretransformVertices.h"
#endif
#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS
-# include "LimitBoneWeightsProcess.h"
+# include "LimitBoneWeightsProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-# include "ValidateDataStructure.h"
+# include "ValidateDataStructure.h"
#endif
#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS
-# include "ImproveCacheLocality.h"
+# include "ImproveCacheLocality.h"
#endif
#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS
-# include "FixNormalsStep.h"
+# include "FixNormalsStep.h"
#endif
#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS
-# include "RemoveRedundantMaterials.h"
+# include "RemoveRedundantMaterials.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
-# include "FindInvalidDataProcess.h"
+# include "FindInvalidDataProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS
-# include "FindDegenerates.h"
+# include "FindDegenerates.h"
#endif
#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS
-# include "SortByPTypeProcess.h"
+# include "SortByPTypeProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
-# include "ComputeUVMappingProcess.h"
+# include "ComputeUVMappingProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
-# include "TextureTransform.h"
+# include "TextureTransform.h"
#endif
#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS
-# include "FindInstancesProcess.h"
+# include "FindInstancesProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
-# include "OptimizeMeshes.h"
+# include "OptimizeMeshes.h"
#endif
#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS
-# include "OptimizeGraph.h"
+# include "OptimizeGraph.h"
#endif
#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
-# include "SplitByBoneCountProcess.h"
+# include "SplitByBoneCountProcess.h"
#endif
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
-# include "DeboneProcess.h"
+# include "DeboneProcess.h"
#endif
namespace Assimp {
@@ -127,103 +126,103 @@ 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(25);
+ // ----------------------------------------------------------------------------
+ // 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(25);
#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS)
- out.push_back( new MakeLeftHandedProcess());
+ out.push_back( new MakeLeftHandedProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS)
- out.push_back( new FlipUVsProcess());
+ out.push_back( new FlipUVsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
- out.push_back( new FlipWindingOrderProcess());
+ out.push_back( new FlipWindingOrderProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS)
- out.push_back( new RemoveVCProcess());
+ out.push_back( new RemoveVCProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS)
- out.push_back( new RemoveRedundantMatsProcess());
+ out.push_back( new RemoveRedundantMatsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS)
- out.push_back( new FindInstancesProcess());
+ out.push_back( new FindInstancesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS)
- out.push_back( new OptimizeGraphProcess());
+ out.push_back( new OptimizeGraphProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS)
- out.push_back( new FindDegeneratesProcess());
+ out.push_back( new FindDegeneratesProcess());
#endif
#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS
- out.push_back( new ComputeUVMappingProcess());
+ out.push_back( new ComputeUVMappingProcess());
#endif
#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS
- out.push_back( new TextureTransformStep());
+ out.push_back( new TextureTransformStep());
#endif
#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS)
- out.push_back( new PretransformVertices());
+ out.push_back( new PretransformVertices());
#endif
#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS)
- out.push_back( new TriangulateProcess());
+ out.push_back( new TriangulateProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS)
- out.push_back( new SortByPTypeProcess());
+ out.push_back( new SortByPTypeProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS)
- out.push_back( new FindInvalidDataProcess());
+ out.push_back( new FindInvalidDataProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS)
- out.push_back( new OptimizeMeshesProcess());
+ out.push_back( new OptimizeMeshesProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS)
- out.push_back( new FixInfacingNormalsProcess());
+ out.push_back( new FixInfacingNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS)
- out.push_back( new SplitByBoneCountProcess());
+ out.push_back( new SplitByBoneCountProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
- out.push_back( new SplitLargeMeshesProcess_Triangle());
+ out.push_back( new SplitLargeMeshesProcess_Triangle());
#endif
#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS)
- out.push_back( new GenFaceNormalsProcess());
+ 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());
- // .........................................................................
+ // .........................................................................
+ // 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());
+ out.push_back( new GenVertexNormalsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS)
- out.push_back( new CalcTangentsProcess());
+ out.push_back( new CalcTangentsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS)
- out.push_back( new JoinVerticesProcess());
+ out.push_back( new JoinVerticesProcess());
#endif
- // .........................................................................
- out.push_back( new DestroySpatialSortProcess());
- // .........................................................................
+ // .........................................................................
+ out.push_back( new DestroySpatialSortProcess());
+ // .........................................................................
#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS)
- out.push_back( new SplitLargeMeshesProcess_Vertex());
+ out.push_back( new SplitLargeMeshesProcess_Vertex());
#endif
#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
- out.push_back( new DeboneProcess());
+ out.push_back( new DeboneProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
- out.push_back( new LimitBoneWeightsProcess());
+ out.push_back( new LimitBoneWeightsProcess());
#endif
#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS)
- out.push_back( new ImproveCacheLocalityProcess());
+ out.push_back( new ImproveCacheLocalityProcess());
#endif
}
diff --git a/src/3rdparty/assimp/code/PretransformVertices.cpp b/src/3rdparty/assimp/code/PretransformVertices.cpp
index 2b0304578..8158bdd6f 100644
--- a/src/3rdparty/assimp/code/PretransformVertices.cpp
+++ b/src/3rdparty/assimp/code/PretransformVertices.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,28 +25,29 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file PretransformVertices.cpp
- * @brief Implementation of the "PretransformVertices" post processing step
+ * @brief Implementation of the "PretransformVertices" post processing step
*/
-#include "AssimpPCH.h"
+
#include "PretransformVertices.h"
#include "ProcessHelper.h"
#include "SceneCombiner.h"
+#include "Exceptional.h"
using namespace Assimp;
@@ -57,7 +58,7 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
PretransformVertices::PretransformVertices()
-: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation()
+: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation()
{
}
@@ -65,658 +66,659 @@ PretransformVertices::PretransformVertices()
// Destructor, private as well
PretransformVertices::~PretransformVertices()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool PretransformVertices::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_PreTransformVertices) != 0;
+ return (pFlags & aiProcess_PreTransformVertices) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup import configuration
void PretransformVertices::SetupProperties(const Importer* pImp)
{
- // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE,
- // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION
- configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0));
- configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0));
- configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
+ // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE,
+ // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION
+ configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0));
+ configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0));
+ configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
- configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
+ configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
}
// ------------------------------------------------------------------------------------------------
// Count the number of nodes
unsigned int PretransformVertices::CountNodes( aiNode* pcNode )
{
- unsigned int iRet = 1;
- for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
- {
- iRet += CountNodes(pcNode->mChildren[i]);
- }
- return iRet;
+ unsigned int iRet = 1;
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+ {
+ iRet += CountNodes(pcNode->mChildren[i]);
+ }
+ return iRet;
}
// ------------------------------------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh
unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh)
{
- // the vertex format is stored in aiMesh::mBones for later retrieval.
- // there isn't a good reason to compute it a few hundred times
- // from scratch. The pointer is unused as animations are lost
- // during PretransformVertices.
- if (pcMesh->mBones)
- return (unsigned int)(uint64_t)pcMesh->mBones;
+ // the vertex format is stored in aiMesh::mBones for later retrieval.
+ // there isn't a good reason to compute it a few hundred times
+ // from scratch. The pointer is unused as animations are lost
+ // during PretransformVertices.
+ if (pcMesh->mBones)
+ return (unsigned int)(uint64_t)pcMesh->mBones;
- const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
+ const unsigned int iRet = GetMeshVFormatUnique(pcMesh);
- // store the value for later use
- pcMesh->mBones = (aiBone**)(uint64_t)iRet;
- return iRet;
+ // store the value for later use
+ pcMesh->mBones = (aiBone**)(uint64_t)iRet;
+ return iRet;
}
// ------------------------------------------------------------------------------------------------
// Count the number of vertices in the whole scene and a given
// material index
void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
- unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices)
+ unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices)
{
- for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
- {
- aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
- if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
- {
- *piVertices += pcMesh->mNumVertices;
- *piFaces += pcMesh->mNumFaces;
- }
- }
- for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
- {
- CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat,
- iVFormat,piFaces,piVertices);
- }
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
+ if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+ {
+ *piVertices += pcMesh->mNumVertices;
+ *piFaces += pcMesh->mNumFaces;
+ }
+ }
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
+ {
+ CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat,
+ iVFormat,piFaces,piVertices);
+ }
}
// ------------------------------------------------------------------------------------------------
// Collect vertex/face data
void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
- unsigned int iVFormat, aiMesh* pcMeshOut,
- unsigned int aiCurrent[2], unsigned int* num_refs)
+ unsigned int iVFormat, aiMesh* pcMeshOut,
+ unsigned int aiCurrent[2], unsigned int* num_refs)
{
- // No need to multiply if there's no transformation
- const bool identity = pcNode->mTransformation.IsIdentity();
- for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
- {
- aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
- if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
- {
- // Decrement mesh reference counter
- unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
- ai_assert(0 != num_ref);
- --num_ref;
-
- if (identity) {
- // copy positions without modifying them
- ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mVertices,
- pcMesh->mNumVertices * sizeof(aiVector3D));
-
- if (iVFormat & 0x2) {
- // copy normals without modifying them
- ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mNormals,
- pcMesh->mNumVertices * sizeof(aiVector3D));
- }
- if (iVFormat & 0x4)
- {
- // copy tangents without modifying them
- ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mTangents,
- pcMesh->mNumVertices * sizeof(aiVector3D));
- // copy bitangents without modifying them
- ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mBitangents,
- pcMesh->mNumVertices * sizeof(aiVector3D));
- }
- }
- else
- {
- // copy positions, transform them to worldspace
- for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
- pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n];
- }
- aiMatrix4x4 mWorldIT = pcNode->mTransformation;
- mWorldIT.Inverse().Transpose();
-
- // TODO: implement Inverse() for aiMatrix3x3
- aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
-
- if (iVFormat & 0x2)
- {
- // copy normals, transform them to worldspace
- for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
- pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
- (m * pcMesh->mNormals[n]).Normalize();
- }
- }
- if (iVFormat & 0x4)
- {
- // copy tangents and bitangents, transform them to worldspace
- for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
- pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mTangents[n]).Normalize();
- pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mBitangents[n]).Normalize();
- }
- }
- }
- unsigned int p = 0;
- while (iVFormat & (0x100 << p))
- {
- // copy texture coordinates
- memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mTextureCoords[p],
- pcMesh->mNumVertices * sizeof(aiVector3D));
- ++p;
- }
- p = 0;
- while (iVFormat & (0x1000000 << p))
- {
- // copy vertex colors
- memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
- pcMesh->mColors[p],
- pcMesh->mNumVertices * sizeof(aiColor4D));
- ++p;
- }
- // now we need to copy all faces. since we will delete the source mesh afterwards,
- // we don't need to reallocate the array of indices except if this mesh is
- // referenced multiple times.
- for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck)
- {
- aiFace& f_src = pcMesh->mFaces[planck];
- aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck];
-
- const unsigned int num_idx = f_src.mNumIndices;
-
- f_dst.mNumIndices = num_idx;
-
- unsigned int* pi;
- if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */
- pi = f_dst.mIndices = f_src.mIndices;
-
- // offset all vertex indices
- for (unsigned int hahn = 0; hahn < num_idx;++hahn){
- pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
- }
- }
- else {
- pi = f_dst.mIndices = new unsigned int[num_idx];
-
- // copy and offset all vertex indices
- for (unsigned int hahn = 0; hahn < num_idx;++hahn){
- pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX];
- }
- }
-
- // Update the mPrimitiveTypes member of the mesh
- switch (pcMesh->mFaces[planck].mNumIndices)
- {
- case 0x1:
- pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT;
- break;
- case 0x2:
- pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE;
- break;
- case 0x3:
- pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- break;
- default:
- pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- break;
- };
- }
- aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
- aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
- }
- }
-
- // append all children of us
- for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
- CollectData(pcScene,pcNode->mChildren[i],iMat,
- iVFormat,pcMeshOut,aiCurrent,num_refs);
- }
+ // No need to multiply if there's no transformation
+ const bool identity = pcNode->mTransformation.IsIdentity();
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ];
+ if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh))
+ {
+ // Decrement mesh reference counter
+ unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
+ ai_assert(0 != num_ref);
+ --num_ref;
+
+ if (identity) {
+ // copy positions without modifying them
+ ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mVertices,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+
+ if (iVFormat & 0x2) {
+ // copy normals without modifying them
+ ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mNormals,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ }
+ if (iVFormat & 0x4)
+ {
+ // copy tangents without modifying them
+ ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mTangents,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ // copy bitangents without modifying them
+ ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mBitangents,
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ }
+ }
+ else
+ {
+ // copy positions, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n];
+ }
+ aiMatrix4x4 mWorldIT = pcNode->mTransformation;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (iVFormat & 0x2)
+ {
+ // copy normals, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] =
+ (m * pcMesh->mNormals[n]).Normalize();
+ }
+ }
+ if (iVFormat & 0x4)
+ {
+ // copy tangents and bitangents, transform them to worldspace
+ for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) {
+ pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mTangents[n]).Normalize();
+ pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mBitangents[n]).Normalize();
+ }
+ }
+ }
+ unsigned int p = 0;
+ while (iVFormat & (0x100 << p))
+ {
+ // copy texture coordinates
+ memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mTextureCoords[p],
+ pcMesh->mNumVertices * sizeof(aiVector3D));
+ ++p;
+ }
+ p = 0;
+ while (iVFormat & (0x1000000 << p))
+ {
+ // copy vertex colors
+ memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX],
+ pcMesh->mColors[p],
+ pcMesh->mNumVertices * sizeof(aiColor4D));
+ ++p;
+ }
+ // now we need to copy all faces. since we will delete the source mesh afterwards,
+ // we don't need to reallocate the array of indices except if this mesh is
+ // referenced multiple times.
+ for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck)
+ {
+ aiFace& f_src = pcMesh->mFaces[planck];
+ aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck];
+
+ const unsigned int num_idx = f_src.mNumIndices;
+
+ f_dst.mNumIndices = num_idx;
+
+ unsigned int* pi;
+ if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */
+ pi = f_dst.mIndices = f_src.mIndices;
+
+ // offset all vertex indices
+ for (unsigned int hahn = 0; hahn < num_idx;++hahn){
+ pi[hahn] += aiCurrent[AI_PTVS_VERTEX];
+ }
+ }
+ else {
+ pi = f_dst.mIndices = new unsigned int[num_idx];
+
+ // copy and offset all vertex indices
+ for (unsigned int hahn = 0; hahn < num_idx;++hahn){
+ pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX];
+ }
+ }
+
+ // Update the mPrimitiveTypes member of the mesh
+ switch (pcMesh->mFaces[planck].mNumIndices)
+ {
+ case 0x1:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 0x2:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 0x3:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ break;
+ };
+ }
+ aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices;
+ aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces;
+ }
+ }
+
+ // append all children of us
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
+ CollectData(pcScene,pcNode->mChildren[i],iMat,
+ iVFormat,pcMeshOut,aiCurrent,num_refs);
+ }
}
// ------------------------------------------------------------------------------------------------
// Get a list of all vertex formats that occur for a given material index
// The output list contains duplicate elements
void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat,
- std::list<unsigned int>& aiOut)
+ std::list<unsigned int>& aiOut)
{
- for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
- {
- aiMesh* pcMesh = pcScene->mMeshes[ i ];
- if (iMat == pcMesh->mMaterialIndex) {
- aiOut.push_back(GetMeshVFormat(pcMesh));
- }
- }
+ for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
+ {
+ aiMesh* pcMesh = pcScene->mMeshes[ i ];
+ if (iMat == pcMesh->mMaterialIndex) {
+ aiOut.push_back(GetMeshVFormat(pcMesh));
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Compute the absolute transformation matrices of each node
void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode )
{
- if (pcNode->mParent) {
- pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
- }
+ if (pcNode->mParent) {
+ pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
+ }
- for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
- ComputeAbsoluteTransform(pcNode->mChildren[i]);
- }
+ for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
+ ComputeAbsoluteTransform(pcNode->mChildren[i]);
+ }
}
// ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh
void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)
{
- // Check whether we need to transform the coordinates at all
- if (!mat.IsIdentity()) {
-
- if (mesh->HasPositions()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mVertices[i] = mat * mesh->mVertices[i];
- }
- }
- if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
- aiMatrix4x4 mWorldIT = mat;
- mWorldIT.Inverse().Transpose();
-
- // TODO: implement Inverse() for aiMatrix3x3
- aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
-
- if (mesh->HasNormals()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
- }
- }
- if (mesh->HasTangentsAndBitangents()) {
- for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
- mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
- }
- }
- }
- }
+ // Check whether we need to transform the coordinates at all
+ if (!mat.IsIdentity()) {
+
+ if (mesh->HasPositions()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mVertices[i] = mat * mesh->mVertices[i];
+ }
+ }
+ if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
+ aiMatrix4x4 mWorldIT = mat;
+ mWorldIT.Inverse().Transpose();
+
+ // TODO: implement Inverse() for aiMatrix3x3
+ aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+ if (mesh->HasNormals()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+ }
+ }
+ if (mesh->HasTangentsAndBitangents()) {
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
+ mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Simple routine to build meshes in worldspace, no further optimization
void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
- unsigned int numIn, aiNode* node)
+ unsigned int numIn, aiNode* node)
{
- // NOTE:
- // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy
- // aiMesh::mBones store reference to abs. transform we multiplied with
-
- // process meshes
- for (unsigned int i = 0; i < node->mNumMeshes;++i) {
- aiMesh* mesh = in[node->mMeshes[i]];
-
- // check whether we can operate on this mesh
- if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) {
- // yes, we can.
- mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
- mesh->mNumBones = UINT_MAX;
- }
- else {
-
- // try to find us in the list of newly created meshes
- for (unsigned int n = 0; n < out.size(); ++n) {
- aiMesh* ctz = out[n];
- if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) {
-
- // ok, use this one. Update node mesh index
- node->mMeshes[i] = numIn + n;
- }
- }
- if (node->mMeshes[i] < numIn) {
- // Worst case. Need to operate on a full copy of the mesh
- DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms");
- aiMesh* ntz;
-
- const unsigned int tmp = mesh->mNumBones; //
- mesh->mNumBones = 0;
- SceneCombiner::Copy(&ntz,mesh);
- mesh->mNumBones = tmp;
-
- ntz->mNumBones = node->mMeshes[i];
- ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
-
- out.push_back(ntz);
-
- node->mMeshes[i] = numIn + out.size() - 1;
- }
- }
- }
-
- // call children
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- BuildWCSMeshes(out,in,numIn,node->mChildren[i]);
+ // NOTE:
+ // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy
+ // aiMesh::mBones store reference to abs. transform we multiplied with
+
+ // process meshes
+ for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+ aiMesh* mesh = in[node->mMeshes[i]];
+
+ // check whether we can operate on this mesh
+ if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) {
+ // yes, we can.
+ mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
+ mesh->mNumBones = UINT_MAX;
+ }
+ else {
+
+ // try to find us in the list of newly created meshes
+ for (unsigned int n = 0; n < out.size(); ++n) {
+ aiMesh* ctz = out[n];
+ if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) {
+
+ // ok, use this one. Update node mesh index
+ node->mMeshes[i] = numIn + n;
+ }
+ }
+ if (node->mMeshes[i] < numIn) {
+ // Worst case. Need to operate on a full copy of the mesh
+ DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms");
+ aiMesh* ntz;
+
+ const unsigned int tmp = mesh->mNumBones; //
+ mesh->mNumBones = 0;
+ SceneCombiner::Copy(&ntz,mesh);
+ mesh->mNumBones = tmp;
+
+ ntz->mNumBones = node->mMeshes[i];
+ ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation);
+
+ out.push_back(ntz);
+
+ node->mMeshes[i] = numIn + out.size() - 1;
+ }
+ }
+ }
+
+ // call children
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ BuildWCSMeshes(out,in,numIn,node->mChildren[i]);
}
// ------------------------------------------------------------------------------------------------
// Reset transformation matrices to identity
void PretransformVertices::MakeIdentityTransform(aiNode* nd)
{
- nd->mTransformation = aiMatrix4x4();
+ nd->mTransformation = aiMatrix4x4();
- // call children
- for (unsigned int i = 0; i < nd->mNumChildren;++i)
- MakeIdentityTransform(nd->mChildren[i]);
+ // call children
+ for (unsigned int i = 0; i < nd->mNumChildren;++i)
+ MakeIdentityTransform(nd->mChildren[i]);
}
// ------------------------------------------------------------------------------------------------
// Build reference counters for all meshes
void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs)
{
- for (unsigned int i = 0; i< nd->mNumMeshes;++i)
- refs[nd->mMeshes[i]]++;
+ for (unsigned int i = 0; i< nd->mNumMeshes;++i)
+ refs[nd->mMeshes[i]]++;
- // call children
- for (unsigned int i = 0; i < nd->mNumChildren;++i)
- BuildMeshRefCountArray(nd->mChildren[i],refs);
+ // call children
+ for (unsigned int i = 0; i < nd->mNumChildren;++i)
+ BuildMeshRefCountArray(nd->mChildren[i],refs);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void PretransformVertices::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("PretransformVerticesProcess begin");
-
- // Return immediately if we have no meshes
- if (!pScene->mNumMeshes)
- return;
-
- const unsigned int iOldMeshes = pScene->mNumMeshes;
- const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
- const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
-
- if(configTransform) {
- pScene->mRootNode->mTransformation = configTransformation;
- }
-
- // first compute absolute transformation matrices for all nodes
- ComputeAbsoluteTransform(pScene->mRootNode);
-
- // Delete aiMesh::mBones for all meshes. The bones are
- // removed during this step and we need the pointer as
- // temporary storage
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
- aiMesh* mesh = pScene->mMeshes[i];
-
- for (unsigned int a = 0; a < mesh->mNumBones;++a)
- delete mesh->mBones[a];
-
- delete[] mesh->mBones;
- mesh->mBones = NULL;
- }
-
- // now build a list of output meshes
- std::vector<aiMesh*> apcOutMeshes;
-
- // Keep scene hierarchy? It's an easy job in this case ...
- // we go on and transform all meshes, if one is referenced by nodes
- // with different absolute transformations a depth copy of the mesh
- // is required.
- if( configKeepHierarchy ) {
-
- // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones
- BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode);
-
- // ... if new meshes have been generated, append them to the end of the scene
- if (apcOutMeshes.size() > 0) {
- aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()];
-
- memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes);
- memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size());
-
- pScene->mNumMeshes += apcOutMeshes.size();
- delete[] pScene->mMeshes; pScene->mMeshes = npp;
- }
-
- // now iterate through all meshes and transform them to worldspace
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones ));
-
- // prevent improper destruction
- pScene->mMeshes[i]->mBones = NULL;
- pScene->mMeshes[i]->mNumBones = 0;
- }
- }
- else {
-
- apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
- std::list<unsigned int> aiVFormats;
-
- std::vector<unsigned int> s(pScene->mNumMeshes,0);
- BuildMeshRefCountArray(pScene->mRootNode,&s[0]);
-
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
- // get the list of all vertex formats for this material
- aiVFormats.clear();
- GetVFormatList(pScene,i,aiVFormats);
- aiVFormats.sort();
- aiVFormats.unique();
- for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
- unsigned int iVertices = 0;
- unsigned int iFaces = 0;
- CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
- if (0 != iFaces && 0 != iVertices)
- {
- apcOutMeshes.push_back(new aiMesh());
- aiMesh* pcMesh = apcOutMeshes.back();
- pcMesh->mNumFaces = iFaces;
- pcMesh->mNumVertices = iVertices;
- pcMesh->mFaces = new aiFace[iFaces];
- pcMesh->mVertices = new aiVector3D[iVertices];
- pcMesh->mMaterialIndex = i;
- if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
- if ((*j) & 0x4)
- {
- pcMesh->mTangents = new aiVector3D[iVertices];
- pcMesh->mBitangents = new aiVector3D[iVertices];
- }
- iFaces = 0;
- while ((*j) & (0x100 << iFaces))
- {
- pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
- if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
- else pcMesh->mNumUVComponents[iFaces] = 2;
- iFaces++;
- }
- iFaces = 0;
- while ((*j) & (0x1000000 << iFaces))
- pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
-
- // fill the mesh ...
- unsigned int aiTemp[2] = {0,0};
- CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]);
- }
- }
- }
-
- // If no meshes are referenced in the node graph it is possible that we get no output meshes.
- if (apcOutMeshes.empty()) {
- throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
- }
- else
- {
- // now delete all meshes in the scene and build a new mesh list
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- {
- aiMesh* mesh = pScene->mMeshes[i];
- mesh->mNumBones = 0;
- mesh->mBones = NULL;
-
- // we're reusing the face index arrays. avoid destruction
- for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
- mesh->mFaces[a].mNumIndices = 0;
- mesh->mFaces[a].mIndices = NULL;
- }
-
- delete mesh;
-
- // Invalidate the contents of the old mesh array. We will most
- // likely have less output meshes now, so the last entries of
- // the mesh array are not overridden. We set them to NULL to
- // make sure the developer gets notified when his application
- // attempts to access these fields ...
- mesh = NULL;
- }
-
- // It is impossible that we have more output meshes than
- // input meshes, so we can easily reuse the old mesh array
- pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
- pScene->mMeshes[i] = apcOutMeshes[i];
- }
- }
- }
-
- // remove all animations from the scene
- for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
- delete pScene->mAnimations[i];
- delete[] pScene->mAnimations;
-
- pScene->mAnimations = NULL;
- pScene->mNumAnimations = 0;
-
- // --- we need to keep all cameras and lights
- for (unsigned int i = 0; i < pScene->mNumCameras;++i)
- {
- aiCamera* cam = pScene->mCameras[i];
- const aiNode* nd = pScene->mRootNode->FindNode(cam->mName);
- ai_assert(NULL != nd);
-
- // multiply all properties of the camera with the absolute
- // transformation of the corresponding node
- cam->mPosition = nd->mTransformation * cam->mPosition;
- cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt;
- cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp;
- }
-
- for (unsigned int i = 0; i < pScene->mNumLights;++i)
- {
- aiLight* l = pScene->mLights[i];
- const aiNode* nd = pScene->mRootNode->FindNode(l->mName);
- ai_assert(NULL != nd);
-
- // multiply all properties of the camera with the absolute
- // transformation of the corresponding node
- l->mPosition = nd->mTransformation * l->mPosition;
- l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection;
- }
-
- if( !configKeepHierarchy ) {
-
- // now delete all nodes in the scene and build a new
- // flat node graph with a root node and some level 1 children
- delete pScene->mRootNode;
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<dummy_root>");
-
- if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
- {
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- }
- else
- {
- pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
- aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
-
- // generate mesh nodes
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
- {
- aiNode* pcNode = *nodes = new aiNode();
- pcNode->mParent = pScene->mRootNode;
- pcNode->mName.length = ::sprintf(pcNode->mName.data,"mesh_%i",i);
-
- // setup mesh indices
- pcNode->mNumMeshes = 1;
- pcNode->mMeshes = new unsigned int[1];
- pcNode->mMeshes[0] = i;
- }
- // generate light nodes
- for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
- {
- aiNode* pcNode = *nodes = new aiNode();
- pcNode->mParent = pScene->mRootNode;
- pcNode->mName.length = ::sprintf(pcNode->mName.data,"light_%i",i);
- pScene->mLights[i]->mName = pcNode->mName;
- }
- // generate camera nodes
- for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes)
- {
- aiNode* pcNode = *nodes = new aiNode();
- pcNode->mParent = pScene->mRootNode;
- pcNode->mName.length = ::sprintf(pcNode->mName.data,"cam_%i",i);
- pScene->mCameras[i]->mName = pcNode->mName;
- }
- }
- }
- else {
- // ... and finally set the transformation matrix of all nodes to identity
- MakeIdentityTransform(pScene->mRootNode);
- }
-
- if (configNormalize) {
- // compute the boundary of all meshes
- aiVector3D min,max;
- MinMaxChooser<aiVector3D> ()(min,max);
-
- for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
- aiMesh* m = pScene->mMeshes[a];
- for (unsigned int i = 0; i < m->mNumVertices;++i) {
- min = std::min(m->mVertices[i],min);
- max = std::max(m->mVertices[i],max);
- }
- }
-
- // find the dominant axis
- aiVector3D d = max-min;
- const float div = std::max(d.x,std::max(d.y,d.z))*0.5f;
-
- d = min+d*0.5f;
- for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
- aiMesh* m = pScene->mMeshes[a];
- for (unsigned int i = 0; i < m->mNumVertices;++i) {
- m->mVertices[i] = (m->mVertices[i]-d)/div;
- }
- }
- }
-
- // print statistics
- if (!DefaultLogger::isNullLogger())
- {
- char buffer[4096];
-
- DefaultLogger::get()->debug("PretransformVerticesProcess finished");
-
- sprintf(buffer,"Removed %i nodes and %i animation channels (%i output nodes)",
- iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode));
- DefaultLogger::get()->info(buffer);
-
- sprintf(buffer,"Kept %i lights and %i cameras",
- pScene->mNumLights,pScene->mNumCameras);
- DefaultLogger::get()->info(buffer);
-
- sprintf(buffer,"Moved %i meshes to WCS (number of output meshes: %i)",
- iOldMeshes,pScene->mNumMeshes);
- DefaultLogger::get()->info(buffer);
- }
+ DefaultLogger::get()->debug("PretransformVerticesProcess begin");
+
+ // Return immediately if we have no meshes
+ if (!pScene->mNumMeshes)
+ return;
+
+ const unsigned int iOldMeshes = pScene->mNumMeshes;
+ const unsigned int iOldAnimationChannels = pScene->mNumAnimations;
+ const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
+
+ if(configTransform) {
+ pScene->mRootNode->mTransformation = configTransformation;
+ }
+
+ // first compute absolute transformation matrices for all nodes
+ ComputeAbsoluteTransform(pScene->mRootNode);
+
+ // Delete aiMesh::mBones for all meshes. The bones are
+ // removed during this step and we need the pointer as
+ // temporary storage
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ aiMesh* mesh = pScene->mMeshes[i];
+
+ for (unsigned int a = 0; a < mesh->mNumBones;++a)
+ delete mesh->mBones[a];
+
+ delete[] mesh->mBones;
+ mesh->mBones = NULL;
+ }
+
+ // now build a list of output meshes
+ std::vector<aiMesh*> apcOutMeshes;
+
+ // Keep scene hierarchy? It's an easy job in this case ...
+ // we go on and transform all meshes, if one is referenced by nodes
+ // with different absolute transformations a depth copy of the mesh
+ // is required.
+ if( configKeepHierarchy ) {
+
+ // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones
+ BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode);
+
+ // ... if new meshes have been generated, append them to the end of the scene
+ if (apcOutMeshes.size() > 0) {
+ aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()];
+
+ memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes);
+ memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size());
+
+ pScene->mNumMeshes += apcOutMeshes.size();
+ delete[] pScene->mMeshes; pScene->mMeshes = npp;
+ }
+
+ // now iterate through all meshes and transform them to worldspace
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones ));
+
+ // prevent improper destruction
+ pScene->mMeshes[i]->mBones = NULL;
+ pScene->mMeshes[i]->mNumBones = 0;
+ }
+ }
+ else {
+
+ apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
+ std::list<unsigned int> aiVFormats;
+
+ std::vector<unsigned int> s(pScene->mNumMeshes,0);
+ BuildMeshRefCountArray(pScene->mRootNode,&s[0]);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ // get the list of all vertex formats for this material
+ aiVFormats.clear();
+ GetVFormatList(pScene,i,aiVFormats);
+ aiVFormats.sort();
+ aiVFormats.unique();
+ for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
+ unsigned int iVertices = 0;
+ unsigned int iFaces = 0;
+ CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);
+ if (0 != iFaces && 0 != iVertices)
+ {
+ apcOutMeshes.push_back(new aiMesh());
+ aiMesh* pcMesh = apcOutMeshes.back();
+ pcMesh->mNumFaces = iFaces;
+ pcMesh->mNumVertices = iVertices;
+ pcMesh->mFaces = new aiFace[iFaces];
+ pcMesh->mVertices = new aiVector3D[iVertices];
+ pcMesh->mMaterialIndex = i;
+ if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices];
+ if ((*j) & 0x4)
+ {
+ pcMesh->mTangents = new aiVector3D[iVertices];
+ pcMesh->mBitangents = new aiVector3D[iVertices];
+ }
+ iFaces = 0;
+ while ((*j) & (0x100 << iFaces))
+ {
+ pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices];
+ if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3;
+ else pcMesh->mNumUVComponents[iFaces] = 2;
+ iFaces++;
+ }
+ iFaces = 0;
+ while ((*j) & (0x1000000 << iFaces))
+ pcMesh->mColors[iFaces++] = new aiColor4D[iVertices];
+
+ // fill the mesh ...
+ unsigned int aiTemp[2] = {0,0};
+ CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]);
+ }
+ }
+ }
+
+ // If no meshes are referenced in the node graph it is possible that we get no output meshes.
+ if (apcOutMeshes.empty()) {
+ throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
+ }
+ else
+ {
+ // now delete all meshes in the scene and build a new mesh list
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ aiMesh* mesh = pScene->mMeshes[i];
+ mesh->mNumBones = 0;
+ mesh->mBones = NULL;
+
+ // we're reusing the face index arrays. avoid destruction
+ for (unsigned int a = 0; a < mesh->mNumFaces; ++a) {
+ mesh->mFaces[a].mNumIndices = 0;
+ mesh->mFaces[a].mIndices = NULL;
+ }
+
+ delete mesh;
+
+ // Invalidate the contents of the old mesh array. We will most
+ // likely have less output meshes now, so the last entries of
+ // the mesh array are not overridden. We set them to NULL to
+ // make sure the developer gets notified when his application
+ // attempts to access these fields ...
+ mesh = NULL;
+ }
+
+ // It is impossible that we have more output meshes than
+ // input meshes, so we can easily reuse the old mesh array
+ pScene->mNumMeshes = (unsigned int)apcOutMeshes.size();
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ pScene->mMeshes[i] = apcOutMeshes[i];
+ }
+ }
+ }
+
+ // remove all animations from the scene
+ for (unsigned int i = 0; i < pScene->mNumAnimations;++i)
+ delete pScene->mAnimations[i];
+ delete[] pScene->mAnimations;
+
+ pScene->mAnimations = NULL;
+ pScene->mNumAnimations = 0;
+
+ // --- we need to keep all cameras and lights
+ for (unsigned int i = 0; i < pScene->mNumCameras;++i)
+ {
+ aiCamera* cam = pScene->mCameras[i];
+ const aiNode* nd = pScene->mRootNode->FindNode(cam->mName);
+ ai_assert(NULL != nd);
+
+ // multiply all properties of the camera with the absolute
+ // transformation of the corresponding node
+ cam->mPosition = nd->mTransformation * cam->mPosition;
+ cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt;
+ cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp;
+ }
+
+ for (unsigned int i = 0; i < pScene->mNumLights;++i)
+ {
+ aiLight* l = pScene->mLights[i];
+ const aiNode* nd = pScene->mRootNode->FindNode(l->mName);
+ ai_assert(NULL != nd);
+
+ // multiply all properties of the camera with the absolute
+ // transformation of the corresponding node
+ l->mPosition = nd->mTransformation * l->mPosition;
+ l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection;
+ l->mUp = aiMatrix3x3( nd->mTransformation ) * l->mUp;
+ }
+
+ if( !configKeepHierarchy ) {
+
+ // now delete all nodes in the scene and build a new
+ // flat node graph with a root node and some level 1 children
+ delete pScene->mRootNode;
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<dummy_root>");
+
+ if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
+ {
+ pScene->mRootNode->mNumMeshes = 1;
+ pScene->mRootNode->mMeshes = new unsigned int[1];
+ pScene->mRootNode->mMeshes[0] = 0;
+ }
+ else
+ {
+ pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras;
+ aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+
+ // generate mesh nodes
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes)
+ {
+ aiNode* pcNode = *nodes = new aiNode();
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"mesh_%u",i);
+
+ // setup mesh indices
+ pcNode->mNumMeshes = 1;
+ pcNode->mMeshes = new unsigned int[1];
+ pcNode->mMeshes[0] = i;
+ }
+ // generate light nodes
+ for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes)
+ {
+ aiNode* pcNode = *nodes = new aiNode();
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u",i);
+ pScene->mLights[i]->mName = pcNode->mName;
+ }
+ // generate camera nodes
+ for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes)
+ {
+ aiNode* pcNode = *nodes = new aiNode();
+ pcNode->mParent = pScene->mRootNode;
+ pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"cam_%u",i);
+ pScene->mCameras[i]->mName = pcNode->mName;
+ }
+ }
+ }
+ else {
+ // ... and finally set the transformation matrix of all nodes to identity
+ MakeIdentityTransform(pScene->mRootNode);
+ }
+
+ if (configNormalize) {
+ // compute the boundary of all meshes
+ aiVector3D min,max;
+ MinMaxChooser<aiVector3D> ()(min,max);
+
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ aiMesh* m = pScene->mMeshes[a];
+ for (unsigned int i = 0; i < m->mNumVertices;++i) {
+ min = std::min(m->mVertices[i],min);
+ max = std::max(m->mVertices[i],max);
+ }
+ }
+
+ // find the dominant axis
+ aiVector3D d = max-min;
+ const float div = std::max(d.x,std::max(d.y,d.z))*0.5f;
+
+ d = min+d*0.5f;
+ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+ aiMesh* m = pScene->mMeshes[a];
+ for (unsigned int i = 0; i < m->mNumVertices;++i) {
+ m->mVertices[i] = (m->mVertices[i]-d)/div;
+ }
+ }
+ }
+
+ // print statistics
+ if (!DefaultLogger::isNullLogger())
+ {
+ char buffer[4096];
+
+ DefaultLogger::get()->debug("PretransformVerticesProcess finished");
+
+ ::ai_snprintf(buffer,4096,"Removed %u nodes and %u animation channels (%u output nodes)",
+ iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode));
+ DefaultLogger::get()->info(buffer);
+
+ ai_snprintf(buffer, 4096,"Kept %u lights and %u cameras",
+ pScene->mNumLights,pScene->mNumCameras);
+ DefaultLogger::get()->info(buffer);
+
+ ai_snprintf(buffer, 4096,"Moved %u meshes to WCS (number of output meshes: %u)",
+ iOldMeshes,pScene->mNumMeshes);
+ DefaultLogger::get()->info(buffer);
+ }
}
diff --git a/src/3rdparty/assimp/code/PretransformVertices.h b/src/3rdparty/assimp/code/PretransformVertices.h
index 3738810ff..28bd95a67 100644
--- a/src/3rdparty/assimp/code/PretransformVertices.h
+++ b/src/3rdparty/assimp/code/PretransformVertices.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,33 +23,36 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file PretransformVertices.h
- * @brief Defines a post processing step to pretransform all
- * vertices in the scenegraph
+ * @brief Defines a post processing step to pretransform all
+ * vertices in the scenegraph
*/
#ifndef AI_PRETRANSFORMVERTICES_H_INC
#define AI_PRETRANSFORMVERTICES_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
+#include <list>
+#include <vector>
+struct aiNode;
class PretransformVerticesTest;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** The PretransformVertices pre-transforms all vertices in the node tree
@@ -60,102 +63,102 @@ class ASSIMP_API PretransformVertices : public BaseProcess
{
public:
- PretransformVertices ();
- ~PretransformVertices ();
+ PretransformVertices ();
+ ~PretransformVertices ();
public:
- // -------------------------------------------------------------------
- // Check whether step is active
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- // Execute step on a given scene
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
- // -------------------------------------------------------------------
- // Setup import settings
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
- // -------------------------------------------------------------------
- /** @brief Toggle the 'keep hierarchy' option
- * @param d hm ... difficult to guess what this means, hu!?
- */
- void KeepHierarchy(bool d) {
- configKeepHierarchy = d;
- }
+ // -------------------------------------------------------------------
+ /** @brief Toggle the 'keep hierarchy' option
+ * @param d hm ... difficult to guess what this means, hu!?
+ */
+ void KeepHierarchy(bool d) {
+ configKeepHierarchy = d;
+ }
- // -------------------------------------------------------------------
- /** @brief Check whether 'keep hierarchy' is currently enabled.
- * @return ...
- */
- bool IsHierarchyKept() const {
- return configKeepHierarchy;
- }
+ // -------------------------------------------------------------------
+ /** @brief Check whether 'keep hierarchy' is currently enabled.
+ * @return ...
+ */
+ bool IsHierarchyKept() const {
+ return configKeepHierarchy;
+ }
private:
- // -------------------------------------------------------------------
- // Count the number of nodes
- unsigned int CountNodes( aiNode* pcNode );
-
- // -------------------------------------------------------------------
- // Get a bitwise combination identifying the vertex format of a mesh
- unsigned int GetMeshVFormat(aiMesh* pcMesh);
-
- // -------------------------------------------------------------------
- // Count the number of vertices in the whole scene and a given
- // material index
- void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode,
- unsigned int iMat,
- unsigned int iVFormat,
- unsigned int* piFaces,
- unsigned int* piVertices);
-
- // -------------------------------------------------------------------
- // Collect vertex/face data
- void CollectData( aiScene* pcScene, aiNode* pcNode,
- unsigned int iMat,
- unsigned int iVFormat,
- aiMesh* pcMeshOut,
- unsigned int aiCurrent[2],
- unsigned int* num_refs);
-
- // -------------------------------------------------------------------
- // Get a list of all vertex formats that occur for a given material
- // The output list contains duplicate elements
- void GetVFormatList( aiScene* pcScene, unsigned int iMat,
- std::list<unsigned int>& aiOut);
-
- // -------------------------------------------------------------------
- // Compute the absolute transformation matrices of each node
- void ComputeAbsoluteTransform( aiNode* pcNode );
-
- // -------------------------------------------------------------------
- // Simple routine to build meshes in worldspace, no further optimization
- void BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
- unsigned int numIn, aiNode* node);
-
- // -------------------------------------------------------------------
- // Apply the node transformation to a mesh
- void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat);
-
- // -------------------------------------------------------------------
- // Reset transformation matrices to identity
- void MakeIdentityTransform(aiNode* nd);
-
- // -------------------------------------------------------------------
- // Build reference counters for all meshes
- void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs);
-
-
-
- //! Configuration option: keep scene hierarchy as long as possible
- bool configKeepHierarchy;
- bool configNormalize;
- bool configTransform;
- aiMatrix4x4 configTransformation;
+ // -------------------------------------------------------------------
+ // Count the number of nodes
+ unsigned int CountNodes( aiNode* pcNode );
+
+ // -------------------------------------------------------------------
+ // Get a bitwise combination identifying the vertex format of a mesh
+ unsigned int GetMeshVFormat(aiMesh* pcMesh);
+
+ // -------------------------------------------------------------------
+ // Count the number of vertices in the whole scene and a given
+ // material index
+ void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode,
+ unsigned int iMat,
+ unsigned int iVFormat,
+ unsigned int* piFaces,
+ unsigned int* piVertices);
+
+ // -------------------------------------------------------------------
+ // Collect vertex/face data
+ void CollectData( aiScene* pcScene, aiNode* pcNode,
+ unsigned int iMat,
+ unsigned int iVFormat,
+ aiMesh* pcMeshOut,
+ unsigned int aiCurrent[2],
+ unsigned int* num_refs);
+
+ // -------------------------------------------------------------------
+ // Get a list of all vertex formats that occur for a given material
+ // The output list contains duplicate elements
+ void GetVFormatList( aiScene* pcScene, unsigned int iMat,
+ std::list<unsigned int>& aiOut);
+
+ // -------------------------------------------------------------------
+ // Compute the absolute transformation matrices of each node
+ void ComputeAbsoluteTransform( aiNode* pcNode );
+
+ // -------------------------------------------------------------------
+ // Simple routine to build meshes in worldspace, no further optimization
+ void BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in,
+ unsigned int numIn, aiNode* node);
+
+ // -------------------------------------------------------------------
+ // Apply the node transformation to a mesh
+ void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat);
+
+ // -------------------------------------------------------------------
+ // Reset transformation matrices to identity
+ void MakeIdentityTransform(aiNode* nd);
+
+ // -------------------------------------------------------------------
+ // Build reference counters for all meshes
+ void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs);
+
+
+
+ //! Configuration option: keep scene hierarchy as long as possible
+ bool configKeepHierarchy;
+ bool configNormalize;
+ bool configTransform;
+ aiMatrix4x4 configTransformation;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/ProcessHelper.cpp b/src/3rdparty/assimp/code/ProcessHelper.cpp
index bccf37e57..e18d54c30 100644
--- a/src/3rdparty/assimp/code/ProcessHelper.cpp
+++ b/src/3rdparty/assimp/code/ProcessHelper.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// @file ProcessHelper.cpp
/** Implement shared utility functions for postprocessing steps */
-#include "AssimpPCH.h"
+
#include "ProcessHelper.h"
@@ -52,364 +52,390 @@ namespace Assimp {
// -------------------------------------------------------------------------------
void ConvertListToStrings(const std::string& in, std::list<std::string>& out)
{
- const char* s = in.c_str();
- while (*s) {
- SkipSpacesAndLineEnd(&s);
- if (*s == '\'') {
- const char* base = ++s;
- while (*s != '\'') {
- ++s;
- if (*s == '\0') {
- DefaultLogger::get()->error("ConvertListToString: String list is ill-formatted");
- return;
- }
- }
- out.push_back(std::string(base,(size_t)(s-base)));
- ++s;
- }
- else {
- out.push_back(GetNextToken(s));
- }
- }
+ const char* s = in.c_str();
+ while (*s) {
+ SkipSpacesAndLineEnd(&s);
+ if (*s == '\'') {
+ const char* base = ++s;
+ while (*s != '\'') {
+ ++s;
+ if (*s == '\0') {
+ DefaultLogger::get()->error("ConvertListToString: String list is ill-formatted");
+ return;
+ }
+ }
+ out.push_back(std::string(base,(size_t)(s-base)));
+ ++s;
+ }
+ else {
+ out.push_back(GetNextToken(s));
+ }
+ }
}
// -------------------------------------------------------------------------------
-void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
- const aiMatrix4x4& m)
+void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
+ const aiMatrix4x4& m)
{
- min = aiVector3D (10e10f, 10e10f, 10e10f);
- max = aiVector3D (-10e10f,-10e10f,-10e10f);
- for (unsigned int i = 0;i < mesh->mNumVertices;++i)
- {
- const aiVector3D v = m * mesh->mVertices[i];
- min = std::min(v,min);
- max = std::max(v,max);
- }
+ min = aiVector3D (10e10f, 10e10f, 10e10f);
+ max = aiVector3D (-10e10f,-10e10f,-10e10f);
+ for (unsigned int i = 0;i < mesh->mNumVertices;++i)
+ {
+ const aiVector3D v = m * mesh->mVertices[i];
+ min = std::min(v,min);
+ max = std::max(v,max);
+ }
}
// -------------------------------------------------------------------------------
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max)
{
- ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max);
- out = min + (max-min)*0.5f;
+ ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max);
+ out = min + (max-min)*0.5f;
}
// -------------------------------------------------------------------------------
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max) {
+ if ( NULL == scene ) {
+ return;
+ }
+
+ if ( 0 == scene->mNumMeshes ) {
+ return;
+ }
+ FindMeshCenter(scene->mMeshes[0], out, min, max);
+ for (unsigned int i = 1; i < scene->mNumMeshes; ++i) {
+ aiVector3D tout, tmin, tmax;
+ FindMeshCenter(scene->mMeshes[i], tout, tmin, tmax);
+ if (min[0] > tmin[0]) min[0] = tmin[0];
+ if (min[1] > tmin[1]) min[1] = tmin[1];
+ if (min[2] > tmin[2]) min[2] = tmin[2];
+ if (max[0] < tmax[0]) max[0] = tmax[0];
+ if (max[1] < tmax[1]) max[1] = tmax[1];
+ if (max[2] < tmax[2]) max[2] = tmax[2];
+ }
+ out = min + (max-min)*0.5f;
+}
+
+
+// -------------------------------------------------------------------------------
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min,
- aiVector3D& max, const aiMatrix4x4& m)
+ aiVector3D& max, const aiMatrix4x4& m)
{
- FindAABBTransformed(mesh,min,max,m);
- out = min + (max-min)*0.5f;
+ FindAABBTransformed(mesh,min,max,m);
+ out = min + (max-min)*0.5f;
}
// -------------------------------------------------------------------------------
void FindMeshCenter (aiMesh* mesh, aiVector3D& out)
{
- aiVector3D min,max;
- FindMeshCenter(mesh,out,min,max);
+ aiVector3D min,max;
+ FindMeshCenter(mesh,out,min,max);
}
// -------------------------------------------------------------------------------
void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out,
- const aiMatrix4x4& m)
+ const aiMatrix4x4& m)
{
- aiVector3D min,max;
- FindMeshCenterTransformed(mesh,out,min,max,m);
+ aiVector3D min,max;
+ FindMeshCenterTransformed(mesh,out,min,max,m);
}
// -------------------------------------------------------------------------------
float ComputePositionEpsilon(const aiMesh* pMesh)
{
- const float epsilon = 1e-4f;
+ const float epsilon = 1e-4f;
- // calculate the position bounds so we have a reliable epsilon to check position differences against
- aiVector3D minVec, maxVec;
- ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec);
- return (maxVec - minVec).Length() * epsilon;
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec, maxVec;
+ ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec);
+ return (maxVec - minVec).Length() * epsilon;
}
// -------------------------------------------------------------------------------
float ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num)
{
- const float epsilon = 1e-4f;
+ ai_assert( NULL != pMeshes );
+
+ const float epsilon = 1e-4f;
- // calculate the position bounds so we have a reliable epsilon to check position differences against
- aiVector3D minVec, maxVec, mi, ma;
- MinMaxChooser<aiVector3D>()(minVec,maxVec);
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec, maxVec, mi, ma;
+ MinMaxChooser<aiVector3D>()(minVec,maxVec);
- for (size_t a = 0; a < num; ++a) {
- const aiMesh* pMesh = pMeshes[a];
- ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma);
+ for (size_t a = 0; a < num; ++a) {
+ const aiMesh* pMesh = pMeshes[a];
+ ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma);
- minVec = std::min(minVec,mi);
- maxVec = std::max(maxVec,ma);
- }
- return (maxVec - minVec).Length() * epsilon;
+ minVec = std::min(minVec,mi);
+ maxVec = std::max(maxVec,ma);
+ }
+ return (maxVec - minVec).Length() * epsilon;
}
// -------------------------------------------------------------------------------
unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh)
{
- ai_assert(NULL != pcMesh);
+ ai_assert(NULL != pcMesh);
- // FIX: the hash may never be 0. Otherwise a comparison against
- // nullptr could be successful
- unsigned int iRet = 1;
+ // FIX: the hash may never be 0. Otherwise a comparison against
+ // nullptr could be successful
+ unsigned int iRet = 1;
- // normals
- if (pcMesh->HasNormals())iRet |= 0x2;
- // tangents and bitangents
- if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
+ // normals
+ if (pcMesh->HasNormals())iRet |= 0x2;
+ // tangents and bitangents
+ if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4;
#ifdef BOOST_STATIC_ASSERT
- BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
- BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
+ BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS);
+ BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS);
#endif
- // texture coordinates
- unsigned int p = 0;
- while (pcMesh->HasTextureCoords(p))
- {
- iRet |= (0x100 << p);
- if (3 == pcMesh->mNumUVComponents[p])
- iRet |= (0x10000 << p);
-
- ++p;
- }
- // vertex colors
- p = 0;
- while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
- return iRet;
+ // texture coordinates
+ unsigned int p = 0;
+ while (pcMesh->HasTextureCoords(p))
+ {
+ iRet |= (0x100 << p);
+ if (3 == pcMesh->mNumUVComponents[p])
+ iRet |= (0x10000 << p);
+
+ ++p;
+ }
+ // vertex colors
+ p = 0;
+ while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++);
+ return iRet;
}
// -------------------------------------------------------------------------------
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh)
{
- if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
- return NULL;
- }
-
- VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
- for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
-
- aiBone* bone = pMesh->mBones[i];
- for (unsigned int a = 0; a < bone->mNumWeights;++a) {
- const aiVertexWeight& weight = bone->mWeights[a];
- avPerVertexWeights[weight.mVertexId].push_back( std::pair<unsigned int,float>(i,weight.mWeight) );
- }
- }
- return avPerVertexWeights;
+ if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
+ return NULL;
+ }
+
+ VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
+ for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
+
+ aiBone* bone = pMesh->mBones[i];
+ for (unsigned int a = 0; a < bone->mNumWeights;++a) {
+ const aiVertexWeight& weight = bone->mWeights[a];
+ avPerVertexWeights[weight.mVertexId].push_back( std::pair<unsigned int,float>(i,weight.mWeight) );
+ }
+ }
+ return avPerVertexWeights;
}
// -------------------------------------------------------------------------------
const char* TextureTypeToString(aiTextureType in)
{
- switch (in)
- {
- case aiTextureType_NONE:
- return "n/a";
- case aiTextureType_DIFFUSE:
- return "Diffuse";
- case aiTextureType_SPECULAR:
- return "Specular";
- case aiTextureType_AMBIENT:
- return "Ambient";
- case aiTextureType_EMISSIVE:
- return "Emissive";
- case aiTextureType_OPACITY:
- return "Opacity";
- case aiTextureType_NORMALS:
- return "Normals";
- case aiTextureType_HEIGHT:
- return "Height";
- case aiTextureType_SHININESS:
- return "Shininess";
- case aiTextureType_DISPLACEMENT:
- return "Displacement";
- case aiTextureType_LIGHTMAP:
- return "Lightmap";
- case aiTextureType_REFLECTION:
- return "Reflection";
- case aiTextureType_UNKNOWN:
- return "Unknown";
- default:
- break;
- }
-
- ai_assert(false);
- return "BUG";
+ switch (in)
+ {
+ case aiTextureType_NONE:
+ return "n/a";
+ case aiTextureType_DIFFUSE:
+ return "Diffuse";
+ case aiTextureType_SPECULAR:
+ return "Specular";
+ case aiTextureType_AMBIENT:
+ return "Ambient";
+ case aiTextureType_EMISSIVE:
+ return "Emissive";
+ case aiTextureType_OPACITY:
+ return "Opacity";
+ case aiTextureType_NORMALS:
+ return "Normals";
+ case aiTextureType_HEIGHT:
+ return "Height";
+ case aiTextureType_SHININESS:
+ return "Shininess";
+ case aiTextureType_DISPLACEMENT:
+ return "Displacement";
+ case aiTextureType_LIGHTMAP:
+ return "Lightmap";
+ case aiTextureType_REFLECTION:
+ return "Reflection";
+ case aiTextureType_UNKNOWN:
+ return "Unknown";
+ default:
+ break;
+ }
+
+ ai_assert(false);
+ return "BUG";
}
// -------------------------------------------------------------------------------
const char* MappingTypeToString(aiTextureMapping in)
{
- switch (in)
- {
- case aiTextureMapping_UV:
- return "UV";
- case aiTextureMapping_BOX:
- return "Box";
- case aiTextureMapping_SPHERE:
- return "Sphere";
- case aiTextureMapping_CYLINDER:
- return "Cylinder";
- case aiTextureMapping_PLANE:
- return "Plane";
- case aiTextureMapping_OTHER:
- return "Other";
- default:
- break;
- }
-
- ai_assert(false);
- return "BUG";
+ switch (in)
+ {
+ case aiTextureMapping_UV:
+ return "UV";
+ case aiTextureMapping_BOX:
+ return "Box";
+ case aiTextureMapping_SPHERE:
+ return "Sphere";
+ case aiTextureMapping_CYLINDER:
+ return "Cylinder";
+ case aiTextureMapping_PLANE:
+ return "Plane";
+ case aiTextureMapping_OTHER:
+ return "Other";
+ default:
+ break;
+ }
+
+ ai_assert(false);
+ return "BUG";
}
// -------------------------------------------------------------------------------
aiMesh* MakeSubmesh(const aiMesh *pMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags)
-{
- aiMesh *oMesh = new aiMesh();
- std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);
-
- size_t numSubVerts = 0;
- size_t numSubFaces = subMeshFaces.size();
-
- for(unsigned int i=0;i<numSubFaces;i++) {
- const aiFace &f = pMesh->mFaces[subMeshFaces[i]];
-
- for(unsigned int j=0;j<f.mNumIndices;j++) {
- if(vMap[f.mIndices[j]]==UINT_MAX) {
- vMap[f.mIndices[j]] = numSubVerts++;
- }
- }
- }
-
- oMesh->mName = pMesh->mName;
-
- oMesh->mMaterialIndex = pMesh->mMaterialIndex;
- oMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
-
- // create all the arrays for this mesh if the old mesh contained them
-
- oMesh->mNumFaces = subMeshFaces.size();
- oMesh->mNumVertices = numSubVerts;
- oMesh->mVertices = new aiVector3D[numSubVerts];
- if( pMesh->HasNormals() ) {
- oMesh->mNormals = new aiVector3D[numSubVerts];
- }
-
- if( pMesh->HasTangentsAndBitangents() ) {
- oMesh->mTangents = new aiVector3D[numSubVerts];
- oMesh->mBitangents = new aiVector3D[numSubVerts];
- }
-
- for( size_t a = 0; pMesh->HasTextureCoords( a) ; ++a ) {
- oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
- oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
- }
-
- for( size_t a = 0; pMesh->HasVertexColors( a); ++a ) {
- oMesh->mColors[a] = new aiColor4D[numSubVerts];
- }
-
- // and copy over the data, generating faces with linear indices along the way
- oMesh->mFaces = new aiFace[numSubFaces];
-
- for(unsigned int a = 0; a < numSubFaces; ++a ) {
-
- const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
- aiFace& dstFace = oMesh->mFaces[a];
- dstFace.mNumIndices = srcFace.mNumIndices;
- dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
-
- // accumulate linearly all the vertices of the source face
- for( size_t b = 0; b < dstFace.mNumIndices; ++b ) {
- dstFace.mIndices[b] = vMap[srcFace.mIndices[b]];
- }
- }
-
- for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) {
- unsigned int nvi = vMap[srcIndex];
- if(nvi==UINT_MAX) {
- continue;
- }
-
- oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
- if( pMesh->HasNormals() ) {
- oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
- }
-
- if( pMesh->HasTangentsAndBitangents() ) {
- oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
- oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
- }
- for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c ) {
- oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
- }
- for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) {
- oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
- }
- }
-
- if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES) {
- std::vector<unsigned int> subBones(pMesh->mNumBones,0);
-
- for(unsigned int a=0;a<pMesh->mNumBones;++a) {
- const aiBone* bone = pMesh->mBones[a];
-
- for(unsigned int b=0;b<bone->mNumWeights;b++) {
- unsigned int v = vMap[bone->mWeights[b].mVertexId];
-
- if(v!=UINT_MAX) {
- subBones[a]++;
- }
- }
- }
-
- for(unsigned int a=0;a<pMesh->mNumBones;++a) {
- if(subBones[a]>0) {
- oMesh->mNumBones++;
- }
- }
-
- if(oMesh->mNumBones) {
- oMesh->mBones = new aiBone*[oMesh->mNumBones]();
- unsigned int nbParanoia = oMesh->mNumBones;
-
- oMesh->mNumBones = 0; //rewind
-
- for(unsigned int a=0;a<pMesh->mNumBones;++a) {
- if(subBones[a]==0) {
- continue;
- }
- aiBone *newBone = new aiBone;
- oMesh->mBones[oMesh->mNumBones++] = newBone;
-
- const aiBone* bone = pMesh->mBones[a];
-
- newBone->mName = bone->mName;
- newBone->mOffsetMatrix = bone->mOffsetMatrix;
- newBone->mWeights = new aiVertexWeight[subBones[a]];
-
- for(unsigned int b=0;b<bone->mNumWeights;b++) {
- const unsigned int v = vMap[bone->mWeights[b].mVertexId];
-
- if(v!=UINT_MAX) {
- aiVertexWeight w(v,bone->mWeights[b].mWeight);
- newBone->mWeights[newBone->mNumWeights++] = w;
- }
- }
- }
-
- ai_assert(nbParanoia==oMesh->mNumBones);
- (void)nbParanoia; // remove compiler warning on release build
- }
- }
-
- return oMesh;
+{
+ aiMesh *oMesh = new aiMesh();
+ std::vector<unsigned int> vMap(pMesh->mNumVertices,UINT_MAX);
+
+ size_t numSubVerts = 0;
+ size_t numSubFaces = subMeshFaces.size();
+
+ for(unsigned int i=0;i<numSubFaces;i++) {
+ const aiFace &f = pMesh->mFaces[subMeshFaces[i]];
+
+ for(unsigned int j=0;j<f.mNumIndices;j++) {
+ if(vMap[f.mIndices[j]]==UINT_MAX) {
+ vMap[f.mIndices[j]] = numSubVerts++;
+ }
+ }
+ }
+
+ oMesh->mName = pMesh->mName;
+
+ oMesh->mMaterialIndex = pMesh->mMaterialIndex;
+ oMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
+
+ // create all the arrays for this mesh if the old mesh contained them
+
+ oMesh->mNumFaces = subMeshFaces.size();
+ oMesh->mNumVertices = numSubVerts;
+ oMesh->mVertices = new aiVector3D[numSubVerts];
+ if( pMesh->HasNormals() ) {
+ oMesh->mNormals = new aiVector3D[numSubVerts];
+ }
+
+ if( pMesh->HasTangentsAndBitangents() ) {
+ oMesh->mTangents = new aiVector3D[numSubVerts];
+ oMesh->mBitangents = new aiVector3D[numSubVerts];
+ }
+
+ for( size_t a = 0; pMesh->HasTextureCoords( a) ; ++a ) {
+ oMesh->mTextureCoords[a] = new aiVector3D[numSubVerts];
+ oMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
+ }
+
+ for( size_t a = 0; pMesh->HasVertexColors( a); ++a ) {
+ oMesh->mColors[a] = new aiColor4D[numSubVerts];
+ }
+
+ // and copy over the data, generating faces with linear indices along the way
+ oMesh->mFaces = new aiFace[numSubFaces];
+
+ for(unsigned int a = 0; a < numSubFaces; ++a ) {
+
+ const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
+ aiFace& dstFace = oMesh->mFaces[a];
+ dstFace.mNumIndices = srcFace.mNumIndices;
+ dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
+
+ // accumulate linearly all the vertices of the source face
+ for( size_t b = 0; b < dstFace.mNumIndices; ++b ) {
+ dstFace.mIndices[b] = vMap[srcFace.mIndices[b]];
+ }
+ }
+
+ for(unsigned int srcIndex = 0; srcIndex < pMesh->mNumVertices; ++srcIndex ) {
+ unsigned int nvi = vMap[srcIndex];
+ if(nvi==UINT_MAX) {
+ continue;
+ }
+
+ oMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
+ if( pMesh->HasNormals() ) {
+ oMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
+ }
+
+ if( pMesh->HasTangentsAndBitangents() ) {
+ oMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
+ oMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
+ }
+ for( size_t c = 0, cc = pMesh->GetNumUVChannels(); c < cc; ++c ) {
+ oMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
+ }
+ for( size_t c = 0, cc = pMesh->GetNumColorChannels(); c < cc; ++c ) {
+ oMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
+ }
+ }
+
+ if(~subFlags&AI_SUBMESH_FLAGS_SANS_BONES) {
+ std::vector<unsigned int> subBones(pMesh->mNumBones,0);
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ const aiBone* bone = pMesh->mBones[a];
+
+ for(unsigned int b=0;b<bone->mNumWeights;b++) {
+ unsigned int v = vMap[bone->mWeights[b].mVertexId];
+
+ if(v!=UINT_MAX) {
+ subBones[a]++;
+ }
+ }
+ }
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ if(subBones[a]>0) {
+ oMesh->mNumBones++;
+ }
+ }
+
+ if(oMesh->mNumBones) {
+ oMesh->mBones = new aiBone*[oMesh->mNumBones]();
+ unsigned int nbParanoia = oMesh->mNumBones;
+
+ oMesh->mNumBones = 0; //rewind
+
+ for(unsigned int a=0;a<pMesh->mNumBones;++a) {
+ if(subBones[a]==0) {
+ continue;
+ }
+ aiBone *newBone = new aiBone;
+ oMesh->mBones[oMesh->mNumBones++] = newBone;
+
+ const aiBone* bone = pMesh->mBones[a];
+
+ newBone->mName = bone->mName;
+ newBone->mOffsetMatrix = bone->mOffsetMatrix;
+ newBone->mWeights = new aiVertexWeight[subBones[a]];
+
+ for(unsigned int b=0;b<bone->mNumWeights;b++) {
+ const unsigned int v = vMap[bone->mWeights[b].mVertexId];
+
+ if(v!=UINT_MAX) {
+ aiVertexWeight w(v,bone->mWeights[b].mWeight);
+ newBone->mWeights[newBone->mNumWeights++] = w;
+ }
+ }
+ }
+
+ ai_assert(nbParanoia==oMesh->mNumBones);
+ (void)nbParanoia; // remove compiler warning on release build
+ }
+ }
+
+ return oMesh;
}
} // namespace Assimp
diff --git a/src/3rdparty/assimp/code/ProcessHelper.h b/src/3rdparty/assimp/code/ProcessHelper.h
index 310fe6be8..3f50a46c6 100644
--- a/src/3rdparty/assimp/code/ProcessHelper.h
+++ b/src/3rdparty/assimp/code/ProcessHelper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,12 +41,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_PROCESS_HELPER_H_INCLUDED
#define AI_PROCESS_HELPER_H_INCLUDED
-#include "../include/assimp/postprocess.h"
+#include <assimp/postprocess.h>
+#include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/material.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
#include "SpatialSort.h"
#include "BaseProcess.h"
#include "ParsingUtils.h"
+#include <list>
+
// -------------------------------------------------------------------------------
// Some extensions to std namespace. Mainly std::min and std::max for all
// flat data types in the aiScene. They're used to quickly determine the
@@ -54,86 +61,86 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef __cplusplus
namespace std {
- // std::min for aiVector3D
- template <typename TReal>
- inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
- return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
- }
-
- // std::max for aiVector3t<TReal>
- template <typename TReal>
- inline ::aiVector3t<TReal> max (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
- return ::aiVector3t<TReal> (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
- }
-
- // std::min for aiVector2t<TReal>
- template <typename TReal>
- inline ::aiVector2t<TReal> min (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
- return ::aiVector2t<TReal> (min(a.x,b.x),min(a.y,b.y));
- }
-
- // std::max for aiVector2t<TReal>
- template <typename TReal>
- inline ::aiVector2t<TReal> max (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
- return ::aiVector2t<TReal> (max(a.x,b.x),max(a.y,b.y));
- }
-
- // std::min for aiColor4D
- template <typename TReal>
- inline ::aiColor4t<TReal> min (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
- return ::aiColor4t<TReal> (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a));
- }
-
- // std::max for aiColor4D
- template <typename TReal>
- inline ::aiColor4t<TReal> max (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
- return ::aiColor4t<TReal> (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a));
- }
-
-
- // std::min for aiQuaterniont<TReal>
- template <typename TReal>
- inline ::aiQuaterniont<TReal> min (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
- return ::aiQuaterniont<TReal> (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
- }
-
- // std::max for aiQuaterniont<TReal>
- template <typename TReal>
- inline ::aiQuaterniont<TReal> max (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
- return ::aiQuaterniont<TReal> (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
- }
-
-
-
- // std::min for aiVectorKey
- inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) {
- return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
- }
-
- // std::max for aiVectorKey
- inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) {
- return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
- }
-
- // std::min for aiQuatKey
- inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) {
- return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
- }
-
- // std::max for aiQuatKey
- inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) {
- return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
- }
-
- // std::min for aiVertexWeight
- inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
- return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight));
- }
-
- // std::max for aiVertexWeight
- inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
- return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight));
- }
+ // std::min for aiVector3D
+ template <typename TReal>
+ inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
+ return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
+ }
+
+ // std::max for aiVector3t<TReal>
+ template <typename TReal>
+ inline ::aiVector3t<TReal> max (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b) {
+ return ::aiVector3t<TReal> (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
+ }
+
+ // std::min for aiVector2t<TReal>
+ template <typename TReal>
+ inline ::aiVector2t<TReal> min (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
+ return ::aiVector2t<TReal> (min(a.x,b.x),min(a.y,b.y));
+ }
+
+ // std::max for aiVector2t<TReal>
+ template <typename TReal>
+ inline ::aiVector2t<TReal> max (const ::aiVector2t<TReal>& a, const ::aiVector2t<TReal>& b) {
+ return ::aiVector2t<TReal> (max(a.x,b.x),max(a.y,b.y));
+ }
+
+ // std::min for aiColor4D
+ template <typename TReal>
+ inline ::aiColor4t<TReal> min (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
+ return ::aiColor4t<TReal> (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a));
+ }
+
+ // std::max for aiColor4D
+ template <typename TReal>
+ inline ::aiColor4t<TReal> max (const ::aiColor4t<TReal>& a, const ::aiColor4t<TReal>& b) {
+ return ::aiColor4t<TReal> (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a));
+ }
+
+
+ // std::min for aiQuaterniont<TReal>
+ template <typename TReal>
+ inline ::aiQuaterniont<TReal> min (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
+ return ::aiQuaterniont<TReal> (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
+ }
+
+ // std::max for aiQuaterniont<TReal>
+ template <typename TReal>
+ inline ::aiQuaterniont<TReal> max (const ::aiQuaterniont<TReal>& a, const ::aiQuaterniont<TReal>& b) {
+ return ::aiQuaterniont<TReal> (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z));
+ }
+
+
+
+ // std::min for aiVectorKey
+ inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) {
+ return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
+ }
+
+ // std::max for aiVectorKey
+ inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) {
+ return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
+ }
+
+ // std::min for aiQuatKey
+ inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) {
+ return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue));
+ }
+
+ // std::max for aiQuatKey
+ inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) {
+ return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue));
+ }
+
+ // std::min for aiVertexWeight
+ inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
+ return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight));
+ }
+
+ // std::max for aiVertexWeight
+ inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) {
+ return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight));
+ }
} // end namespace std
#endif // !! C++
@@ -146,58 +153,58 @@ template <typename T>
struct MinMaxChooser;
template <> struct MinMaxChooser<float> {
- void operator ()(float& min,float& max) {
- max = -1e10f;
- min = 1e10f;
+ void operator ()(float& min,float& max) {
+ max = -1e10f;
+ min = 1e10f;
}};
template <> struct MinMaxChooser<double> {
- void operator ()(double& min,double& max) {
- max = -1e10;
- min = 1e10;
+ void operator ()(double& min,double& max) {
+ max = -1e10;
+ min = 1e10;
}};
template <> struct MinMaxChooser<unsigned int> {
- void operator ()(unsigned int& min,unsigned int& max) {
- max = 0;
- min = (1u<<(sizeof(unsigned int)*8-1));
+ void operator ()(unsigned int& min,unsigned int& max) {
+ max = 0;
+ min = (1u<<(sizeof(unsigned int)*8-1));
}};
template <typename T> struct MinMaxChooser< aiVector3t<T> > {
- void operator ()(aiVector3t<T>& min,aiVector3t<T>& max) {
- max = aiVector3t<T>(-1e10f,-1e10f,-1e10f);
- min = aiVector3t<T>( 1e10f, 1e10f, 1e10f);
+ void operator ()(aiVector3t<T>& min,aiVector3t<T>& max) {
+ max = aiVector3t<T>(-1e10f,-1e10f,-1e10f);
+ min = aiVector3t<T>( 1e10f, 1e10f, 1e10f);
}};
template <typename T> struct MinMaxChooser< aiVector2t<T> > {
- void operator ()(aiVector2t<T>& min,aiVector2t<T>& max) {
- max = aiVector2t<T>(-1e10f,-1e10f);
- min = aiVector2t<T>( 1e10f, 1e10f);
- }};
+ void operator ()(aiVector2t<T>& min,aiVector2t<T>& max) {
+ max = aiVector2t<T>(-1e10f,-1e10f);
+ min = aiVector2t<T>( 1e10f, 1e10f);
+ }};
template <typename T> struct MinMaxChooser< aiColor4t<T> > {
- void operator ()(aiColor4t<T>& min,aiColor4t<T>& max) {
- max = aiColor4t<T>(-1e10f,-1e10f,-1e10f,-1e10f);
- min = aiColor4t<T>( 1e10f, 1e10f, 1e10f, 1e10f);
+ void operator ()(aiColor4t<T>& min,aiColor4t<T>& max) {
+ max = aiColor4t<T>(-1e10f,-1e10f,-1e10f,-1e10f);
+ min = aiColor4t<T>( 1e10f, 1e10f, 1e10f, 1e10f);
}};
template <typename T> struct MinMaxChooser< aiQuaterniont<T> > {
- void operator ()(aiQuaterniont<T>& min,aiQuaterniont<T>& max) {
- max = aiQuaterniont<T>(-1e10f,-1e10f,-1e10f,-1e10f);
- min = aiQuaterniont<T>( 1e10f, 1e10f, 1e10f, 1e10f);
+ void operator ()(aiQuaterniont<T>& min,aiQuaterniont<T>& max) {
+ max = aiQuaterniont<T>(-1e10f,-1e10f,-1e10f,-1e10f);
+ min = aiQuaterniont<T>( 1e10f, 1e10f, 1e10f, 1e10f);
}};
template <> struct MinMaxChooser<aiVectorKey> {
- void operator ()(aiVectorKey& min,aiVectorKey& max) {
- MinMaxChooser<double>()(min.mTime,max.mTime);
- MinMaxChooser<aiVector3D>()(min.mValue,max.mValue);
+ void operator ()(aiVectorKey& min,aiVectorKey& max) {
+ MinMaxChooser<double>()(min.mTime,max.mTime);
+ MinMaxChooser<aiVector3D>()(min.mValue,max.mValue);
}};
template <> struct MinMaxChooser<aiQuatKey> {
- void operator ()(aiQuatKey& min,aiQuatKey& max) {
- MinMaxChooser<double>()(min.mTime,max.mTime);
- MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue);
+ void operator ()(aiQuatKey& min,aiQuatKey& max) {
+ MinMaxChooser<double>()(min.mTime,max.mTime);
+ MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue);
}};
template <> struct MinMaxChooser<aiVertexWeight> {
- void operator ()(aiVertexWeight& min,aiVertexWeight& max) {
- MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId);
- MinMaxChooser<float>()(min.mWeight,max.mWeight);
+ void operator ()(aiVertexWeight& min,aiVertexWeight& max) {
+ MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId);
+ MinMaxChooser<float>()(min.mWeight,max.mWeight);
}};
// -------------------------------------------------------------------------------
@@ -208,32 +215,32 @@ template <> struct MinMaxChooser<aiVertexWeight> {
* @param[out] max maximum value
*/
template <typename T>
-inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
+inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max)
{
- MinMaxChooser<T> ()(min,max);
- for (unsigned int i = 0; i < size;++i) {
- min = std::min(in[i],min);
- max = std::max(in[i],max);
- }
+ MinMaxChooser<T> ()(min,max);
+ for (unsigned int i = 0; i < size;++i) {
+ min = std::min(in[i],min);
+ max = std::max(in[i],max);
+ }
}
// -------------------------------------------------------------------------------
-/** Little helper function to calculate the quadratic difference
- * of two colours.
+/** Little helper function to calculate the quadratic difference
+ * of two colours.
* @param pColor1 First color
* @param pColor2 second color
* @return Quadratic color difference */
-inline float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
+inline float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2)
{
- const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
- return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
+ const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
+ return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a;
}
// -------------------------------------------------------------------------------
/** @brief Extract single strings from a list of identifiers
- * @param in Input string list.
+ * @param in Input string list.
* @param out Receives a list of clean output strings
* @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */
void ConvertListToStrings(const std::string& in, std::list<std::string>& out);
@@ -258,6 +265,16 @@ void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max,
* @param[out] out Center point */
void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max);
+// -------------------------------------------------------------------------------
+/** @brief Helper function to determine the 'real' center of a scene
+ *
+ * That is the center of its axis-aligned bounding box.
+ * @param scene Input scene
+ * @param[out] min Minimum vertex of the scene
+ * @param[out] max maximum vertex of the scene
+ * @param[out] out Center point */
+void FindSceneCenter (aiScene* scene, aiVector3D& out, aiVector3D& min, aiVector3D& max);
+
// -------------------------------------------------------------------------------
// Helper function to determine the 'real' center of a mesh after applying a given transform
@@ -291,7 +308,7 @@ unsigned int GetMeshVFormatUnique(const aiMesh* pcMesh);
// defs for ComputeVertexBoneWeightTable()
typedef std::pair <unsigned int,float> PerVertexWeight;
-typedef std::vector <PerVertexWeight> VertexWeightTable;
+typedef std::vector <PerVertexWeight> VertexWeightTable;
// -------------------------------------------------------------------------------
// Compute a per-vertex bone weight table
@@ -309,7 +326,7 @@ const char* MappingTypeToString(aiTextureMapping in);
// flags for MakeSubmesh()
-#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
+#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
// -------------------------------------------------------------------------------
// Split a mesh given a list of faces to be contained in the sub mesh
@@ -320,45 +337,45 @@ aiMesh* MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &su
// all steps which use it to speedup its computations.
class ComputeSpatialSortProcess : public BaseProcess
{
- bool IsActive( unsigned int pFlags) const
- {
- return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
- aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
- }
-
- void Execute( aiScene* pScene)
- {
- typedef std::pair<SpatialSort, float> _Type;
- DefaultLogger::get()->debug("Generate spatially-sorted vertex cache");
-
- std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
- std::vector<_Type>::iterator it = p->begin();
-
- for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
- aiMesh* mesh = pScene->mMeshes[i];
- _Type& blubb = *it;
- blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
- blubb.second = ComputePositionEpsilon(mesh);
- }
-
- shared->AddProperty(AI_SPP_SPATIAL_SORT,p);
- }
+ bool IsActive( unsigned int pFlags) const
+ {
+ return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
+ aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
+ }
+
+ void Execute( aiScene* pScene)
+ {
+ typedef std::pair<SpatialSort, float> _Type;
+ DefaultLogger::get()->debug("Generate spatially-sorted vertex cache");
+
+ std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes);
+ std::vector<_Type>::iterator it = p->begin();
+
+ for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
+ aiMesh* mesh = pScene->mMeshes[i];
+ _Type& blubb = *it;
+ blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D));
+ blubb.second = ComputePositionEpsilon(mesh);
+ }
+
+ shared->AddProperty(AI_SPP_SPATIAL_SORT,p);
+ }
};
// -------------------------------------------------------------------------------
// ... and the same again to cleanup the whole stuff
class DestroySpatialSortProcess : public BaseProcess
{
- bool IsActive( unsigned int pFlags) const
- {
- return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
- aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
- }
-
- void Execute( aiScene* /*pScene*/)
- {
- shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
- }
+ bool IsActive( unsigned int pFlags) const
+ {
+ return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
+ aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
+ }
+
+ void Execute( aiScene* /*pScene*/)
+ {
+ shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
+ }
};
diff --git a/src/3rdparty/assimp/code/Profiler.h b/src/3rdparty/assimp/code/Profiler.h
index d331f5384..9354339a2 100644
--- a/src/3rdparty/assimp/code/Profiler.h
+++ b/src/3rdparty/assimp/code/Profiler.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,15 +44,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_PROFILER_H
#define INCLUDED_PROFILER_H
-#include "boost/timer.hpp"
-
-#include "../include/assimp/DefaultLogger.hpp"
+#include <chrono>
+#include <assimp/DefaultLogger.hpp>
#include "TinyFormatter.h"
+#include <map>
+
namespace Assimp {
- namespace Profiling {
+ namespace Profiling {
- using namespace Formatter;
+ using namespace Formatter;
// ------------------------------------------------------------------------------------------------
@@ -64,34 +65,35 @@ class Profiler
public:
- Profiler() {}
+ Profiler() {}
public:
-
- /** Start a named timer */
- void BeginRegion(const std::string& region) {
- regions[region] = boost::timer();
- DefaultLogger::get()->debug((format("START `"),region,"`"));
- }
-
-
- /** End a specific named timer and write its end time to the log */
- void EndRegion(const std::string& region) {
- RegionMap::const_iterator it = regions.find(region);
- if (it == regions.end()) {
- return;
- }
-
- DefaultLogger::get()->debug((format("END `"),region,"`, dt= ",(*it).second.elapsed()," s"));
- }
+
+ /** Start a named timer */
+ void BeginRegion(const std::string& region) {
+ regions[region] = std::chrono::system_clock::now();
+ DefaultLogger::get()->debug((format("START `"),region,"`"));
+ }
+
+
+ /** End a specific named timer and write its end time to the log */
+ void EndRegion(const std::string& region) {
+ RegionMap::const_iterator it = regions.find(region);
+ if (it == regions.end()) {
+ return;
+ }
+
+ auto elapsedSeconds = std::chrono::system_clock::now() - regions[region];
+ DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s"));
+ }
private:
- typedef std::map<std::string,boost::timer> RegionMap;
- RegionMap regions;
+ typedef std::map<std::string,std::chrono::time_point<std::chrono::system_clock>> RegionMap;
+ RegionMap regions;
};
- }
+ }
}
#endif
diff --git a/src/3rdparty/assimp/code/Q3BSPFileData.h b/src/3rdparty/assimp/code/Q3BSPFileData.h
index a3516ae36..42e2bf148 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileData.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileData.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ASSIMP_Q3BSPFILEDATA_H_INC
#include <vector>
+#include <string.h> //memset
+#include <string>
namespace Assimp {
namespace Q3BSP {
@@ -48,165 +50,165 @@ namespace Q3BSP {
static const unsigned int CE_BSP_LIGHTMAPWIDTH = 128;
static const unsigned int CE_BSP_LIGHTMAPHEIGHT = 128;
-static const unsigned int CE_BSP_LIGHTMAPSIZE = 128*128*3; ///< = 128( width ) * 128 ( height ) * 3 ( channels / RGB ).
-static const int VERION_Q3LEVEL = 46; ///< Supported version.
+static const unsigned int CE_BSP_LIGHTMAPSIZE = 128*128*3; ///< = 128( width ) * 128 ( height ) * 3 ( channels / RGB ).
+static const int VERION_Q3LEVEL = 46; ///< Supported version.
-/// Geometric type enumeration
+/// Geometric type enumeration
enum Q3BSPGeoType {
- Polygon = 1,
- Patch,
- TriangleMesh,
- Billboard
+ Polygon = 1,
+ Patch,
+ TriangleMesh,
+ Billboard
};
-/// Integer vector.
+/// Integer vector.
struct ceVec3i {
int x, y, z;
- ceVec3i(): x( 0 ), y( 0 ), z( 0 ) { /* empty */ }
- ceVec3i( int iX, int iY=0, int iZ=0) : x( iX ), y( iY ), z( iZ ) { /* empty */ }
+ ceVec3i(): x( 0 ), y( 0 ), z( 0 ) { /* empty */ }
+ ceVec3i( int iX, int iY=0, int iZ=0) : x( iX ), y( iY ), z( iZ ) { /* empty */ }
};
-/// the file header
+/// the file header
struct sQ3BSPHeader {
- char strID[ 4 ]; ///< Should be "IBSP"
+ char strID[ 4 ]; ///< Should be "IBSP"
int iVersion; ///< 46 for standard levels
};
-/// Describes an entry.
-struct sQ3BSPLump
+/// Describes an entry.
+struct sQ3BSPLump
{
- int iOffset; ///< Offset from start pointer of file
- int iSize; ///< Size of part
+ int iOffset; ///< Offset from start pointer of file
+ int iSize; ///< Size of part
};
struct vec2f
{
- float x,y;
+ float x,y;
};
struct vec3f
{
- float x, y, z;
+ float x, y, z;
};
-/// Vertex of a Q3 level
-struct sQ3BSPVertex
+/// Vertex of a Q3 level
+struct sQ3BSPVertex
{
- vec3f vPosition; ///< Position of vertex
- vec2f vTexCoord; ///< (u,v) Texturecoordinate of detailtexture
- vec2f vLightmap; ///< (u,v) Texturecoordinate of lightmap
- vec3f vNormal; ///< vertex normale
- unsigned char bColor[ 4 ]; ///< Color in RGBA
+ vec3f vPosition; ///< Position of vertex
+ vec2f vTexCoord; ///< (u,v) Texturecoordinate of detailtexture
+ vec2f vLightmap; ///< (u,v) Texturecoordinate of lightmap
+ vec3f vNormal; ///< vertex normale
+ unsigned char bColor[ 4 ]; ///< Color in RGBA
};
-/// A face in bsp format info
-struct sQ3BSPFace
+/// A face in bsp format info
+struct sQ3BSPFace
{
- int iTextureID; ///< Index in texture array
- int iEffect; ///< Index in effect array (-1 = no effect)
- int iType; ///< 1=Polygon, 2=Patch, 3=Mesh, 4=Billboard
- int iVertexIndex; ///< Start index of polygon
- int iNumOfVerts; ///< Number of vertices
- int iFaceVertexIndex; ///< Index of first mesh vertex
- int iNumOfFaceVerts; ///< number of mesh vertices
- int iLightmapID; ///< Index to the light-map array
- int iLMapCorner[ 2 ]; ///< edge of the light-map in texture
- int iLMapSize[ 2 ]; ///< Size of the light-map stored on the texture
- vec3f vLMapPos; ///< 3D origin of the light-map
- vec3f vLMapVecs[ 2 ]; ///< 3D-s-t-vectors
- vec3f vNormal; ///< Polygon normals
- int patchWidth, patchHeight; ///< bezier patch
+ int iTextureID; ///< Index in texture array
+ int iEffect; ///< Index in effect array (-1 = no effect)
+ int iType; ///< 1=Polygon, 2=Patch, 3=Mesh, 4=Billboard
+ int iVertexIndex; ///< Start index of polygon
+ int iNumOfVerts; ///< Number of vertices
+ int iFaceVertexIndex; ///< Index of first mesh vertex
+ int iNumOfFaceVerts; ///< number of mesh vertices
+ int iLightmapID; ///< Index to the light-map array
+ int iLMapCorner[ 2 ]; ///< edge of the light-map in texture
+ int iLMapSize[ 2 ]; ///< Size of the light-map stored on the texture
+ vec3f vLMapPos; ///< 3D origin of the light-map
+ vec3f vLMapVecs[ 2 ]; ///< 3D-s-t-vectors
+ vec3f vNormal; ///< Polygon normals
+ int patchWidth, patchHeight; ///< bezier patch
};
/// A quake3 texture name.
struct sQ3BSPTexture {
- char strName[ 64 ]; ///< Name of the texture without extension
- int iFlags; ///< Not used
- int iContents; ///< Not used
+ char strName[ 64 ]; ///< Name of the texture without extension
+ int iFlags; ///< Not used
+ int iContents; ///< Not used
};
-/// A light-map of the level, size 128 x 128, RGB components.
+/// A light-map of the level, size 128 x 128, RGB components.
struct sQ3BSPLightmap {
- unsigned char bLMapData[ CE_BSP_LIGHTMAPSIZE ];
- sQ3BSPLightmap() {
- ::memset(bLMapData, 0, CE_BSP_LIGHTMAPSIZE );
- }
+ unsigned char bLMapData[ CE_BSP_LIGHTMAPSIZE ];
+ sQ3BSPLightmap() {
+ ::memset(bLMapData, 0, CE_BSP_LIGHTMAPSIZE );
+ }
};
struct SubPatch {
- std::vector<size_t> indices;
- int lightmapID;
+ std::vector<size_t> indices;
+ int lightmapID;
};
enum eLumps {
- kEntities = 0,
- kTextures,
- kPlanes,
- kNodes,
- kLeafs,
- kLeafFaces,
- kLeafBrushes,
- kModels,
- kBrushes,
- kBrushSides,
- kVertices,
- kMeshVerts,
- kShaders,
- kFaces,
- kLightmaps,
- kLightVolumes,
- kVisData,
- kMaxLumps
+ kEntities = 0,
+ kTextures,
+ kPlanes,
+ kNodes,
+ kLeafs,
+ kLeafFaces,
+ kLeafBrushes,
+ kModels,
+ kBrushes,
+ kBrushSides,
+ kVertices,
+ kMeshVerts,
+ kShaders,
+ kFaces,
+ kLightmaps,
+ kLightVolumes,
+ kVisData,
+ kMaxLumps
};
struct Q3BSPModel {
- std::vector<unsigned char> m_Data;
- std::vector<sQ3BSPLump*> m_Lumps;
- std::vector<sQ3BSPVertex*> m_Vertices;
- std::vector<sQ3BSPFace*> m_Faces;
- std::vector<int> m_Indices;
- std::vector<sQ3BSPTexture*> m_Textures;
- std::vector<sQ3BSPLightmap*> m_Lightmaps;
- std::vector<char> m_EntityData;
- std::string m_ModelName;
-
- Q3BSPModel() :
- m_Data(),
- m_Lumps(),
- m_Vertices(),
- m_Faces(),
- m_Indices(),
- m_Textures(),
- m_Lightmaps(),
- m_EntityData(),
- m_ModelName( "" )
- {
- // empty
- }
-
- ~Q3BSPModel() {
- for ( unsigned int i=0; i<m_Lumps.size(); i++ ) {
+ std::vector<unsigned char> m_Data;
+ std::vector<sQ3BSPLump*> m_Lumps;
+ std::vector<sQ3BSPVertex*> m_Vertices;
+ std::vector<sQ3BSPFace*> m_Faces;
+ std::vector<int> m_Indices;
+ std::vector<sQ3BSPTexture*> m_Textures;
+ std::vector<sQ3BSPLightmap*> m_Lightmaps;
+ std::vector<char> m_EntityData;
+ std::string m_ModelName;
+
+ Q3BSPModel() :
+ m_Data(),
+ m_Lumps(),
+ m_Vertices(),
+ m_Faces(),
+ m_Indices(),
+ m_Textures(),
+ m_Lightmaps(),
+ m_EntityData(),
+ m_ModelName( "" )
+ {
+ // empty
+ }
+
+ ~Q3BSPModel() {
+ for ( unsigned int i=0; i<m_Lumps.size(); i++ ) {
delete m_Lumps[ i ];
}
- for ( unsigned int i=0; i<m_Vertices.size(); i++ ) {
+ for ( unsigned int i=0; i<m_Vertices.size(); i++ ) {
delete m_Vertices[ i ];
}
- for ( unsigned int i=0; i<m_Faces.size(); i++ ) {
+ for ( unsigned int i=0; i<m_Faces.size(); i++ ) {
delete m_Faces[ i ];
}
- for ( unsigned int i=0; i<m_Textures.size(); i++ ) {
+ for ( unsigned int i=0; i<m_Textures.size(); i++ ) {
delete m_Textures[ i ];
}
- for ( unsigned int i=0; i<m_Lightmaps.size(); i++ ) {
+ for ( unsigned int i=0; i<m_Lightmaps.size(); i++ ) {
delete m_Lightmaps[ i ];
}
- m_Lumps.clear();
- m_Vertices.clear();
- m_Faces.clear();
- m_Textures.clear();
- m_Lightmaps.clear();
- }
+ m_Lumps.clear();
+ m_Vertices.clear();
+ m_Faces.clear();
+ m_Textures.clear();
+ m_Lightmaps.clear();
+ }
};
} // Namespace Q3BSP
diff --git a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
index 81a770261..47001d06f 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPFileImporter.cpp
@@ -5,8 +5,8 @@ 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
+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
@@ -23,24 +23,24 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
-//#include <windows.h>
+//#include <windows.h>
#include "DefaultIOSystem.h"
#include "Q3BSPFileImporter.h"
#include "Q3BSPZipArchive.h"
@@ -48,597 +48,602 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Q3BSPFileData.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
+# include <zlib.h>
#else
-# include "../contrib/zlib/zlib.h"
+# include "../contrib/zlib/zlib.h"
#endif
-#include "../include/assimp/types.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/types.h>
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
#include <vector>
-
+#include <sstream>
+#include "StringComparison.h"
static const aiImporterDesc desc = {
- "Quake III BSP Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "pk3"
+ "Quake III BSP Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "pk3"
};
namespace Assimp {
+/*
static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" );
}
-
+*/
+
using namespace Q3BSP;
// ------------------------------------------------------------------------------------------------
-// Local function to create a material key name.
+// Local function to create a material key name.
static void createKey( int id1, int id2, std::string &rKey )
{
- std::ostringstream str;
- str << id1 << "." << id2;
- rKey = str.str();
+ std::ostringstream str;
+ str << id1 << "." << id2;
+ rKey = str.str();
}
// ------------------------------------------------------------------------------------------------
-// Local function to extract the texture ids from a material key-name.
+// Local function to extract the texture ids from a material key-name.
static void extractIds( const std::string &rKey, int &rId1, int &rId2 )
{
- rId1 = -1;
- rId2 = -1;
- if ( rKey.empty() )
- return;
-
- std::string::size_type pos = rKey.find( "." );
- if ( std::string::npos == pos )
- return;
-
- std::string tmp1 = rKey.substr( 0, pos );
- std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 );
- rId1 = atoi( tmp1.c_str() );
- rId2 = atoi( tmp2.c_str() );
+ rId1 = -1;
+ rId2 = -1;
+ if ( rKey.empty() )
+ return;
+
+ std::string::size_type pos = rKey.find( "." );
+ if ( std::string::npos == pos )
+ return;
+
+ std::string tmp1 = rKey.substr( 0, pos );
+ std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 );
+ rId1 = atoi( tmp1.c_str() );
+ rId2 = atoi( tmp2.c_str() );
}
// ------------------------------------------------------------------------------------------------
-// Local helper function to normalize filenames.
+// Local helper function to normalize filenames.
static void normalizePathName( const std::string &rPath, std::string &rNormalizedPath )
{
- rNormalizedPath = "";
- if ( rPath.empty() )
- return;
+ rNormalizedPath = "";
+ if ( rPath.empty() )
+ return;
#ifdef _WIN32
- std::string sep = "\\";
+ std::string sep = "\\";
#else
- std::string sep = "/";
+ std::string sep = "/";
#endif
- static const unsigned int numDelimiters = 2;
- const char delimiters[ numDelimiters ] = { '/', '\\' };
- rNormalizedPath = rPath;
- for ( unsigned int i=0; i<numDelimiters; i++ )
- {
- for ( size_t j=0; j<rNormalizedPath.size(); j++ )
- {
- if ( rNormalizedPath[j] == delimiters[ i ] )
- {
- rNormalizedPath[ j ] = sep[ 0 ];
- }
- }
- }
+ static const unsigned int numDelimiters = 2;
+ const char delimiters[ numDelimiters ] = { '/', '\\' };
+ rNormalizedPath = rPath;
+ for (const char delimiter : delimiters)
+ {
+ for ( size_t j=0; j<rNormalizedPath.size(); j++ )
+ {
+ if ( rNormalizedPath[j] == delimiter )
+ {
+ rNormalizedPath[ j ] = sep[ 0 ];
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Constructor.
+// Constructor.
Q3BSPFileImporter::Q3BSPFileImporter() :
- m_pCurrentMesh( NULL ),
- m_pCurrentFace( NULL ),
- m_MaterialLookupMap(),
- mTextures()
+ m_pCurrentMesh( NULL ),
+ m_pCurrentFace( NULL ),
+ m_MaterialLookupMap(),
+ mTextures()
{
- // empty
+ // empty
}
// ------------------------------------------------------------------------------------------------
-// Destructor.
+// Destructor.
Q3BSPFileImporter::~Q3BSPFileImporter() {
- m_pCurrentMesh = NULL;
- m_pCurrentFace = NULL;
-
- // Clear face-to-material map
+ m_pCurrentMesh = NULL;
+ m_pCurrentFace = NULL;
+
+ // Clear face-to-material map
for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) {
- const std::string &matName = it->first;
- if ( !matName.empty() ) {
+ const std::string &matName = it->first;
+ if ( !matName.empty() ) {
delete it->second;
- }
- }
- m_MaterialLookupMap.clear();
+ }
+ }
+ m_MaterialLookupMap.clear();
}
// ------------------------------------------------------------------------------------------------
-// Returns true, if the loader can read this.
+// Returns true, if the loader can read this.
bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
{
- if(!checkSig) {
- return SimpleExtensionCheck( rFile, "pk3" );
- }
- // TODO perhaps add keyword based detection
- return false;
+ if(!checkSig) {
+ return SimpleExtensionCheck( rFile, "pk3" );
+ }
+ // TODO perhaps add keyword based detection
+ return false;
}
// ------------------------------------------------------------------------------------------------
-// Adds extensions.
+// Adds extensions.
const aiImporterDesc* Q3BSPFileImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Import method.
+// Import method.
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* pIOHandler)
{
- Q3BSPZipArchive Archive( pIOHandler, rFile );
- if ( !Archive.isOpen() )
- {
- throw DeadlyImportError( "Failed to open file " + rFile + "." );
- }
-
- std::string archiveName( "" ), mapName( "" );
- separateMapName( rFile, archiveName, mapName );
-
- if ( mapName.empty() )
- {
- if ( !findFirstMapInArchive( Archive, mapName ) )
- {
- return;
- }
- }
-
- Q3BSPFileParser fileParser( mapName, &Archive );
- Q3BSPModel *pBSPModel = fileParser.getModel();
- if ( NULL != pBSPModel )
- {
- CreateDataFromImport( pBSPModel, pScene, &Archive );
- }
+ Q3BSPZipArchive Archive( pIOHandler, rFile );
+ if ( !Archive.isOpen() )
+ {
+ throw DeadlyImportError( "Failed to open file " + rFile + "." );
+ }
+
+ std::string archiveName( "" ), mapName( "" );
+ separateMapName( rFile, archiveName, mapName );
+
+ if ( mapName.empty() )
+ {
+ if ( !findFirstMapInArchive( Archive, mapName ) )
+ {
+ return;
+ }
+ }
+
+ Q3BSPFileParser fileParser( mapName, &Archive );
+ Q3BSPModel *pBSPModel = fileParser.getModel();
+ if ( NULL != pBSPModel )
+ {
+ CreateDataFromImport( pBSPModel, pScene, &Archive );
+ }
}
// ------------------------------------------------------------------------------------------------
-// Separates the map name from the import name.
-void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName,
- std::string &rMapName )
+// Separates the map name from the import name.
+void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName,
+ std::string &rMapName )
{
- rArchiveName = "";
- rMapName = "";
- if ( rImportName.empty() )
- return;
-
- std::string::size_type pos = rImportName.rfind( "," );
- if ( std::string::npos == pos )
- {
- rArchiveName = rImportName;
- return;
- }
-
- rArchiveName = rImportName.substr( 0, pos );
- rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 );
+ rArchiveName = "";
+ rMapName = "";
+ if ( rImportName.empty() )
+ return;
+
+ std::string::size_type pos = rImportName.rfind( "," );
+ if ( std::string::npos == pos )
+ {
+ rArchiveName = rImportName;
+ return;
+ }
+
+ rArchiveName = rImportName.substr( 0, pos );
+ rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 );
}
// ------------------------------------------------------------------------------------------------
-// Returns the first map in the map archive.
+// Returns the first map in the map archive.
bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::string &rMapName )
{
- rMapName = "";
- std::vector<std::string> fileList;
- rArchive.getFileList( fileList );
- if ( fileList.empty() )
- return false;
-
- for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end();
- ++it )
- {
- std::string::size_type pos = (*it).find( "maps/" );
- if ( std::string::npos != pos )
- {
- std::string::size_type extPos = (*it).find( ".bsp" );
- if ( std::string::npos != extPos )
- {
- rMapName = *it;
- return true;
- }
- }
- }
-
- return false;
+ rMapName = "";
+ std::vector<std::string> fileList;
+ rArchive.getFileList( fileList );
+ if ( fileList.empty() )
+ return false;
+
+ for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end();
+ ++it )
+ {
+ std::string::size_type pos = (*it).find( "maps/" );
+ if ( std::string::npos != pos )
+ {
+ std::string::size_type extPos = (*it).find( ".bsp" );
+ if ( std::string::npos != extPos )
+ {
+ rMapName = *it;
+ return true;
+ }
+ }
+ }
+
+ return false;
}
// ------------------------------------------------------------------------------------------------
-// Creates the assimp specific data.
-void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
- Q3BSPZipArchive *pArchive )
+// Creates the assimp specific data.
+void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
+ Q3BSPZipArchive *pArchive )
{
- if ( NULL == pModel || NULL == pScene )
- return;
-
- pScene->mRootNode = new aiNode;
- if ( !pModel->m_ModelName.empty() )
- {
- pScene->mRootNode->mName.Set( pModel->m_ModelName );
- }
-
- // Create the face to material relation map
- createMaterialMap( pModel );
-
- // Create all nodes
- CreateNodes( pModel, pScene, pScene->mRootNode );
-
- // Create the assigned materials
- createMaterials( pModel, pScene, pArchive );
+ if ( NULL == pModel || NULL == pScene )
+ return;
+
+ pScene->mRootNode = new aiNode;
+ if ( !pModel->m_ModelName.empty() )
+ {
+ pScene->mRootNode->mName.Set( pModel->m_ModelName );
+ }
+
+ // Create the face to material relation map
+ createMaterialMap( pModel );
+
+ // Create all nodes
+ CreateNodes( pModel, pScene, pScene->mRootNode );
+
+ // Create the assigned materials
+ createMaterials( pModel, pScene, pArchive );
}
// ------------------------------------------------------------------------------------------------
-// Creates all assimp nodes.
-void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
- aiNode *pParent )
+// Creates all assimp nodes.
+void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
+ aiNode *pParent )
{
- ai_assert( NULL != pModel );
- if ( NULL == pModel )
- {
- return;
- }
-
- unsigned int matIdx = 0;
- std::vector<aiMesh*> MeshArray;
- std::vector<aiNode*> NodeArray;
- for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it )
- {
- std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
- size_t numVerts = countData( *pArray );
- if ( 0 != numVerts )
- {
- aiMesh* pMesh = new aiMesh;
- aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, pMesh );
- if ( NULL != pNode )
- {
- NodeArray.push_back( pNode );
- MeshArray.push_back( pMesh );
- }
- else
- {
- delete pMesh;
- }
- }
- matIdx++;
- }
-
- pScene->mNumMeshes = MeshArray.size();
- if ( pScene->mNumMeshes > 0 )
- {
- pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
- for ( size_t i = 0; i < MeshArray.size(); i++ )
- {
- aiMesh *pMesh = MeshArray[ i ];
- if ( NULL != pMesh )
- {
- pScene->mMeshes[ i ] = pMesh;
- }
- }
- }
-
- pParent->mNumChildren = MeshArray.size();
- pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
- for ( size_t i=0; i<NodeArray.size(); i++ )
- {
- aiNode *pNode = NodeArray[ i ];
- pNode->mParent = pParent;
- pParent->mChildren[ i ] = pNode;
- pParent->mChildren[ i ]->mMeshes[ 0 ] = i;
- }
+ ai_assert( NULL != pModel );
+ if ( NULL == pModel )
+ {
+ return;
+ }
+
+ unsigned int matIdx = 0;
+ std::vector<aiMesh*> MeshArray;
+ std::vector<aiNode*> NodeArray;
+ for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it )
+ {
+ std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second;
+ size_t numVerts = countData( *pArray );
+ if ( 0 != numVerts )
+ {
+ aiMesh* pMesh = new aiMesh;
+ aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, pMesh );
+ if ( NULL != pNode )
+ {
+ NodeArray.push_back( pNode );
+ MeshArray.push_back( pMesh );
+ }
+ else
+ {
+ delete pMesh;
+ }
+ }
+ matIdx++;
+ }
+
+ pScene->mNumMeshes = static_cast<unsigned int>( MeshArray.size() );
+ if ( pScene->mNumMeshes > 0 )
+ {
+ pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+ for ( size_t i = 0; i < MeshArray.size(); i++ )
+ {
+ aiMesh *pMesh = MeshArray[ i ];
+ if ( NULL != pMesh )
+ {
+ pScene->mMeshes[ i ] = pMesh;
+ }
+ }
+ }
+
+ pParent->mNumChildren = MeshArray.size();
+ pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ];
+ for ( size_t i=0; i<NodeArray.size(); i++ )
+ {
+ aiNode *pNode = NodeArray[ i ];
+ pNode->mParent = pParent;
+ pParent->mChildren[ i ] = pNode;
+ pParent->mChildren[ i ]->mMeshes[ 0 ] = i;
+ }
}
// ------------------------------------------------------------------------------------------------
-// Creates the topology.
+// Creates the topology.
aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel,
- unsigned int materialIdx,
- std::vector<sQ3BSPFace*> &rArray,
- aiMesh* pMesh )
+ unsigned int materialIdx,
+ std::vector<sQ3BSPFace*> &rArray,
+ aiMesh* pMesh )
{
- size_t numVerts = countData( rArray );
- if ( 0 == numVerts )
- {
- return NULL;
- }
-
- size_t numFaces = countFaces( rArray );
- if ( 0 == numFaces )
- {
- return NULL;
- }
-
- size_t numTriangles = countTriangles( rArray );
- pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- pMesh->mFaces = new aiFace[ numTriangles ];
- pMesh->mNumFaces = numTriangles;
-
- pMesh->mNumVertices = numVerts;
- pMesh->mVertices = new aiVector3D[ numVerts ];
- pMesh->mNormals = new aiVector3D[ numVerts ];
- pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
- pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ];
- pMesh->mMaterialIndex = materialIdx;
-
- unsigned int faceIdx = 0;
- unsigned int vertIdx = 0;
- pMesh->mNumUVComponents[ 0 ] = 2;
- pMesh->mNumUVComponents[ 1 ] = 2;
- for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it )
- {
- Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
- ai_assert( NULL != pQ3BSPFace );
- if ( NULL == pQ3BSPFace )
- {
- continue;
- }
-
- if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
- {
- if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
- {
- createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx );
- }
- }
- }
-
- aiNode *pNode = new aiNode;
- pNode->mNumMeshes = 1;
- pNode->mMeshes = new unsigned int[ 1 ];
-
- return pNode;
+ size_t numVerts = countData( rArray );
+ if ( 0 == numVerts )
+ {
+ return NULL;
+ }
+
+ size_t numFaces = countFaces( rArray );
+ if ( 0 == numFaces )
+ {
+ return NULL;
+ }
+
+ size_t numTriangles = countTriangles( rArray );
+ pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ pMesh->mFaces = new aiFace[ numTriangles ];
+ pMesh->mNumFaces = numTriangles;
+
+ pMesh->mNumVertices = numVerts;
+ pMesh->mVertices = new aiVector3D[ numVerts ];
+ pMesh->mNormals = new aiVector3D[ numVerts ];
+ pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ];
+ pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ];
+ pMesh->mMaterialIndex = materialIdx;
+
+ unsigned int faceIdx = 0;
+ unsigned int vertIdx = 0;
+ pMesh->mNumUVComponents[ 0 ] = 2;
+ pMesh->mNumUVComponents[ 1 ] = 2;
+ for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it )
+ {
+ Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+ ai_assert( NULL != pQ3BSPFace );
+ if ( NULL == pQ3BSPFace )
+ {
+ continue;
+ }
+
+ if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
+ {
+ if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
+ {
+ createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx );
+ }
+ }
+ }
+
+ aiNode *pNode = new aiNode;
+ pNode->mNumMeshes = 1;
+ pNode->mMeshes = new unsigned int[ 1 ];
+
+ return pNode;
}
// ------------------------------------------------------------------------------------------------
-// Creates the triangle topology from a face array.
+// Creates the triangle topology from a face array.
void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel,
- Q3BSP::sQ3BSPFace *pQ3BSPFace,
- aiMesh* pMesh,
- unsigned int &rFaceIdx,
- unsigned int &rVertIdx )
+ Q3BSP::sQ3BSPFace *pQ3BSPFace,
+ aiMesh* pMesh,
+ unsigned int &rFaceIdx,
+ unsigned int &rVertIdx )
{
- ai_assert( rFaceIdx < pMesh->mNumFaces );
-
- m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
- ai_assert( NULL != m_pCurrentFace );
- if ( NULL == m_pCurrentFace )
- {
- return;
- }
-
- m_pCurrentFace->mNumIndices = 3;
- m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ];
-
- size_t idx = 0;
- for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ )
- {
- const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ];
- ai_assert( index < pModel->m_Vertices.size() );
- if ( index >= pModel->m_Vertices.size() )
- {
- continue;
- }
-
- sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ];
- ai_assert( NULL != pVertex );
- if ( NULL == pVertex )
- {
- continue;
- }
-
- pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z );
- pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z );
-
- pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f );
- pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f );
-
- m_pCurrentFace->mIndices[ idx ] = rVertIdx;
- rVertIdx++;
-
- idx++;
- if ( idx > 2 )
- {
- idx = 0;
- m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
- if ( NULL != m_pCurrentFace )
- {
- m_pCurrentFace->mNumIndices = 3;
- m_pCurrentFace->mIndices = new unsigned int[ 3 ];
- }
- }
- }
- rFaceIdx--;
+ ai_assert( rFaceIdx < pMesh->mNumFaces );
+
+ m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
+ ai_assert( NULL != m_pCurrentFace );
+ if ( NULL == m_pCurrentFace )
+ {
+ return;
+ }
+
+ m_pCurrentFace->mNumIndices = 3;
+ m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ];
+
+ size_t idx = 0;
+ for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ )
+ {
+ const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ];
+ ai_assert( index < pModel->m_Vertices.size() );
+ if ( index >= pModel->m_Vertices.size() )
+ {
+ continue;
+ }
+
+ sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ];
+ ai_assert( NULL != pVertex );
+ if ( NULL == pVertex )
+ {
+ continue;
+ }
+
+ pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z );
+ pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z );
+
+ pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f );
+ pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f );
+
+ m_pCurrentFace->mIndices[ idx ] = rVertIdx;
+ rVertIdx++;
+
+ idx++;
+ if ( idx > 2 )
+ {
+ idx = 0;
+ m_pCurrentFace = getNextFace( pMesh, rFaceIdx );
+ if ( NULL != m_pCurrentFace )
+ {
+ m_pCurrentFace->mNumIndices = 3;
+ m_pCurrentFace->mIndices = new unsigned int[ 3 ];
+ }
+ }
+ }
+ rFaceIdx--;
}
// ------------------------------------------------------------------------------------------------
-// Creates all referenced materials.
+// Creates all referenced materials.
void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
- Q3BSPZipArchive *pArchive )
+ Q3BSPZipArchive *pArchive )
{
- if ( m_MaterialLookupMap.empty() )
- {
- return;
- }
-
- pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ];
- aiString aiMatName;
- int textureId( -1 ), lightmapId( -1 );
- for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
- ++it )
- {
- const std::string matName = (*it).first;
- if ( matName.empty() )
- {
- continue;
- }
-
- aiMatName.Set( matName );
- aiMaterial *pMatHelper = new aiMaterial;
- pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME );
-
- extractIds( matName, textureId, lightmapId );
-
- // Adding the texture
- if ( -1 != textureId )
- {
- sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
- if ( NULL != pTexture )
- {
- std::string tmp( "*" ), texName( "" );
- tmp += pTexture->strName;
- tmp += ".jpg";
- normalizePathName( tmp, texName );
-
- if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) )
- {
- }
- }
-
- }
- if ( -1 != lightmapId )
- {
- importLightmap( pModel, pScene, pMatHelper, lightmapId );
- }
- pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper;
- pScene->mNumMaterials++;
- }
- pScene->mNumTextures = mTextures.size();
- pScene->mTextures = new aiTexture*[ pScene->mNumTextures ];
- std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures );
+ if ( m_MaterialLookupMap.empty() )
+ {
+ return;
+ }
+
+ pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ];
+ aiString aiMatName;
+ int textureId( -1 ), lightmapId( -1 );
+ for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end();
+ ++it )
+ {
+ const std::string matName = (*it).first;
+ if ( matName.empty() )
+ {
+ continue;
+ }
+
+ aiMatName.Set( matName );
+ aiMaterial *pMatHelper = new aiMaterial;
+ pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME );
+
+ extractIds( matName, textureId, lightmapId );
+
+ // Adding the texture
+ if ( -1 != textureId )
+ {
+ sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
+ if ( NULL != pTexture )
+ {
+ std::string tmp( "*" ), texName( "" );
+ tmp += pTexture->strName;
+ tmp += ".jpg";
+ normalizePathName( tmp, texName );
+
+ if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) )
+ {
+ }
+ }
+
+ }
+ if ( -1 != lightmapId )
+ {
+ importLightmap( pModel, pScene, pMatHelper, lightmapId );
+ }
+ pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper;
+ pScene->mNumMaterials++;
+ }
+ pScene->mNumTextures = mTextures.size();
+ pScene->mTextures = new aiTexture*[ pScene->mNumTextures ];
+ std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures );
}
// ------------------------------------------------------------------------------------------------
-// Counts the number of referenced vertices.
+// Counts the number of referenced vertices.
size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &rArray ) const
{
- size_t numVerts = 0;
- for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
- ++it )
- {
- sQ3BSPFace *pQ3BSPFace = *it;
- if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
- {
- Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
- ai_assert( NULL != pQ3BSPFace );
- numVerts += pQ3BSPFace->iNumOfFaceVerts;
- }
- }
-
- return numVerts;
+ size_t numVerts = 0;
+ for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
+ ++it )
+ {
+ sQ3BSPFace *pQ3BSPFace = *it;
+ if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh )
+ {
+ Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+ ai_assert( NULL != pQ3BSPFace );
+ numVerts += pQ3BSPFace->iNumOfFaceVerts;
+ }
+ }
+
+ return numVerts;
}
// ------------------------------------------------------------------------------------------------
-// Counts the faces with vertices.
+// Counts the faces with vertices.
size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
{
- size_t numFaces = 0;
- for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
- ++it )
- {
- Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
- if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
- {
- numFaces++;
- }
- }
-
- return numFaces;
+ size_t numFaces = 0;
+ for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
+ ++it )
+ {
+ Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+ if ( pQ3BSPFace->iNumOfFaceVerts > 0 )
+ {
+ numFaces++;
+ }
+ }
+
+ return numFaces;
}
// ------------------------------------------------------------------------------------------------
-// Counts the number of triangles in a Q3-face-array.
+// Counts the number of triangles in a Q3-face-array.
size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const
{
- size_t numTriangles = 0;
- for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
- ++it )
- {
- const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
- if ( NULL != pQ3BSPFace )
- {
- numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3;
- }
- }
-
- return numTriangles;
+ size_t numTriangles = 0;
+ for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end();
+ ++it )
+ {
+ const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it;
+ if ( NULL != pQ3BSPFace )
+ {
+ numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3;
+ }
+ }
+
+ return numTriangles;
}
// ------------------------------------------------------------------------------------------------
-// Creates the faces-to-material map.
+// Creates the faces-to-material map.
void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel )
{
- std::string key( "" );
- std::vector<sQ3BSPFace*> *pCurFaceArray = NULL;
- for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ )
- {
- Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
- const int texId = pQ3BSPFace->iTextureID;
- const int lightMapId = pQ3BSPFace->iLightmapID;
- createKey( texId, lightMapId, key );
- FaceMapIt it = m_MaterialLookupMap.find( key );
- if ( m_MaterialLookupMap.end() == it )
- {
- pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>;
- m_MaterialLookupMap[ key ] = pCurFaceArray;
- }
- else
- {
- pCurFaceArray = (*it).second;
- }
- ai_assert( NULL != pCurFaceArray );
- if ( NULL != pCurFaceArray )
- {
- pCurFaceArray->push_back( pQ3BSPFace );
- }
- }
+ std::string key( "" );
+ std::vector<sQ3BSPFace*> *pCurFaceArray = NULL;
+ for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ )
+ {
+ Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ];
+ const int texId = pQ3BSPFace->iTextureID;
+ const int lightMapId = pQ3BSPFace->iLightmapID;
+ createKey( texId, lightMapId, key );
+ FaceMapIt it = m_MaterialLookupMap.find( key );
+ if ( m_MaterialLookupMap.end() == it )
+ {
+ pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>;
+ m_MaterialLookupMap[ key ] = pCurFaceArray;
+ }
+ else
+ {
+ pCurFaceArray = (*it).second;
+ }
+ ai_assert( NULL != pCurFaceArray );
+ if ( NULL != pCurFaceArray )
+ {
+ pCurFaceArray->push_back( pQ3BSPFace );
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Returns the next face.
+// Returns the next face.
aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
{
- aiFace *pFace( NULL );
- if ( rFaceIdx < pMesh->mNumFaces ) {
- pFace = &pMesh->mFaces[ rFaceIdx ];
- rFaceIdx++;
- }
+ aiFace *pFace( NULL );
+ if ( rFaceIdx < pMesh->mNumFaces ) {
+ pFace = &pMesh->mFaces[ rFaceIdx ];
+ rFaceIdx++;
+ }
- return pFace;
+ return pFace;
}
// ------------------------------------------------------------------------------------------------
-// Imports a texture file.
+// Imports a texture file.
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
- Q3BSP::Q3BSPZipArchive *pArchive, aiScene*,
- aiMaterial *pMatHelper, int textureId ) {
- if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) {
- return false;
- }
-
- if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) ) {
- return false;
- }
-
- bool res = true;
- sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
- if ( !pTexture ) {
+ Q3BSP::Q3BSPZipArchive *pArchive, aiScene*,
+ aiMaterial *pMatHelper, int textureId ) {
+ if ( NULL == pArchive || NULL == pMatHelper ) {
+ return false;
+ }
+
+ if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) ) {
+ return false;
+ }
+
+ bool res = true;
+ sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
+ if ( !pTexture ) {
return false;
}
@@ -646,124 +651,124 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" );
- std::string textureName, ext;
- if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) {
- IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
- if ( !pTextureStream ) {
- size_t texSize = pTextureStream->FileSize();
- aiTexture *pTexture = new aiTexture;
- pTexture->mHeight = 0;
- pTexture->mWidth = texSize;
- unsigned char *pData = new unsigned char[ pTexture->mWidth ];
- size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth );
- (void)readSize;
- ai_assert( readSize == pTexture->mWidth );
- pTexture->pcData = reinterpret_cast<aiTexel*>( pData );
- pTexture->achFormatHint[ 0 ] = ext[ 1 ];
- pTexture->achFormatHint[ 1 ] = ext[ 2 ];
- pTexture->achFormatHint[ 2 ] = ext[ 3 ];
- pTexture->achFormatHint[ 3 ] = '\0';
- res = true;
-
- aiString name;
- name.data[ 0 ] = '*';
- name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
-
- pArchive->Close( pTextureStream );
-
- pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
- mTextures.push_back( pTexture );
- } else {
- // If it doesn't exist in the archive, it is probably just a reference to an external file.
- // We'll leave it up to the user to figure out which extension the file has.
- aiString name;
- strncpy( name.data, pTexture->strName, sizeof name.data );
- name.length = strlen( name.data );
- pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
- }
- }
-
- return res;
+ std::string textureName, ext;
+ if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) {
+ IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
+ if ( pTextureStream ) {
+ size_t texSize = pTextureStream->FileSize();
+ aiTexture *pTexture = new aiTexture;
+ pTexture->mHeight = 0;
+ pTexture->mWidth = texSize;
+ unsigned char *pData = new unsigned char[ pTexture->mWidth ];
+ size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth );
+ (void)readSize;
+ ai_assert( readSize == pTexture->mWidth );
+ pTexture->pcData = reinterpret_cast<aiTexel*>( pData );
+ pTexture->achFormatHint[ 0 ] = ext[ 1 ];
+ pTexture->achFormatHint[ 1 ] = ext[ 2 ];
+ pTexture->achFormatHint[ 2 ] = ext[ 3 ];
+ pTexture->achFormatHint[ 3 ] = '\0';
+ res = true;
+
+ aiString name;
+ name.data[ 0 ] = '*';
+ name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
+
+ pArchive->Close( pTextureStream );
+
+ pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
+ mTextures.push_back( pTexture );
+ } else {
+ // If it doesn't exist in the archive, it is probably just a reference to an external file.
+ // We'll leave it up to the user to figure out which extension the file has.
+ aiString name;
+ strncpy( name.data, pTexture->strName, sizeof name.data );
+ name.length = strlen( name.data );
+ pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
+ }
+ }
+
+ return res;
}
// ------------------------------------------------------------------------------------------------
-// Imports a light map file.
-bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
- aiMaterial *pMatHelper, int lightmapId )
+// Imports a light map file.
+bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene,
+ aiMaterial *pMatHelper, int lightmapId )
{
- if ( NULL == pModel || NULL == pScene || NULL == pMatHelper )
- {
- return false;
- }
-
- if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) )
- {
- return false;
- }
-
- sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ];
- if ( NULL == pLightMap )
- {
- return false;
- }
-
- aiTexture *pTexture = new aiTexture;
-
- pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH;
- pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT;
- pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT];
-
- ::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth );
- size_t p = 0;
- for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i )
- {
- pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ];
- pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ];
- pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ];
- pTexture->pcData[ i ].a = 0xFF;
- }
-
- aiString name;
- name.data[ 0 ] = '*';
- name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
-
- pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) );
- mTextures.push_back( pTexture );
-
- return true;
+ if ( NULL == pModel || NULL == pScene || NULL == pMatHelper )
+ {
+ return false;
+ }
+
+ if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) )
+ {
+ return false;
+ }
+
+ sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ];
+ if ( NULL == pLightMap )
+ {
+ return false;
+ }
+
+ aiTexture *pTexture = new aiTexture;
+
+ pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH;
+ pTexture->mHeight = CE_BSP_LIGHTMAPHEIGHT;
+ pTexture->pcData = new aiTexel[CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT];
+
+ ::memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth );
+ size_t p = 0;
+ for ( size_t i = 0; i < CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; ++i )
+ {
+ pTexture->pcData[ i ].r = pLightMap->bLMapData[ p++ ];
+ pTexture->pcData[ i ].g = pLightMap->bLMapData[ p++ ];
+ pTexture->pcData[ i ].b = pLightMap->bLMapData[ p++ ];
+ pTexture->pcData[ i ].a = 0xFF;
+ }
+
+ aiString name;
+ name.data[ 0 ] = '*';
+ name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() );
+
+ pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) );
+ mTextures.push_back( pTexture );
+
+ return true;
}
// ------------------------------------------------------------------------------------------------
-// Will search for a supported extension.
-bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename,
- const std::vector<std::string> &rExtList, std::string &rFile,
- std::string &rExt )
+// Will search for a supported extension.
+bool Q3BSPFileImporter::expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename,
+ const std::vector<std::string> &rExtList, std::string &rFile,
+ std::string &rExt )
{
- ai_assert( NULL != pArchive );
- ai_assert( !rFilename.empty() );
-
- if ( rExtList.empty() )
- {
- rFile = rFilename;
- rExt = "";
- return true;
- }
-
- bool found = false;
- for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it )
- {
- const std::string textureName = rFilename + *it;
- if ( pArchive->Exists( textureName.c_str() ) )
- {
- rExt = *it;
- rFile = textureName;
- found = true;
- break;
- }
- }
-
- return found;
+ ai_assert( NULL != pArchive );
+ ai_assert( !rFilename.empty() );
+
+ if ( rExtList.empty() )
+ {
+ rFile = rFilename;
+ rExt = "";
+ return true;
+ }
+
+ bool found = false;
+ for ( std::vector<std::string>::const_iterator it = rExtList.begin(); it != rExtList.end(); ++it )
+ {
+ const std::string textureName = rFilename + *it;
+ if ( pArchive->Exists( textureName.c_str() ) )
+ {
+ rExt = *it;
+ rFile = textureName;
+ found = true;
+ break;
+ }
+ }
+
+ return found;
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Q3BSPFileImporter.h b/src/3rdparty/assimp/code/Q3BSPFileImporter.h
index 7a60defad..c995f82ab 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileImporter.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileImporter.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,6 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
struct aiMesh;
+struct aiNode;
+struct aiFace;
+struct aiMaterial;
+struct aiTexture;
namespace Assimp
{
@@ -55,57 +59,57 @@ struct sQ3BSPFace;
}
// ------------------------------------------------------------------------------------------------
-/** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level.
+/** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level.
*/
// ------------------------------------------------------------------------------------------------
class Q3BSPFileImporter : public BaseImporter
{
public:
- /// @brief Default constructor.
- Q3BSPFileImporter();
+ /// @brief Default constructor.
+ Q3BSPFileImporter();
- /// @brief Destructor.
- ~Q3BSPFileImporter();
+ /// @brief Destructor.
+ ~Q3BSPFileImporter();
public:
- /// @brief Returns whether the class can handle the format of the given file.
- /// @remark See BaseImporter::CanRead() for details.
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
+ /// @brief Returns whether the class can handle the format of the given file.
+ /// @remark See BaseImporter::CanRead() for details.
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
private:
- typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*> FaceMap;
- typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator FaceMapIt;
- typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator FaceMapConstIt;
-
- const aiImporterDesc* GetInfo () const;
- void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
- void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
- bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, std::string &rMapName );
- void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
- void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
- aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
- std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh );
- void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx,
- unsigned int &rVertIdx );
- void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
- size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
- size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
- size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
- void createMaterialMap( const Q3BSP::Q3BSPModel *pModel);
- aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx );
- bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene,
- aiMaterial *pMatHelper, int textureId );
- bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId );
- bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
- bool expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList,
- std::string &rFile, std::string &rExt );
+ typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*> FaceMap;
+ typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator FaceMapIt;
+ typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator FaceMapConstIt;
+
+ const aiImporterDesc* GetInfo () const;
+ void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+ void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );
+ bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, std::string &rMapName );
+ void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
+ void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent );
+ aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx,
+ std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh );
+ void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx,
+ unsigned int &rVertIdx );
+ void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive );
+ size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
+ size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
+ size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const;
+ void createMaterialMap( const Q3BSP::Q3BSPModel *pModel);
+ aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx );
+ bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene,
+ aiMaterial *pMatHelper, int textureId );
+ bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiMaterial *pMatHelper, int lightmapId );
+ bool importEntities( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene );
+ bool expandFile( Q3BSP::Q3BSPZipArchive *pArchive, const std::string &rFilename, const std::vector<std::string> &rExtList,
+ std::string &rFile, std::string &rExt );
private:
- aiMesh *m_pCurrentMesh;
- aiFace *m_pCurrentFace;
- FaceMap m_MaterialLookupMap;
- std::vector<aiTexture*> mTextures;
+ aiMesh *m_pCurrentMesh;
+ aiFace *m_pCurrentFace;
+ FaceMap m_MaterialLookupMap;
+ std::vector<aiTexture*> mTextures;
};
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Q3BSPFileParser.cpp b/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
index 9713798f7..db2247b8a 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPFileParser.cpp
@@ -5,8 +5,8 @@ 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
+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
@@ -23,21 +23,21 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
@@ -46,231 +46,231 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Q3BSPFileData.h"
#include "Q3BSPZipArchive.h"
#include <vector>
+#include <assimp/ai_assert.h>
-namespace Assimp
-{
+namespace Assimp {
using namespace Q3BSP;
// ------------------------------------------------------------------------------------------------
Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *pZipArchive ) :
- m_sOffset( 0 ),
- m_Data(),
- m_pModel( NULL ),
- m_pZipArchive( pZipArchive )
+ m_sOffset( 0 ),
+ m_Data(),
+ m_pModel( NULL ),
+ m_pZipArchive( pZipArchive )
{
- ai_assert( NULL != m_pZipArchive );
- ai_assert( !rMapName.empty() );
-
- if ( !readData( rMapName ) )
- return;
-
- m_pModel = new Q3BSPModel;
- m_pModel->m_ModelName = rMapName;
- if ( !parseFile() )
- {
- delete m_pModel;
- m_pModel = NULL;
- }
+ ai_assert( NULL != m_pZipArchive );
+ ai_assert( !rMapName.empty() );
+
+ if ( !readData( rMapName ) )
+ return;
+
+ m_pModel = new Q3BSPModel;
+ m_pModel->m_ModelName = rMapName;
+ if ( !parseFile() )
+ {
+ delete m_pModel;
+ m_pModel = NULL;
+ }
}
// ------------------------------------------------------------------------------------------------
Q3BSPFileParser::~Q3BSPFileParser()
{
- delete m_pModel;
- m_pModel = NULL;
+ delete m_pModel;
+ m_pModel = NULL;
}
// ------------------------------------------------------------------------------------------------
Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const
{
- return m_pModel;
+ return m_pModel;
}
// ------------------------------------------------------------------------------------------------
bool Q3BSPFileParser::readData( const std::string &rMapName )
{
- if ( !m_pZipArchive->Exists( rMapName.c_str() ) )
- return false;
-
- IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() );
- if ( NULL == pMapFile )
- return false;
-
- const size_t size = pMapFile->FileSize();
- m_Data.resize( size );
-
- const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
- if ( readSize != size )
- {
- m_Data.clear();
- return false;
- }
- m_pZipArchive->Close( pMapFile );
-
- return true;
+ if ( !m_pZipArchive->Exists( rMapName.c_str() ) )
+ return false;
+
+ IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() );
+ if ( NULL == pMapFile )
+ return false;
+
+ const size_t size = pMapFile->FileSize();
+ m_Data.resize( size );
+
+ const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
+ if ( readSize != size )
+ {
+ m_Data.clear();
+ return false;
+ }
+ m_pZipArchive->Close( pMapFile );
+
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool Q3BSPFileParser::parseFile()
{
- if ( m_Data.empty() )
- {
- return false;
- }
+ if ( m_Data.empty() )
+ {
+ return false;
+ }
+
+ if ( !validateFormat() )
+ {
+ return false;
+ }
- if ( !validateFormat() )
- {
- return false;
- }
+ // Imports the dictionary of the level
+ getLumps();
- // Imports the dictionary of the level
- getLumps();
+ // Conunt data and prepare model data
+ countLumps();
- // Conunt data and prepare model data
- countLumps();
+ // Read in Vertices
+ getVertices();
- // Read in Vertices
- getVertices();
+ // Read in Indices
+ getIndices();
- // Read in Indices
- getIndices();
-
- // Read Faces
- getFaces();
+ // Read Faces
+ getFaces();
- // Read Textures
- getTextures();
+ // Read Textures
+ getTextures();
- // Read Lightmaps
- getLightMaps();
+ // Read Lightmaps
+ getLightMaps();
- // Load the entities
- getEntities();
+ // Load the entities
+ getEntities();
- return true;
+ return true;
}
// ------------------------------------------------------------------------------------------------
bool Q3BSPFileParser::validateFormat()
{
- sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ];
- m_sOffset += sizeof( sQ3BSPHeader );
+ sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ];
+ m_sOffset += sizeof( sQ3BSPHeader );
- // Version and identify string validation
- if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S'
- || pHeader->strID[ 3 ] != 'P')
- {
- return false;
- }
+ // Version and identify string validation
+ if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S'
+ || pHeader->strID[ 3 ] != 'P')
+ {
+ return false;
+ }
- return true;
+ return true;
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getLumps()
{
- size_t Offset = m_sOffset;
- m_pModel->m_Lumps.resize( kMaxLumps );
- for ( size_t idx=0; idx < kMaxLumps; idx++ )
- {
- sQ3BSPLump *pLump = new sQ3BSPLump;
- memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) );
- Offset += sizeof( sQ3BSPLump );
- m_pModel->m_Lumps[ idx ] = pLump;
- }
+ size_t Offset = m_sOffset;
+ m_pModel->m_Lumps.resize( kMaxLumps );
+ for ( size_t idx=0; idx < kMaxLumps; idx++ )
+ {
+ sQ3BSPLump *pLump = new sQ3BSPLump;
+ memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) );
+ Offset += sizeof( sQ3BSPLump );
+ m_pModel->m_Lumps[ idx ] = pLump;
+ }
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::countLumps()
{
- m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) );
- m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) );
- m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) );
- m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) );
- m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) );
+ m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) );
+ m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) );
+ m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) );
+ m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) );
+ m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) );
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getVertices()
{
- size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset;
- for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ )
- {
- sQ3BSPVertex *pVertex = new sQ3BSPVertex;
- memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) );
- Offset += sizeof( sQ3BSPVertex );
- m_pModel->m_Vertices[ idx ] = pVertex;
- }
+ size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset;
+ for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ )
+ {
+ sQ3BSPVertex *pVertex = new sQ3BSPVertex;
+ memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) );
+ Offset += sizeof( sQ3BSPVertex );
+ m_pModel->m_Vertices[ idx ] = pVertex;
+ }
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getIndices()
{
- ai_assert( NULL != m_pModel );
+ ai_assert( NULL != m_pModel );
- sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ];
- size_t Offset = (size_t) lump->iOffset;
- const size_t nIndices = lump->iSize / sizeof( int );
- m_pModel->m_Indices.resize( nIndices );
- memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize );
+ sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ];
+ size_t Offset = (size_t) lump->iOffset;
+ const size_t nIndices = lump->iSize / sizeof( int );
+ m_pModel->m_Indices.resize( nIndices );
+ memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize );
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getFaces()
{
- ai_assert( NULL != m_pModel );
-
- size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset;
- for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ )
- {
- sQ3BSPFace *pFace = new sQ3BSPFace;
- memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) );
- m_pModel->m_Faces[ idx ] = pFace;
- Offset += sizeof( sQ3BSPFace );
- }
+ ai_assert( NULL != m_pModel );
+
+ size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset;
+ for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ )
+ {
+ sQ3BSPFace *pFace = new sQ3BSPFace;
+ memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) );
+ m_pModel->m_Faces[ idx ] = pFace;
+ Offset += sizeof( sQ3BSPFace );
+ }
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getTextures()
{
- ai_assert( NULL != m_pModel );
-
- size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset;
- for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ )
- {
- sQ3BSPTexture *pTexture = new sQ3BSPTexture;
- memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) );
- m_pModel->m_Textures[ idx ] = pTexture;
- Offset += sizeof(sQ3BSPTexture);
- }
+ ai_assert( NULL != m_pModel );
+
+ size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset;
+ for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ )
+ {
+ sQ3BSPTexture *pTexture = new sQ3BSPTexture;
+ memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) );
+ m_pModel->m_Textures[ idx ] = pTexture;
+ Offset += sizeof(sQ3BSPTexture);
+ }
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getLightMaps()
{
- ai_assert( NULL != m_pModel );
-
- size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset;
- for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ )
- {
- sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap;
- memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) );
- Offset += sizeof( sQ3BSPLightmap );
- m_pModel->m_Lightmaps[ idx ] = pLightmap;
- }
+ ai_assert( NULL != m_pModel );
+
+ size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset;
+ for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ )
+ {
+ sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap;
+ memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) );
+ Offset += sizeof( sQ3BSPLightmap );
+ m_pModel->m_Lightmaps[ idx ] = pLightmap;
+ }
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileParser::getEntities()
{
- int size = m_pModel->m_Lumps[ kEntities ]->iSize;
- m_pModel->m_EntityData.resize( size );
- if ( size > 0 )
- {
- size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset;
- memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size );
- }
+ int size = m_pModel->m_Lumps[ kEntities ]->iSize;
+ m_pModel->m_EntityData.resize( size );
+ if ( size > 0 )
+ {
+ size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset;
+ memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size );
+ }
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Q3BSPFileParser.h b/src/3rdparty/assimp/code/Q3BSPFileParser.h
index 9685854d2..55de25491 100644
--- a/src/3rdparty/assimp/code/Q3BSPFileParser.h
+++ b/src/3rdparty/assimp/code/Q3BSPFileParser.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -60,28 +60,28 @@ class ZipFile;
class Q3BSPFileParser
{
public:
- Q3BSPFileParser( const std::string &rMapName, Q3BSP::Q3BSPZipArchive *pZipArchive );
- ~Q3BSPFileParser();
- Q3BSP::Q3BSPModel *getModel() const;
+ Q3BSPFileParser( const std::string &rMapName, Q3BSP::Q3BSPZipArchive *pZipArchive );
+ ~Q3BSPFileParser();
+ Q3BSP::Q3BSPModel *getModel() const;
protected:
- bool readData(const std::string &rMapName);
- bool parseFile();
- bool validateFormat();
- void getLumps();
- void countLumps();
- void getVertices();
- void getIndices();
- void getFaces();
- void getTextures();
- void getLightMaps();
- void getEntities();
+ bool readData(const std::string &rMapName);
+ bool parseFile();
+ bool validateFormat();
+ void getLumps();
+ void countLumps();
+ void getVertices();
+ void getIndices();
+ void getFaces();
+ void getTextures();
+ void getLightMaps();
+ void getEntities();
private:
- size_t m_sOffset;
- std::vector<char> m_Data;
- Q3BSP::Q3BSPModel *m_pModel;
- Q3BSP::Q3BSPZipArchive *m_pZipArchive;
+ size_t m_sOffset;
+ std::vector<char> m_Data;
+ Q3BSP::Q3BSPModel *m_pModel;
+ Q3BSP::Q3BSPZipArchive *m_pZipArchive;
};
} // Namespace Assimp
diff --git a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
index ec98a2877..59e437836 100644
--- a/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
+++ b/src/3rdparty/assimp/code/Q3BSPZipArchive.cpp
@@ -5,8 +5,8 @@ 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
+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
@@ -23,290 +23,292 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#include "Q3BSPZipArchive.h"
#include <algorithm>
#include <cassert>
+#include <cstdlib>
+#include <assimp/ai_assert.h>
namespace Assimp {
namespace Q3BSP {
voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
- IOSystem* io_system = (IOSystem*) opaque;
-
- const char* mode_fopen = NULL;
- if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) {
- mode_fopen = "rb";
- } else {
- if(mode & ZLIB_FILEFUNC_MODE_EXISTING) {
- mode_fopen = "r+b";
- } else {
- if(mode & ZLIB_FILEFUNC_MODE_CREATE) {
- mode_fopen = "wb";
- }
- }
- }
-
- return (voidpf) io_system->Open(filename, mode_fopen);
+ IOSystem* io_system = (IOSystem*) opaque;
+
+ const char* mode_fopen = NULL;
+ if((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) {
+ mode_fopen = "rb";
+ } else {
+ if(mode & ZLIB_FILEFUNC_MODE_EXISTING) {
+ mode_fopen = "r+b";
+ } else {
+ if(mode & ZLIB_FILEFUNC_MODE_CREATE) {
+ mode_fopen = "wb";
+ }
+ }
+ }
+
+ return (voidpf) io_system->Open(filename, mode_fopen);
}
-uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) {
- IOStream* io_stream = (IOStream*) stream;
+uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
+ IOStream* io_stream = (IOStream*) stream;
- return io_stream->Read(buf, 1, size);
+ return io_stream->Read(buf, 1, size);
}
-uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
- IOStream* io_stream = (IOStream*) stream;
+uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
+ IOStream* io_stream = (IOStream*) stream;
- return io_stream->Write(buf, 1, size);
+ return io_stream->Write(buf, 1, size);
}
-long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) {
- IOStream* io_stream = (IOStream*) stream;
+long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
+ IOStream* io_stream = (IOStream*) stream;
- return io_stream->Tell();
+ return io_stream->Tell();
}
-long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
- IOStream* io_stream = (IOStream*) stream;
-
- aiOrigin assimp_origin;
- switch (origin) {
- default:
- case ZLIB_FILEFUNC_SEEK_CUR:
- assimp_origin = aiOrigin_CUR;
- break;
- case ZLIB_FILEFUNC_SEEK_END:
- assimp_origin = aiOrigin_END;
- break;
- case ZLIB_FILEFUNC_SEEK_SET:
- assimp_origin = aiOrigin_SET;
- break;
- }
-
- return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
+long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
+ IOStream* io_stream = (IOStream*) stream;
+
+ aiOrigin assimp_origin;
+ switch (origin) {
+ default:
+ case ZLIB_FILEFUNC_SEEK_CUR:
+ assimp_origin = aiOrigin_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END:
+ assimp_origin = aiOrigin_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET:
+ assimp_origin = aiOrigin_SET;
+ break;
+ }
+
+ return (io_stream->Seek(offset, assimp_origin) == aiReturn_SUCCESS ? 0 : -1);
}
int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
- IOSystem* io_system = (IOSystem*) opaque;
- IOStream* io_stream = (IOStream*) stream;
+ IOSystem* io_system = (IOSystem*) opaque;
+ IOStream* io_stream = (IOStream*) stream;
- io_system->Close(io_stream);
+ io_system->Close(io_stream);
- return 0;
+ return 0;
}
-int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
- return 0;
+int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
+ return 0;
}
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
- zlib_filefunc_def mapping;
-
- mapping.zopen_file = open;
- mapping.zread_file = read;
- mapping.zwrite_file = write;
- mapping.ztell_file = tell;
- mapping.zseek_file = seek;
- mapping.zclose_file = close;
- mapping.zerror_file = testerror;
- mapping.opaque = (voidpf) pIOHandler;
-
- return mapping;
+ zlib_filefunc_def mapping;
+
+ mapping.zopen_file = open;
+ mapping.zread_file = read;
+ mapping.zwrite_file = write;
+ mapping.ztell_file = tell;
+ mapping.zseek_file = seek;
+ mapping.zclose_file = close;
+ mapping.zerror_file = testerror;
+ mapping.opaque = (voidpf) pIOHandler;
+
+ return mapping;
}
// ------------------------------------------------------------------------------------------------
ZipFile::ZipFile(size_t size) : m_Size(size) {
- ai_assert(m_Size != 0);
+ ai_assert(m_Size != 0);
- m_Buffer = std::malloc(m_Size);
+ m_Buffer = malloc(m_Size);
}
-
+
ZipFile::~ZipFile() {
- std::free(m_Buffer);
- m_Buffer = NULL;
+ free(m_Buffer);
+ m_Buffer = NULL;
}
size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
- const size_t size = pSize * pCount;
- assert(size <= m_Size);
-
- std::memcpy(pvBuffer, m_Buffer, size);
+ const size_t size = pSize * pCount;
+ assert(size <= m_Size);
+
+ std::memcpy(pvBuffer, m_Buffer, size);
- return size;
+ return size;
}
size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
- return 0;
+ return 0;
}
size_t ZipFile::FileSize() const {
- return m_Size;
+ return m_Size;
}
aiReturn ZipFile::Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
- return aiReturn_FAILURE;
+ return aiReturn_FAILURE;
}
size_t ZipFile::Tell() const {
- return 0;
+ return 0;
}
void ZipFile::Flush() {
- // empty
+ // empty
}
// ------------------------------------------------------------------------------------------------
-// Constructor.
+// Constructor.
Q3BSPZipArchive::Q3BSPZipArchive(IOSystem* pIOHandler, const std::string& rFile) : m_ZipFileHandle(NULL), m_ArchiveMap() {
- if (! rFile.empty()) {
- zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
+ if (! rFile.empty()) {
+ zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);
- m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
+ m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
- if(m_ZipFileHandle != NULL) {
- mapArchive();
- }
- }
+ if(m_ZipFileHandle != NULL) {
+ mapArchive();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Destructor.
+// Destructor.
Q3BSPZipArchive::~Q3BSPZipArchive() {
- for( std::map<std::string, ZipFile*>::iterator it(m_ArchiveMap.begin()), end(m_ArchiveMap.end()); it != end; ++it ) {
- delete it->second;
- }
- m_ArchiveMap.clear();
-
- if(m_ZipFileHandle != NULL) {
- unzClose(m_ZipFileHandle);
- m_ZipFileHandle = NULL;
- }
+ for(auto &file : m_ArchiveMap) {
+ delete file.second;
+ }
+ m_ArchiveMap.clear();
+
+ if(m_ZipFileHandle != NULL) {
+ unzClose(m_ZipFileHandle);
+ m_ZipFileHandle = NULL;
+ }
}
// ------------------------------------------------------------------------------------------------
-// Returns true, if the archive is already open.
+// Returns true, if the archive is already open.
bool Q3BSPZipArchive::isOpen() const {
- return (m_ZipFileHandle != NULL);
+ return (m_ZipFileHandle != NULL);
}
// ------------------------------------------------------------------------------------------------
-// Returns true, if the filename is part of the archive.
+// Returns true, if the filename is part of the archive.
bool Q3BSPZipArchive::Exists(const char* pFile) const {
- ai_assert(pFile != NULL);
+ ai_assert(pFile != NULL);
- bool exist = false;
+ bool exist = false;
- if (pFile != NULL) {
- std::string rFile(pFile);
- std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
+ if (pFile != NULL) {
+ std::string rFile(pFile);
+ std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
- if(it != m_ArchiveMap.end()) {
- exist = true;
- }
- }
+ if(it != m_ArchiveMap.end()) {
+ exist = true;
+ }
+ }
- return exist;
+ return exist;
}
// ------------------------------------------------------------------------------------------------
-// Returns the separator delimiter.
+// Returns the separator delimiter.
char Q3BSPZipArchive::getOsSeparator() const {
#ifndef _WIN32
- return '/';
+ return '/';
#else
- return '\\';
+ return '\\';
#endif
}
// ------------------------------------------------------------------------------------------------
-// Opens a file, which is part of the archive.
+// Opens a file, which is part of the archive.
IOStream *Q3BSPZipArchive::Open(const char* pFile, const char* /*pMode*/) {
- ai_assert(pFile != NULL);
+ ai_assert(pFile != NULL);
- IOStream* result = NULL;
+ IOStream* result = NULL;
- std::map<std::string, ZipFile*>::iterator it = m_ArchiveMap.find(pFile);
+ std::map<std::string, ZipFile*>::iterator it = m_ArchiveMap.find(pFile);
- if(it != m_ArchiveMap.end()) {
- result = (IOStream*) it->second;
- }
+ if(it != m_ArchiveMap.end()) {
+ result = (IOStream*) it->second;
+ }
- return result;
+ return result;
}
// ------------------------------------------------------------------------------------------------
-// Close a filestream.
+// Close a filestream.
void Q3BSPZipArchive::Close(IOStream *pFile) {
- ai_assert(pFile != NULL);
+ ai_assert(pFile != NULL);
- // We don't do anything in case the file would be opened again in the future
+ // We don't do anything in case the file would be opened again in the future
}
// ------------------------------------------------------------------------------------------------
-// Returns the file-list of the archive.
+// Returns the file-list of the archive.
void Q3BSPZipArchive::getFileList(std::vector<std::string> &rFileList) {
- rFileList.clear();
+ rFileList.clear();
- for(std::map<std::string, ZipFile*>::iterator it(m_ArchiveMap.begin()), end(m_ArchiveMap.end()); it != end; ++it) {
- rFileList.push_back(it->first);
- }
+ for(auto &file : m_ArchiveMap) {
+ rFileList.push_back(file.first);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Maps the archive content.
+// Maps the archive content.
bool Q3BSPZipArchive::mapArchive() {
- bool success = false;
-
- if(m_ZipFileHandle != NULL) {
- if(m_ArchiveMap.empty()) {
- // At first ensure file is already open
- if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) {
- // Loop over all files
- do {
- char filename[FileNameSize];
- unz_file_info fileInfo;
-
- if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) {
- // The file has EXACTLY the size of uncompressed_size. In C
- // you need to mark the last character with '\0', so add
- // another character
- if(unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) {
- std::pair<std::map<std::string, ZipFile*>::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size)));
-
- if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) {
- if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) {
- // Nothing to do anymore...
- }
- }
- }
- }
- } while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
- }
- }
-
- success = true;
- }
-
- return success;
+ bool success = false;
+
+ if(m_ZipFileHandle != NULL) {
+ if(m_ArchiveMap.empty()) {
+ // At first ensure file is already open
+ if(unzGoToFirstFile(m_ZipFileHandle) == UNZ_OK) {
+ // Loop over all files
+ do {
+ char filename[FileNameSize];
+ unz_file_info fileInfo;
+
+ if(unzGetCurrentFileInfo(m_ZipFileHandle, &fileInfo, filename, FileNameSize, NULL, 0, NULL, 0) == UNZ_OK) {
+ // The file has EXACTLY the size of uncompressed_size. In C
+ // you need to mark the last character with '\0', so add
+ // another character
+ if(fileInfo.uncompressed_size != 0 && unzOpenCurrentFile(m_ZipFileHandle) == UNZ_OK) {
+ std::pair<std::map<std::string, ZipFile*>::iterator, bool> result = m_ArchiveMap.insert(std::make_pair(filename, new ZipFile(fileInfo.uncompressed_size)));
+
+ if(unzReadCurrentFile(m_ZipFileHandle, result.first->second->m_Buffer, fileInfo.uncompressed_size) == (long int) fileInfo.uncompressed_size) {
+ if(unzCloseCurrentFile(m_ZipFileHandle) == UNZ_OK) {
+ // Nothing to do anymore...
+ }
+ }
+ }
+ }
+ } while(unzGoToNextFile(m_ZipFileHandle) != UNZ_END_OF_LIST_OF_FILE);
+ }
+ }
+
+ success = true;
+ }
+
+ return success;
}
// ------------------------------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/Q3BSPZipArchive.h b/src/3rdparty/assimp/code/Q3BSPZipArchive.h
index 12ce6a52d..e46a11b4c 100644
--- a/src/3rdparty/assimp/code/Q3BSPZipArchive.h
+++ b/src/3rdparty/assimp/code/Q3BSPZipArchive.h
@@ -5,8 +5,8 @@ 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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,9 +40,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_Q3BSP_ZIPARCHIVE_H_INC
#define AI_Q3BSP_ZIPARCHIVE_H_INC
-#include "../contrib/unzip/unzip.h"
-#include "../include/assimp/IOStream.hpp"
-#include "../include/assimp/IOSystem.hpp"
+#include <contrib/unzip/unzip.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
#include <string>
#include <vector>
#include <map>
@@ -52,107 +52,107 @@ namespace Assimp {
namespace Q3BSP {
// ------------------------------------------------------------------------------------------------
-/// \class IOSystem2Unzip
-/// \ingroup Assimp::Q3BSP
+/// \class IOSystem2Unzip
+/// \ingroup Assimp::Q3BSP
///
-/// \brief
+/// \brief
// ------------------------------------------------------------------------------------------------
class IOSystem2Unzip {
- public:
+ public:
- static voidpf open(voidpf opaque, const char* filename, int mode);
+ static voidpf open(voidpf opaque, const char* filename, int mode);
- static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
+ static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
- static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
+ static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
- static long tell(voidpf opaque, voidpf stream);
+ static long tell(voidpf opaque, voidpf stream);
- static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
+ static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
- static int close(voidpf opaque, voidpf stream);
+ static int close(voidpf opaque, voidpf stream);
- static int testerror(voidpf opaque, voidpf stream);
+ static int testerror(voidpf opaque, voidpf stream);
- static zlib_filefunc_def get(IOSystem* pIOHandler);
+ static zlib_filefunc_def get(IOSystem* pIOHandler);
};
// ------------------------------------------------------------------------------------------------
-/// \class ZipFile
-/// \ingroup Assimp::Q3BSP
+/// \class ZipFile
+/// \ingroup Assimp::Q3BSP
///
-/// \brief
+/// \brief
// ------------------------------------------------------------------------------------------------
class ZipFile : public IOStream {
- friend class Q3BSPZipArchive;
+ friend class Q3BSPZipArchive;
- public:
+ public:
- ZipFile(size_t size);
-
- ~ZipFile();
+ explicit ZipFile(size_t size);
- size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
+ ~ZipFile();
- size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
- size_t FileSize() const;
+ size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
- aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
+ size_t FileSize() const;
- size_t Tell() const;
+ aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
- void Flush();
+ size_t Tell() const;
- private:
+ void Flush();
- void* m_Buffer;
+ private:
- size_t m_Size;
+ void* m_Buffer;
+
+ size_t m_Size;
};
// ------------------------------------------------------------------------------------------------
-/// \class Q3BSPZipArchive
-/// \ingroup Assimp::Q3BSP
-///
-/// \brief IMplements a zip archive like the WinZip archives. Will be also used to import data
-/// from a P3K archive ( Quake level format ).
+/// \class Q3BSPZipArchive
+/// \ingroup Assimp::Q3BSP
+///
+/// \brief IMplements a zip archive like the WinZip archives. Will be also used to import data
+/// from a P3K archive ( Quake level format ).
// ------------------------------------------------------------------------------------------------
class Q3BSPZipArchive : public Assimp::IOSystem {
- public:
+ public:
- static const unsigned int FileNameSize = 256;
+ static const unsigned int FileNameSize = 256;
- public:
+ public:
- Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
+ Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
- ~Q3BSPZipArchive();
+ ~Q3BSPZipArchive();
- bool Exists(const char* pFile) const;
+ bool Exists(const char* pFile) const;
- char getOsSeparator() const;
+ char getOsSeparator() const;
- IOStream* Open(const char* pFile, const char* pMode = "rb");
+ IOStream* Open(const char* pFile, const char* pMode = "rb");
- void Close(IOStream* pFile);
+ void Close(IOStream* pFile);
- bool isOpen() const;
+ bool isOpen() const;
- void getFileList(std::vector<std::string> &rFileList);
+ void getFileList(std::vector<std::string> &rFileList);
- private:
+ private:
- bool mapArchive();
+ bool mapArchive();
- private:
+ private:
- unzFile m_ZipFileHandle;
+ unzFile m_ZipFileHandle;
- std::map<std::string, ZipFile*> m_ArchiveMap;
+ std::map<std::string, ZipFile*> m_ArchiveMap;
};
diff --git a/src/3rdparty/assimp/code/Q3DLoader.cpp b/src/3rdparty/assimp/code/Q3DLoader.cpp
index 0e436e328..d9dc29672 100644
--- a/src/3rdparty/assimp/code/Q3DLoader.cpp
+++ b/src/3rdparty/assimp/code/Q3DLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,27 +43,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Q3D importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER
// internal headers
#include "Q3DLoader.h"
#include "StreamReader.h"
#include "fast_atof.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
using namespace Assimp;
static const aiImporterDesc desc = {
- "Quick3D Importer",
- "",
- "",
- "http://www.quick3d.com/",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "q3o q3s"
+ "Quick3D Importer",
+ "",
+ "",
+ "http://www.quick3d.com/",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "q3o q3s"
};
// ------------------------------------------------------------------------------------------------
@@ -72,540 +75,540 @@ Q3DImporter::Q3DImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
Q3DImporter::~Q3DImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- if (extension == "q3s" || extension == "q3o")
- return true;
- else if (!extension.length() || checkSig) {
- if (!pIOHandler)
- return true;
- const char* tokens[] = {"quick3Do","quick3Ds"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "q3s" || extension == "q3o")
+ return true;
+ else if (!extension.length() || checkSig) {
+ if (!pIOHandler)
+ return true;
+ const char* tokens[] = {"quick3Do","quick3Ds"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* Q3DImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void Q3DImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void Q3DImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
-
- // The header is 22 bytes large
- if (stream.GetRemainingSize() < 22)
- throw DeadlyImportError("File is either empty or corrupt: " + pFile);
-
- // Check the file's signature
- if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) &&
- ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 ))
- {
- throw DeadlyImportError("Not a Quick3D file. Signature string is: " +
- std::string((const char*)stream.GetPtr(),8));
- }
-
- // Print the file format version
- DefaultLogger::get()->info("Quick3D File format version: " +
- std::string(&((const char*)stream.GetPtr())[8],2));
-
- // ... an store it
- char major = ((const char*)stream.GetPtr())[8];
- char minor = ((const char*)stream.GetPtr())[9];
-
- stream.IncPtr(10);
- unsigned int numMeshes = (unsigned int)stream.GetI4();
- unsigned int numMats = (unsigned int)stream.GetI4();
- unsigned int numTextures = (unsigned int)stream.GetI4();
-
- std::vector<Material> materials;
- materials.reserve(numMats);
-
- std::vector<Mesh> meshes;
- meshes.reserve(numMeshes);
-
- // Allocate the scene root node
- pScene->mRootNode = new aiNode();
-
- aiColor3D fgColor (0.6f,0.6f,0.6f);
-
- // Now read all file chunks
- while (true)
- {
- if (stream.GetRemainingSize() < 1)break;
- char c = stream.GetI1();
- switch (c)
- {
- // Meshes chunk
- case 'm':
- {
- for (unsigned int quak = 0; quak < numMeshes; ++quak)
- {
- meshes.push_back(Mesh());
- Mesh& mesh = meshes.back();
-
- // read all vertices
- unsigned int numVerts = (unsigned int)stream.GetI4();
- if (!numVerts)
- throw DeadlyImportError("Quick3D: Found mesh with zero vertices");
-
- std::vector<aiVector3D>& verts = mesh.verts;
- verts.resize(numVerts);
-
- for (unsigned int i = 0; i < numVerts;++i)
- {
- verts[i].x = stream.GetF4();
- verts[i].y = stream.GetF4();
- verts[i].z = stream.GetF4();
- }
-
- // read all faces
- numVerts = (unsigned int)stream.GetI4();
- if (!numVerts)
- throw DeadlyImportError("Quick3D: Found mesh with zero faces");
-
- std::vector<Face >& faces = mesh.faces;
- faces.reserve(numVerts);
-
- // number of indices
- for (unsigned int i = 0; i < numVerts;++i)
- {
- faces.push_back(Face(stream.GetI2()) );
- if (faces.back().indices.empty())
- throw DeadlyImportError("Quick3D: Found face with zero indices");
- }
-
- // indices
- for (unsigned int i = 0; i < numVerts;++i)
- {
- Face& vec = faces[i];
- for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
- vec.indices[a] = stream.GetI4();
- }
-
- // material indices
- for (unsigned int i = 0; i < numVerts;++i)
- {
- faces[i].mat = (unsigned int)stream.GetI4();
- }
-
- // read all normals
- numVerts = (unsigned int)stream.GetI4();
- std::vector<aiVector3D>& normals = mesh.normals;
- normals.resize(numVerts);
-
- for (unsigned int i = 0; i < numVerts;++i)
- {
- normals[i].x = stream.GetF4();
- normals[i].y = stream.GetF4();
- normals[i].z = stream.GetF4();
- }
-
- numVerts = (unsigned int)stream.GetI4();
- if (numTextures && numVerts)
- {
- // read all texture coordinates
- std::vector<aiVector3D>& uv = mesh.uv;
- uv.resize(numVerts);
-
- for (unsigned int i = 0; i < numVerts;++i)
- {
- uv[i].x = stream.GetF4();
- uv[i].y = stream.GetF4();
- }
-
- // UV indices
- for (unsigned int i = 0; i < (unsigned int)faces.size();++i)
- {
- Face& vec = faces[i];
- for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
- {
- vec.uvindices[a] = stream.GetI4();
- if (!i && !a)
- mesh.prevUVIdx = vec.uvindices[a];
- else if (vec.uvindices[a] != mesh.prevUVIdx)
- mesh.prevUVIdx = UINT_MAX;
- }
- }
- }
-
- // we don't need the rest, but we need to get to the next chunk
- stream.IncPtr(36);
- if (minor > '0' && major == '3')
- stream.IncPtr(mesh.faces.size());
- }
- // stream.IncPtr(4); // unknown value here
- }
- break;
-
- // materials chunk
- case 'c':
-
- for (unsigned int i = 0; i < numMats; ++i)
- {
- materials.push_back(Material());
- Material& mat = materials.back();
-
- // read the material name
- while (( c = stream.GetI1()))
- mat.name.data[mat.name.length++] = c;
-
- // add the terminal character
- mat.name.data[mat.name.length] = '\0';
-
- // read the ambient color
- mat.ambient.r = stream.GetF4();
- mat.ambient.g = stream.GetF4();
- mat.ambient.b = stream.GetF4();
-
- // read the diffuse color
- mat.diffuse.r = stream.GetF4();
- mat.diffuse.g = stream.GetF4();
- mat.diffuse.b = stream.GetF4();
-
- // read the ambient color
- mat.specular.r = stream.GetF4();
- mat.specular.g = stream.GetF4();
- mat.specular.b = stream.GetF4();
-
- // read the transparency
- mat.transparency = stream.GetF4();
-
- // unknown value here
- // stream.IncPtr(4);
- // FIX: it could be the texture index ...
- mat.texIdx = (unsigned int)stream.GetI4();
- }
-
- break;
-
- // texture chunk
- case 't':
-
- pScene->mNumTextures = numTextures;
- if (!numTextures)break;
- pScene->mTextures = new aiTexture*[pScene->mNumTextures];
- // to make sure we won't crash if we leave through an exception
- ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures);
- for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
- {
- aiTexture* tex = pScene->mTextures[i] = new aiTexture();
-
- // skip the texture name
- while (stream.GetI1());
-
- // read texture width and height
- tex->mWidth = (unsigned int)stream.GetI4();
- tex->mHeight = (unsigned int)stream.GetI4();
-
- if (!tex->mWidth || !tex->mHeight)
- throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
-
- unsigned int mul = tex->mWidth * tex->mHeight;
- aiTexel* begin = tex->pcData = new aiTexel[mul];
- aiTexel* const end = & begin [mul];
-
- for (;begin != end; ++begin)
- {
- begin->r = stream.GetI1();
- begin->g = stream.GetI1();
- begin->b = stream.GetI1();
- begin->a = 0xff;
- }
- }
-
- break;
-
- // scene chunk
- case 's':
- {
- // skip position and rotation
- stream.IncPtr(12);
-
- for (unsigned int i = 0; i < 4;++i)
- for (unsigned int a = 0; a < 4;++a)
- pScene->mRootNode->mTransformation[i][a] = stream.GetF4();
-
- stream.IncPtr(16);
-
- // now setup a single camera
- pScene->mNumCameras = 1;
- pScene->mCameras = new aiCamera*[1];
- aiCamera* cam = pScene->mCameras[0] = new aiCamera();
- cam->mPosition.x = stream.GetF4();
- cam->mPosition.y = stream.GetF4();
- cam->mPosition.z = stream.GetF4();
- cam->mName.Set("Q3DCamera");
-
- // skip eye rotation for the moment
- stream.IncPtr(12);
-
- // read the default material color
- fgColor .r = stream.GetF4();
- fgColor .g = stream.GetF4();
- fgColor .b = stream.GetF4();
-
- // skip some unimportant properties
- stream.IncPtr(29);
-
- // setup a single point light with no attenuation
- pScene->mNumLights = 1;
- pScene->mLights = new aiLight*[1];
- aiLight* light = pScene->mLights[0] = new aiLight();
- light->mName.Set("Q3DLight");
- light->mType = aiLightSource_POINT;
-
- light->mAttenuationConstant = 1;
- light->mAttenuationLinear = 0;
- light->mAttenuationQuadratic = 0;
-
- light->mColorDiffuse.r = stream.GetF4();
- light->mColorDiffuse.g = stream.GetF4();
- light->mColorDiffuse.b = stream.GetF4();
-
- light->mColorSpecular = light->mColorDiffuse;
-
-
- // We don't need the rest, but we need to know where this chunk ends.
- unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
-
- // skip the background file name
- while (stream.GetI1());
-
- // skip background texture data + the remaining fields
- stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here
-
- // TODO
- goto outer;
- }
- break;
-
- default:
- throw DeadlyImportError("Quick3D: Unknown chunk");
- break;
- };
- }
+ StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+
+ // The header is 22 bytes large
+ if (stream.GetRemainingSize() < 22)
+ throw DeadlyImportError("File is either empty or corrupt: " + pFile);
+
+ // Check the file's signature
+ if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) &&
+ ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 ))
+ {
+ throw DeadlyImportError("Not a Quick3D file. Signature string is: " +
+ std::string((const char*)stream.GetPtr(),8));
+ }
+
+ // Print the file format version
+ DefaultLogger::get()->info("Quick3D File format version: " +
+ std::string(&((const char*)stream.GetPtr())[8],2));
+
+ // ... an store it
+ char major = ((const char*)stream.GetPtr())[8];
+ char minor = ((const char*)stream.GetPtr())[9];
+
+ stream.IncPtr(10);
+ unsigned int numMeshes = (unsigned int)stream.GetI4();
+ unsigned int numMats = (unsigned int)stream.GetI4();
+ unsigned int numTextures = (unsigned int)stream.GetI4();
+
+ std::vector<Material> materials;
+ materials.reserve(numMats);
+
+ std::vector<Mesh> meshes;
+ meshes.reserve(numMeshes);
+
+ // Allocate the scene root node
+ pScene->mRootNode = new aiNode();
+
+ aiColor3D fgColor (0.6f,0.6f,0.6f);
+
+ // Now read all file chunks
+ while (true)
+ {
+ if (stream.GetRemainingSize() < 1)break;
+ char c = stream.GetI1();
+ switch (c)
+ {
+ // Meshes chunk
+ case 'm':
+ {
+ for (unsigned int quak = 0; quak < numMeshes; ++quak)
+ {
+ meshes.push_back(Mesh());
+ Mesh& mesh = meshes.back();
+
+ // read all vertices
+ unsigned int numVerts = (unsigned int)stream.GetI4();
+ if (!numVerts)
+ throw DeadlyImportError("Quick3D: Found mesh with zero vertices");
+
+ std::vector<aiVector3D>& verts = mesh.verts;
+ verts.resize(numVerts);
+
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ verts[i].x = stream.GetF4();
+ verts[i].y = stream.GetF4();
+ verts[i].z = stream.GetF4();
+ }
+
+ // read all faces
+ numVerts = (unsigned int)stream.GetI4();
+ if (!numVerts)
+ throw DeadlyImportError("Quick3D: Found mesh with zero faces");
+
+ std::vector<Face >& faces = mesh.faces;
+ faces.reserve(numVerts);
+
+ // number of indices
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ faces.push_back(Face(stream.GetI2()) );
+ if (faces.back().indices.empty())
+ throw DeadlyImportError("Quick3D: Found face with zero indices");
+ }
+
+ // indices
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ Face& vec = faces[i];
+ for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
+ vec.indices[a] = stream.GetI4();
+ }
+
+ // material indices
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ faces[i].mat = (unsigned int)stream.GetI4();
+ }
+
+ // read all normals
+ numVerts = (unsigned int)stream.GetI4();
+ std::vector<aiVector3D>& normals = mesh.normals;
+ normals.resize(numVerts);
+
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ normals[i].x = stream.GetF4();
+ normals[i].y = stream.GetF4();
+ normals[i].z = stream.GetF4();
+ }
+
+ numVerts = (unsigned int)stream.GetI4();
+ if (numTextures && numVerts)
+ {
+ // read all texture coordinates
+ std::vector<aiVector3D>& uv = mesh.uv;
+ uv.resize(numVerts);
+
+ for (unsigned int i = 0; i < numVerts;++i)
+ {
+ uv[i].x = stream.GetF4();
+ uv[i].y = stream.GetF4();
+ }
+
+ // UV indices
+ for (unsigned int i = 0; i < (unsigned int)faces.size();++i)
+ {
+ Face& vec = faces[i];
+ for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
+ {
+ vec.uvindices[a] = stream.GetI4();
+ if (!i && !a)
+ mesh.prevUVIdx = vec.uvindices[a];
+ else if (vec.uvindices[a] != mesh.prevUVIdx)
+ mesh.prevUVIdx = UINT_MAX;
+ }
+ }
+ }
+
+ // we don't need the rest, but we need to get to the next chunk
+ stream.IncPtr(36);
+ if (minor > '0' && major == '3')
+ stream.IncPtr(mesh.faces.size());
+ }
+ // stream.IncPtr(4); // unknown value here
+ }
+ break;
+
+ // materials chunk
+ case 'c':
+
+ for (unsigned int i = 0; i < numMats; ++i)
+ {
+ materials.push_back(Material());
+ Material& mat = materials.back();
+
+ // read the material name
+ while (( c = stream.GetI1()))
+ mat.name.data[mat.name.length++] = c;
+
+ // add the terminal character
+ mat.name.data[mat.name.length] = '\0';
+
+ // read the ambient color
+ mat.ambient.r = stream.GetF4();
+ mat.ambient.g = stream.GetF4();
+ mat.ambient.b = stream.GetF4();
+
+ // read the diffuse color
+ mat.diffuse.r = stream.GetF4();
+ mat.diffuse.g = stream.GetF4();
+ mat.diffuse.b = stream.GetF4();
+
+ // read the ambient color
+ mat.specular.r = stream.GetF4();
+ mat.specular.g = stream.GetF4();
+ mat.specular.b = stream.GetF4();
+
+ // read the transparency
+ mat.transparency = stream.GetF4();
+
+ // unknown value here
+ // stream.IncPtr(4);
+ // FIX: it could be the texture index ...
+ mat.texIdx = (unsigned int)stream.GetI4();
+ }
+
+ break;
+
+ // texture chunk
+ case 't':
+
+ pScene->mNumTextures = numTextures;
+ if (!numTextures)break;
+ pScene->mTextures = new aiTexture*[pScene->mNumTextures];
+ // to make sure we won't crash if we leave through an exception
+ ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures);
+ for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
+ {
+ aiTexture* tex = pScene->mTextures[i] = new aiTexture();
+
+ // skip the texture name
+ while (stream.GetI1());
+
+ // read texture width and height
+ tex->mWidth = (unsigned int)stream.GetI4();
+ tex->mHeight = (unsigned int)stream.GetI4();
+
+ if (!tex->mWidth || !tex->mHeight)
+ throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero");
+
+ unsigned int mul = tex->mWidth * tex->mHeight;
+ aiTexel* begin = tex->pcData = new aiTexel[mul];
+ aiTexel* const end = & begin [mul];
+
+ for (;begin != end; ++begin)
+ {
+ begin->r = stream.GetI1();
+ begin->g = stream.GetI1();
+ begin->b = stream.GetI1();
+ begin->a = 0xff;
+ }
+ }
+
+ break;
+
+ // scene chunk
+ case 's':
+ {
+ // skip position and rotation
+ stream.IncPtr(12);
+
+ for (unsigned int i = 0; i < 4;++i)
+ for (unsigned int a = 0; a < 4;++a)
+ pScene->mRootNode->mTransformation[i][a] = stream.GetF4();
+
+ stream.IncPtr(16);
+
+ // now setup a single camera
+ pScene->mNumCameras = 1;
+ pScene->mCameras = new aiCamera*[1];
+ aiCamera* cam = pScene->mCameras[0] = new aiCamera();
+ cam->mPosition.x = stream.GetF4();
+ cam->mPosition.y = stream.GetF4();
+ cam->mPosition.z = stream.GetF4();
+ cam->mName.Set("Q3DCamera");
+
+ // skip eye rotation for the moment
+ stream.IncPtr(12);
+
+ // read the default material color
+ fgColor .r = stream.GetF4();
+ fgColor .g = stream.GetF4();
+ fgColor .b = stream.GetF4();
+
+ // skip some unimportant properties
+ stream.IncPtr(29);
+
+ // setup a single point light with no attenuation
+ pScene->mNumLights = 1;
+ pScene->mLights = new aiLight*[1];
+ aiLight* light = pScene->mLights[0] = new aiLight();
+ light->mName.Set("Q3DLight");
+ light->mType = aiLightSource_POINT;
+
+ light->mAttenuationConstant = 1;
+ light->mAttenuationLinear = 0;
+ light->mAttenuationQuadratic = 0;
+
+ light->mColorDiffuse.r = stream.GetF4();
+ light->mColorDiffuse.g = stream.GetF4();
+ light->mColorDiffuse.b = stream.GetF4();
+
+ light->mColorSpecular = light->mColorDiffuse;
+
+
+ // We don't need the rest, but we need to know where this chunk ends.
+ unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
+
+ // skip the background file name
+ while (stream.GetI1());
+
+ // skip background texture data + the remaining fields
+ stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here
+
+ // TODO
+ goto outer;
+ }
+ break;
+
+ default:
+ throw DeadlyImportError("Quick3D: Unknown chunk");
+ break;
+ };
+ }
outer:
- // If we have no mesh loaded - break here
- if (meshes.empty())
- throw DeadlyImportError("Quick3D: No meshes loaded");
-
- // If we have no materials loaded - generate a default mat
- if (materials.empty())
- {
- DefaultLogger::get()->info("Quick3D: No material found, generating one");
- materials.push_back(Material());
- materials.back().diffuse = fgColor ;
- }
-
- // find out which materials we'll need
- typedef std::pair<unsigned int, unsigned int> FaceIdx;
- typedef std::vector< FaceIdx > FaceIdxArray;
- FaceIdxArray* fidx = new FaceIdxArray[materials.size()];
-
- unsigned int p = 0;
- for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end();
- it != end; ++it,++p)
- {
- unsigned int q = 0;
- for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end();
- fit != fend; ++fit,++q)
- {
- if ((*fit).mat >= materials.size())
- {
- DefaultLogger::get()->warn("Quick3D: Material index overflow");
- (*fit).mat = 0;
- }
- if (fidx[(*fit).mat].empty())++pScene->mNumMeshes;
- fidx[(*fit).mat].push_back( FaceIdx(p,q) );
- }
- }
- pScene->mNumMaterials = pScene->mNumMeshes;
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
- pScene->mMeshes = new aiMesh*[pScene->mNumMaterials];
-
- for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i)
- {
- if (fidx[i].empty())continue;
-
- // Allocate a mesh and a material
- aiMesh* mesh = pScene->mMeshes[real] = new aiMesh();
- aiMaterial* mat = new aiMaterial();
- pScene->mMaterials[real] = mat;
-
- mesh->mMaterialIndex = real;
-
- // Build the output material
- Material& srcMat = materials[i];
- mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE);
- mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
- mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
-
- // NOTE: Ignore transparency for the moment - it seems
- // unclear how to interpret the data
+ // If we have no mesh loaded - break here
+ if (meshes.empty())
+ throw DeadlyImportError("Quick3D: No meshes loaded");
+
+ // If we have no materials loaded - generate a default mat
+ if (materials.empty())
+ {
+ DefaultLogger::get()->info("Quick3D: No material found, generating one");
+ materials.push_back(Material());
+ materials.back().diffuse = fgColor ;
+ }
+
+ // find out which materials we'll need
+ typedef std::pair<unsigned int, unsigned int> FaceIdx;
+ typedef std::vector< FaceIdx > FaceIdxArray;
+ FaceIdxArray* fidx = new FaceIdxArray[materials.size()];
+
+ unsigned int p = 0;
+ for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end();
+ it != end; ++it,++p)
+ {
+ unsigned int q = 0;
+ for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end();
+ fit != fend; ++fit,++q)
+ {
+ if ((*fit).mat >= materials.size())
+ {
+ DefaultLogger::get()->warn("Quick3D: Material index overflow");
+ (*fit).mat = 0;
+ }
+ if (fidx[(*fit).mat].empty())++pScene->mNumMeshes;
+ fidx[(*fit).mat].push_back( FaceIdx(p,q) );
+ }
+ }
+ pScene->mNumMaterials = pScene->mNumMeshes;
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ pScene->mMeshes = new aiMesh*[pScene->mNumMaterials];
+
+ for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i)
+ {
+ if (fidx[i].empty())continue;
+
+ // Allocate a mesh and a material
+ aiMesh* mesh = pScene->mMeshes[real] = new aiMesh();
+ aiMaterial* mat = new aiMaterial();
+ pScene->mMaterials[real] = mat;
+
+ mesh->mMaterialIndex = real;
+
+ // Build the output material
+ Material& srcMat = materials[i];
+ mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE);
+ mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
+ mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ // NOTE: Ignore transparency for the moment - it seems
+ // unclear how to interpret the data
#if 0
- if (!(minor > '0' && major == '3'))
- srcMat.transparency = 1.0f - srcMat.transparency;
- mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
+ if (!(minor > '0' && major == '3'))
+ srcMat.transparency = 1.0f - srcMat.transparency;
+ mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
#endif
- // add shininess - Quick3D seems to use it ins its viewer
- srcMat.transparency = 16.f;
- mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS);
-
- int m = (int)aiShadingMode_Phong;
- mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL);
-
- if (srcMat.name.length)
- mat->AddProperty(&srcMat.name,AI_MATKEY_NAME);
-
- // Add a texture
- if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures)
- {
- srcMat.name.data[0] = '*';
- srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000,
- (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real));
- mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
-
- mesh->mNumFaces = (unsigned int)fidx[i].size();
- aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
-
- // Now build the output mesh. First find out how many
- // vertices we'll need
- for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
- it != end; ++it)
- {
- mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[
- (*it).second].indices.size();
- }
-
- aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
- aiVector3D* uv;
- if (real < pScene->mNumTextures)
- {
- uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
- mesh->mNumUVComponents[0] = 2;
- }
- else uv = NULL;
-
- // Build the final array
- unsigned int cnt = 0;
- for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
- it != end; ++it, ++faces)
- {
- Mesh& m = meshes[(*it).first];
- Face& face = m.faces[(*it).second];
- faces->mNumIndices = (unsigned int)face.indices.size();
- faces->mIndices = new unsigned int [faces->mNumIndices];
-
-
- aiVector3D faceNormal;
- bool fnOK = false;
-
- for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts)
- {
- if (face.indices[n] >= m.verts.size())
- {
- DefaultLogger::get()->warn("Quick3D: Vertex index overflow");
- face.indices[n] = 0;
- }
-
- // copy vertices
- *verts = m.verts[ face.indices[n] ];
-
- if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3)
- {
- // we have no normal here - assign the face normal
- if (!fnOK)
- {
- const aiVector3D& pV1 = m.verts[ face.indices[0] ];
- const aiVector3D& pV2 = m.verts[ face.indices[1] ];
- const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ];
- faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize();
- fnOK = true;
- }
- *norms = faceNormal;
- }
- else *norms = m.normals[ face.indices[n] ];
-
- // copy texture coordinates
- if (uv && m.uv.size())
- {
- if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
- {
- *uv = m.uv[face.indices[n]];
- }
- else
- {
- if (face.uvindices[n] >= m.uv.size())
- {
- DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow");
- face.uvindices[n] = 0;
- }
- *uv = m.uv[face.uvindices[n]];
- }
- uv->y = 1.f - uv->y;
- ++uv;
- }
-
- // setup the new vertex index
- faces->mIndices[n] = cnt;
- }
-
- }
- ++real;
- }
-
- // Delete our nice helper array
- delete[] fidx;
-
- // Now we need to attach the meshes to the root node of the scene
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mRootNode->mMeshes[i] = i;
-
- /*pScene->mRootNode->mTransformation *= aiMatrix4x4(
- 1.f, 0.f, 0.f, 0.f,
- 0.f, -1.f,0.f, 0.f,
- 0.f, 0.f, 1.f, 0.f,
- 0.f, 0.f, 0.f, 1.f);*/
-
- // Add cameras and light sources to the scene root node
- pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras;
- if (pScene->mRootNode->mNumChildren)
- {
- pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ];
-
- // the light source
- aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode();
- nd->mParent = pScene->mRootNode;
- nd->mName.Set("Q3DLight");
- nd->mTransformation = pScene->mRootNode->mTransformation;
- nd->mTransformation.Inverse();
-
- // camera
- nd = pScene->mRootNode->mChildren[1] = new aiNode();
- nd->mParent = pScene->mRootNode;
- nd->mName.Set("Q3DCamera");
- nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation;
- }
+ // add shininess - Quick3D seems to use it ins its viewer
+ srcMat.transparency = 16.f;
+ mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS);
+
+ int m = (int)aiShadingMode_Phong;
+ mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL);
+
+ if (srcMat.name.length)
+ mat->AddProperty(&srcMat.name,AI_MATKEY_NAME);
+
+ // Add a texture
+ if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures)
+ {
+ srcMat.name.data[0] = '*';
+ srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000,
+ (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real));
+ mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+
+ mesh->mNumFaces = (unsigned int)fidx[i].size();
+ aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+
+ // Now build the output mesh. First find out how many
+ // vertices we'll need
+ for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
+ it != end; ++it)
+ {
+ mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[
+ (*it).second].indices.size();
+ }
+
+ aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+ aiVector3D* uv;
+ if (real < pScene->mNumTextures)
+ {
+ uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+ mesh->mNumUVComponents[0] = 2;
+ }
+ else uv = NULL;
+
+ // Build the final array
+ unsigned int cnt = 0;
+ for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
+ it != end; ++it, ++faces)
+ {
+ Mesh& m = meshes[(*it).first];
+ Face& face = m.faces[(*it).second];
+ faces->mNumIndices = (unsigned int)face.indices.size();
+ faces->mIndices = new unsigned int [faces->mNumIndices];
+
+
+ aiVector3D faceNormal;
+ bool fnOK = false;
+
+ for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts)
+ {
+ if (face.indices[n] >= m.verts.size())
+ {
+ DefaultLogger::get()->warn("Quick3D: Vertex index overflow");
+ face.indices[n] = 0;
+ }
+
+ // copy vertices
+ *verts = m.verts[ face.indices[n] ];
+
+ if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3)
+ {
+ // we have no normal here - assign the face normal
+ if (!fnOK)
+ {
+ const aiVector3D& pV1 = m.verts[ face.indices[0] ];
+ const aiVector3D& pV2 = m.verts[ face.indices[1] ];
+ const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ];
+ faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize();
+ fnOK = true;
+ }
+ *norms = faceNormal;
+ }
+ else *norms = m.normals[ face.indices[n] ];
+
+ // copy texture coordinates
+ if (uv && m.uv.size())
+ {
+ if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
+ {
+ *uv = m.uv[face.indices[n]];
+ }
+ else
+ {
+ if (face.uvindices[n] >= m.uv.size())
+ {
+ DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow");
+ face.uvindices[n] = 0;
+ }
+ *uv = m.uv[face.uvindices[n]];
+ }
+ uv->y = 1.f - uv->y;
+ ++uv;
+ }
+
+ // setup the new vertex index
+ faces->mIndices[n] = cnt;
+ }
+
+ }
+ ++real;
+ }
+
+ // Delete our nice helper array
+ delete[] fidx;
+
+ // Now we need to attach the meshes to the root node of the scene
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mRootNode->mMeshes[i] = i;
+
+ /*pScene->mRootNode->mTransformation *= aiMatrix4x4(
+ 1.f, 0.f, 0.f, 0.f,
+ 0.f, -1.f,0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f);*/
+
+ // Add cameras and light sources to the scene root node
+ pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras;
+ if (pScene->mRootNode->mNumChildren)
+ {
+ pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ];
+
+ // the light source
+ aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode();
+ nd->mParent = pScene->mRootNode;
+ nd->mName.Set("Q3DLight");
+ nd->mTransformation = pScene->mRootNode->mTransformation;
+ nd->mTransformation.Inverse();
+
+ // camera
+ nd = pScene->mRootNode->mChildren[1] = new aiNode();
+ nd->mParent = pScene->mRootNode;
+ nd->mName.Set("Q3DCamera");
+ nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation;
+ }
}
#endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/Q3DLoader.h b/src/3rdparty/assimp/code/Q3DLoader.h
index 986630406..fb1dd1818 100644
--- a/src/3rdparty/assimp/code/Q3DLoader.h
+++ b/src/3rdparty/assimp/code/Q3DLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,10 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_Q3DLOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include <vector>
+#include <stdint.h>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the Quick3D Object and Scene formats.
@@ -56,74 +57,74 @@ namespace Assimp {
class Q3DImporter : public BaseImporter
{
public:
- Q3DImporter();
- ~Q3DImporter();
+ Q3DImporter();
+ ~Q3DImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- struct Material
- {
- Material()
- : diffuse (0.6f,0.6f,0.6f)
- , transparency (0.f)
- , texIdx (UINT_MAX)
- {}
-
- aiString name;
- aiColor3D ambient, diffuse, specular;
- float transparency;
-
- unsigned int texIdx;
- };
-
- struct Face
- {
- Face(unsigned int s)
- : indices (s)
- , uvindices (s)
- , mat (0)
- {
- }
-
- std::vector<unsigned int> indices;
- std::vector<unsigned int> uvindices;
- unsigned int mat;
- };
-
- struct Mesh
- {
-
- std::vector<aiVector3D> verts;
- std::vector<aiVector3D> normals;
- std::vector<aiVector3D> uv;
- std::vector<Face> faces;
-
- uint32_t prevUVIdx;
- };
+ struct Material
+ {
+ Material()
+ : diffuse (0.6f,0.6f,0.6f)
+ , transparency (0.f)
+ , texIdx (UINT_MAX)
+ {}
+
+ aiString name;
+ aiColor3D ambient, diffuse, specular;
+ float transparency;
+
+ unsigned int texIdx;
+ };
+
+ struct Face
+ {
+ explicit Face(unsigned int s)
+ : indices (s)
+ , uvindices (s)
+ , mat (0)
+ {
+ }
+
+ std::vector<unsigned int> indices;
+ std::vector<unsigned int> uvindices;
+ unsigned int mat;
+ };
+
+ struct Mesh
+ {
+
+ std::vector<aiVector3D> verts;
+ std::vector<aiVector3D> normals;
+ std::vector<aiVector3D> uv;
+ std::vector<Face> faces;
+
+ uint32_t prevUVIdx;
+ };
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/RawLoader.cpp b/src/3rdparty/assimp/code/RawLoader.cpp
index 044cbf300..57e0fc119 100644
--- a/src/3rdparty/assimp/code/RawLoader.cpp
+++ b/src/3rdparty/assimp/code/RawLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,45 +25,50 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file RawLoader.cpp
- * @brief Implementation of the RAW importer class
+ * @brief Implementation of the RAW importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
// internal headers
#include "RawLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Raw Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "raw"
+ "Raw Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "raw"
};
// ------------------------------------------------------------------------------------------------
@@ -72,253 +77,250 @@ RAWImporter::RAWImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
RAWImporter::~RAWImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
{
- return SimpleExtensionCheck(pFile,"raw");
+ return SimpleExtensionCheck(pFile,"raw");
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* RAWImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void RAWImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void RAWImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open RAW file " + pFile + ".");
- }
-
- // allocate storage and copy the contents of the file to a memory buffer
- // (terminate it with zero)
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
- const char* buffer = &mBuffer2[0];
-
- // list of groups loaded from the file
- std::vector< GroupInformation > outGroups(1,GroupInformation("<default>"));
- std::vector< GroupInformation >::iterator curGroup = outGroups.begin();
-
- // now read all lines
- char line[4096];
- while (GetNextLine(buffer,line))
- {
- // if the line starts with a non-numeric identifier, it marks
- // the beginning of a new group
- const char* sz = line;SkipSpaces(&sz);
- if (IsLineEnd(*sz))continue;
- if (!IsNumeric(*sz))
- {
- const char* sz2 = sz;
- while (!IsSpaceOrNewLine(*sz2))++sz2;
- const unsigned int length = (unsigned int)(sz2-sz);
-
- // find an existing group with this name
- for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
- it != end;++it)
- {
- if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str()))
- {
- curGroup = it;sz2 = NULL;
- break;
- }
- }
- if (sz2)
- {
- outGroups.push_back(GroupInformation(std::string(sz,length)));
- curGroup = outGroups.end()-1;
- }
- }
- else
- {
- // there can be maximally 12 floats plus an extra texture file name
- float data[12];
- unsigned int num;
- for (num = 0; num < 12;++num)
- {
- if(!SkipSpaces(&sz) || !IsNumeric(*sz))break;
- sz = fast_atoreal_move<float>(sz,data[num]);
- }
- if (num != 12 && num != 9)
- {
- DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture");
- continue;
- }
-
- MeshInformation* output = NULL;
-
- const char* sz2 = sz;
- unsigned int length;
- if (!IsLineEnd(*sz))
- {
- while (!IsSpaceOrNewLine(*sz2))++sz2;
- length = (unsigned int)(sz2-sz);
- }
- else if (9 == num)
- {
- sz = "%default%";
- length = 9;
- }
- else
- {
- sz = "";
- length = 0;
- }
-
- // search in the list of meshes whether we have one with this texture
- for (std::vector< MeshInformation >::iterator it = (*curGroup).meshes.begin(),
- end = (*curGroup).meshes.end(); it != end; ++it)
- {
- if (length == (*it).name.length() && (length ? !::strcmp(sz,(*it).name.c_str()) : true))
- {
- output = &(*it);
- break;
- }
- }
- // if we don't have the mesh, create it
- if (!output)
- {
- (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
- output = &((*curGroup).meshes.back());
- }
- if (12 == num)
- {
- aiColor4D v(data[0],data[1],data[2],1.0f);
- output->colors.push_back(v);
- output->colors.push_back(v);
- output->colors.push_back(v);
-
- output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
- output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
- output->vertices.push_back(aiVector3D(data[9],data[10],data[11]));
- }
- else
- {
- output->vertices.push_back(aiVector3D(data[0],data[1],data[2]));
- output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
- output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
- }
- }
- }
-
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mName.Set("<RawRoot>");
-
- // count the number of valid groups
- // (meshes can't be empty)
- for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
- it != end;++it)
- {
- if (!(*it).meshes.empty())
- {
- ++pScene->mRootNode->mNumChildren;
- pScene->mNumMeshes += (unsigned int)(*it).meshes.size();
- }
- }
-
- if (!pScene->mNumMeshes)
- {
- throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty.");
- }
-
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- aiNode** cc;
- if (1 == pScene->mRootNode->mNumChildren)
- {
- cc = &pScene->mRootNode;
- pScene->mRootNode->mNumChildren = 0;
- }
- else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
-
- pScene->mNumMaterials = pScene->mNumMeshes;
- aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-
- unsigned int meshIdx = 0;
- for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
- it != end;++it)
- {
- if ((*it).meshes.empty())continue;
-
- aiNode* node;
- if (pScene->mRootNode->mNumChildren)
- {
- node = *cc = new aiNode();
- node->mParent = pScene->mRootNode;
- }
- else node = *cc;++cc;
- node->mName.Set((*it).name);
-
- // add all meshes
- node->mNumMeshes = (unsigned int)(*it).meshes.size();
- unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ];
- for (std::vector< MeshInformation >::iterator it2 = (*it).meshes.begin(),
- end2 = (*it).meshes.end(); it2 != end2; ++it2)
- {
- ai_assert(!(*it2).vertices.empty());
-
- // allocate the mesh
- *pi++ = meshIdx;
- aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh();
- mesh->mMaterialIndex = meshIdx++;
-
- mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- // allocate storage for the vertex components and copy them
- mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
- mesh->mVertices = new aiVector3D[ mesh->mNumVertices ];
- ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
-
- if ((*it2).colors.size())
- {
- ai_assert((*it2).colors.size() == mesh->mNumVertices);
-
- mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ];
- ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices);
- }
-
- // generate triangles
- ai_assert(0 == mesh->mNumVertices % 3);
- aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ];
- aiFace* const fcEnd = fc + mesh->mNumFaces;
- unsigned int n = 0;
- while (fc != fcEnd)
- {
- aiFace& f = *fc++;
- f.mIndices = new unsigned int[f.mNumIndices = 3];
- for (unsigned int m = 0; m < 3;++m)
- f.mIndices[m] = n++;
- }
-
- // generate a material for the mesh
- aiMaterial* mat = new aiMaterial();
-
- aiColor4D clr(1.0f,1.0f,1.0f,1.0f);
- if ("%default%" == (*it2).name) // a gray default material
- {
- clr.r = clr.g = clr.b = 0.6f;
- }
- else if ((*it2).name.length() > 0) // a texture
- {
- aiString s;
- s.Set((*it2).name);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
- *mats++ = mat;
- }
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open RAW file " + pFile + ".");
+ }
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ // (terminate it with zero)
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+ const char* buffer = &mBuffer2[0];
+
+ // list of groups loaded from the file
+ std::vector< GroupInformation > outGroups(1,GroupInformation("<default>"));
+ std::vector< GroupInformation >::iterator curGroup = outGroups.begin();
+
+ // now read all lines
+ char line[4096];
+ while (GetNextLine(buffer,line))
+ {
+ // if the line starts with a non-numeric identifier, it marks
+ // the beginning of a new group
+ const char* sz = line;SkipSpaces(&sz);
+ if (IsLineEnd(*sz))continue;
+ if (!IsNumeric(*sz))
+ {
+ const char* sz2 = sz;
+ while (!IsSpaceOrNewLine(*sz2))++sz2;
+ const unsigned int length = (unsigned int)(sz2-sz);
+
+ // find an existing group with this name
+ for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
+ it != end;++it)
+ {
+ if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str()))
+ {
+ curGroup = it;sz2 = NULL;
+ break;
+ }
+ }
+ if (sz2)
+ {
+ outGroups.push_back(GroupInformation(std::string(sz,length)));
+ curGroup = outGroups.end()-1;
+ }
+ }
+ else
+ {
+ // there can be maximally 12 floats plus an extra texture file name
+ float data[12];
+ unsigned int num;
+ for (num = 0; num < 12;++num)
+ {
+ if(!SkipSpaces(&sz) || !IsNumeric(*sz))break;
+ sz = fast_atoreal_move<float>(sz,data[num]);
+ }
+ if (num != 12 && num != 9)
+ {
+ DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture");
+ continue;
+ }
+
+ MeshInformation* output = NULL;
+
+ const char* sz2 = sz;
+ unsigned int length;
+ if (!IsLineEnd(*sz))
+ {
+ while (!IsSpaceOrNewLine(*sz2))++sz2;
+ length = (unsigned int)(sz2-sz);
+ }
+ else if (9 == num)
+ {
+ sz = "%default%";
+ length = 9;
+ }
+ else
+ {
+ sz = "";
+ length = 0;
+ }
+
+ // search in the list of meshes whether we have one with this texture
+ for (auto &mesh : (*curGroup).meshes)
+ {
+ if (length == mesh.name.length() && (length ? !::strcmp(sz, mesh.name.c_str()) : true))
+ {
+ output = &mesh;
+ break;
+ }
+ }
+ // if we don't have the mesh, create it
+ if (!output)
+ {
+ (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
+ output = &((*curGroup).meshes.back());
+ }
+ if (12 == num)
+ {
+ aiColor4D v(data[0],data[1],data[2],1.0f);
+ output->colors.push_back(v);
+ output->colors.push_back(v);
+ output->colors.push_back(v);
+
+ output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
+ output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
+ output->vertices.push_back(aiVector3D(data[9],data[10],data[11]));
+ }
+ else
+ {
+ output->vertices.push_back(aiVector3D(data[0],data[1],data[2]));
+ output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
+ output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
+ }
+ }
+ }
+
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<RawRoot>");
+
+ // count the number of valid groups
+ // (meshes can't be empty)
+ for (auto & outGroup : outGroups)
+ {
+ if (!outGroup.meshes.empty())
+ {
+ ++pScene->mRootNode->mNumChildren;
+ pScene->mNumMeshes += (unsigned int) outGroup.meshes.size();
+ }
+ }
+
+ if (!pScene->mNumMeshes)
+ {
+ throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty.");
+ }
+
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ aiNode** cc;
+ if (1 == pScene->mRootNode->mNumChildren)
+ {
+ cc = &pScene->mRootNode;
+ pScene->mRootNode->mNumChildren = 0;
+ }
+ else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
+
+ pScene->mNumMaterials = pScene->mNumMeshes;
+ aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+
+ unsigned int meshIdx = 0;
+ for (auto & outGroup : outGroups)
+ {
+ if (outGroup.meshes.empty())continue;
+
+ aiNode* node;
+ if (pScene->mRootNode->mNumChildren)
+ {
+ node = *cc = new aiNode();
+ node->mParent = pScene->mRootNode;
+ }
+ else node = *cc;++cc;
+ node->mName.Set(outGroup.name);
+
+ // add all meshes
+ node->mNumMeshes = (unsigned int) outGroup.meshes.size();
+ unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ];
+ for (std::vector< MeshInformation >::iterator it2 = outGroup.meshes.begin(),
+ end2 = outGroup.meshes.end(); it2 != end2; ++it2)
+ {
+ ai_assert(!(*it2).vertices.empty());
+
+ // allocate the mesh
+ *pi++ = meshIdx;
+ aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh();
+ mesh->mMaterialIndex = meshIdx++;
+
+ mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // allocate storage for the vertex components and copy them
+ mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
+ mesh->mVertices = new aiVector3D[ mesh->mNumVertices ];
+ ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
+
+ if ((*it2).colors.size())
+ {
+ ai_assert((*it2).colors.size() == mesh->mNumVertices);
+
+ mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ];
+ ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices);
+ }
+
+ // generate triangles
+ ai_assert(0 == mesh->mNumVertices % 3);
+ aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ];
+ aiFace* const fcEnd = fc + mesh->mNumFaces;
+ unsigned int n = 0;
+ while (fc != fcEnd)
+ {
+ aiFace& f = *fc++;
+ f.mIndices = new unsigned int[f.mNumIndices = 3];
+ for (unsigned int m = 0; m < 3;++m)
+ f.mIndices[m] = n++;
+ }
+
+ // generate a material for the mesh
+ aiMaterial* mat = new aiMaterial();
+
+ aiColor4D clr(1.0f,1.0f,1.0f,1.0f);
+ if ("%default%" == (*it2).name) // a gray default material
+ {
+ clr.r = clr.g = clr.b = 0.6f;
+ }
+ else if ((*it2).name.length() > 0) // a texture
+ {
+ aiString s;
+ s.Set((*it2).name);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ *mats++ = mat;
+ }
+ }
}
#endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER
diff --git a/src/3rdparty/assimp/code/RawLoader.h b/src/3rdparty/assimp/code/RawLoader.h
index 9be07a8ae..984141a04 100644
--- a/src/3rdparty/assimp/code/RawLoader.h
+++ b/src/3rdparty/assimp/code/RawLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,10 +45,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_RAWLOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
#include <vector>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the PovRay RAW triangle format
@@ -56,62 +56,62 @@ namespace Assimp {
class RAWImporter : public BaseImporter
{
public:
- RAWImporter();
- ~RAWImporter();
+ RAWImporter();
+ ~RAWImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- struct MeshInformation
- {
- MeshInformation(const std::string& _name)
- : name(_name)
- {
- vertices.reserve(100);
- colors.reserve(100);
- }
-
- std::string name;
-
- std::vector<aiVector3D> vertices;
- std::vector<aiColor4D> colors;
- };
-
- struct GroupInformation
- {
- GroupInformation(const std::string& _name)
- : name(_name)
- {
- meshes.reserve(10);
- }
-
- std::string name;
- std::vector<MeshInformation> meshes;
- };
+ struct MeshInformation
+ {
+ explicit MeshInformation(const std::string& _name)
+ : name(_name)
+ {
+ vertices.reserve(100);
+ colors.reserve(100);
+ }
+
+ std::string name;
+
+ std::vector<aiVector3D> vertices;
+ std::vector<aiColor4D> colors;
+ };
+
+ struct GroupInformation
+ {
+ explicit GroupInformation(const std::string& _name)
+ : name(_name)
+ {
+ meshes.reserve(10);
+ }
+
+ std::string name;
+ std::vector<MeshInformation> meshes;
+ };
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/RemoveComments.cpp b/src/3rdparty/assimp/code/RemoveComments.cpp
index 8de8227f4..8290d2217 100644
--- a/src/3rdparty/assimp/code/RemoveComments.cpp
+++ b/src/3rdparty/assimp/code/RemoveComments.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,67 +42,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Defines the CommentRemover utility class
*/
-#include "AssimpPCH.h"
#include "RemoveComments.h"
#include "ParsingUtils.h"
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Remove line comments from a file
void CommentRemover::RemoveLineComments(const char* szComment,
- char* szBuffer, char chReplacement /* = ' ' */)
+ 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;
- }
- ++szBuffer;
- }
+ // 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;
+ }
+ ++szBuffer;
+ }
}
// ------------------------------------------------------------------------------------------------
// Remove multi-line comments from a file
void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
- const char* szCommentEnd,char* szBuffer,
- char chReplacement)
+ 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;
- }
+ // 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
diff --git a/src/3rdparty/assimp/code/RemoveComments.h b/src/3rdparty/assimp/code/RemoveComments.h
index 8b162584e..856ed74bf 100644
--- a/src/3rdparty/assimp/code/RemoveComments.h
+++ b/src/3rdparty/assimp/code/RemoveComments.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,44 +44,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_REMOVE_COMMENTS_H_INC
#define AI_REMOVE_COMMENTS_H_INC
-#include "../include/assimp/ai_assert.h"
+#include <assimp/ai_assert.h>
+#include <assimp/defs.h>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** \brief Helper class to remove single and multi line comments from a file
- *
+ *
* Some mesh formats like MD5 have comments that are quite similar
* to those in C or C++ so this code has been moved to a separate
* module.
*/
class ASSIMP_API CommentRemover
{
- // class cannot be instanced
- CommentRemover() {}
+ // class cannot be instanced
+ CommentRemover() {}
public:
- //! Remove single-line comments. The end of a line is
- //! expected to be either NL or CR or NLCR.
- //! \param szComment The start sequence of the comment, e.g. "//"
- //! \param szBuffer Buffer to work with
- //! \param chReplacement Character to be used as replacement
- //! for commented lines. By default this is ' '
- static void RemoveLineComments(const char* szComment,
- char* szBuffer, char chReplacement = ' ');
+ //! Remove single-line comments. The end of a line is
+ //! expected to be either NL or CR or NLCR.
+ //! \param szComment The start sequence of the comment, e.g. "//"
+ //! \param szBuffer Buffer to work with
+ //! \param chReplacement Character to be used as replacement
+ //! for commented lines. By default this is ' '
+ static void RemoveLineComments(const char* szComment,
+ char* szBuffer, char chReplacement = ' ');
- //! Remove multi-line comments. The end of a line is
- //! expected to be either NL or CR or NLCR. Multi-line comments
- //! may not be nested (as in C).
- //! \param szCommentStart The start sequence of the comment, e.g. "/*"
- //! \param szCommentEnd The end sequence of the comment, e.g. "*/"
- //! \param szBuffer Buffer to work with
- //! \param chReplacement Character to be used as replacement
- //! for commented lines. By default this is ' '
- static void RemoveMultiLineComments(const char* szCommentStart,
- const char* szCommentEnd,char* szBuffer,
- char chReplacement = ' ');
+ //! Remove multi-line comments. The end of a line is
+ //! expected to be either NL or CR or NLCR. Multi-line comments
+ //! may not be nested (as in C).
+ //! \param szCommentStart The start sequence of the comment, e.g. "/*"
+ //! \param szCommentEnd The end sequence of the comment, e.g. "*/"
+ //! \param szBuffer Buffer to work with
+ //! \param chReplacement Character to be used as replacement
+ //! for commented lines. By default this is ' '
+ static void RemoveMultiLineComments(const char* szCommentStart,
+ const char* szCommentEnd,char* szBuffer,
+ char chReplacement = ' ');
};
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp b/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
index 9a93f150c..a3e61ae8d 100644
--- a/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
+++ b/src/3rdparty/assimp/code/RemoveRedundantMaterials.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,189 +25,192 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file RemoveRedundantMaterials.cpp
- * @brief Implementation of the "RemoveRedundantMaterials" post processing step
+ * @brief Implementation of the "RemoveRedundantMaterials" post processing step
*/
// internal headers
-#include "AssimpPCH.h"
+
#include "RemoveRedundantMaterials.h"
#include "ParsingUtils.h"
#include "ProcessHelper.h"
#include "MaterialSystem.h"
+#include <stdio.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RemoveRedundantMatsProcess::RemoveRedundantMatsProcess()
-{
- // nothing to do here
+: configFixedMaterials() {
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
+ return (pFlags & aiProcess_RemoveRedundantMaterials) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup import properties
void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp)
{
- // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST
- configFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,"");
+ // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ configFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,"");
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin");
-
- unsigned int redundantRemoved = 0, unreferencedRemoved = 0;
- if (pScene->mNumMaterials)
- {
- // Find out which materials are referenced by meshes
- std::vector<bool> abReferenced(pScene->mNumMaterials,false);
- for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
- abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
-
- // If a list of materials to be excluded was given, match the list with
- // our imported materials and 'salt' all positive matches to ensure that
- // we get unique hashes later.
- if (configFixedMaterials.length()) {
-
- std::list<std::string> strings;
- ConvertListToStrings(configFixedMaterials,strings);
-
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
- aiMaterial* mat = pScene->mMaterials[i];
-
- aiString name;
- mat->Get(AI_MATKEY_NAME,name);
-
- if (name.length) {
- std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data);
- if (it != strings.end()) {
-
- // Our brilliant 'salt': A single material property with ~ as first
- // character to mark it as internal and temporary.
- const int dummy = 1;
- ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0);
-
- // Keep this material even if no mesh references it
- abReferenced[i] = true;
- DefaultLogger::get()->debug(std::string("Found positive match in exclusion list: \'") + name.data + "\'");
- }
- }
- }
- }
-
- // TODO: reimplement this algorithm to work in-place
- unsigned int* aiMappingTable = new unsigned int[pScene->mNumMaterials];
- unsigned int iNewNum = 0;
-
- // Iterate through all materials and calculate a hash for them
- // store all hashes in a list and so a quick search whether
- // we do already have a specific hash. This allows us to
- // determine which materials are identical.
- uint32_t* aiHashes;
- aiHashes = new uint32_t[pScene->mNumMaterials];
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
- {
- // No mesh is referencing this material, remove it.
- if (!abReferenced[i]) {
- ++unreferencedRemoved;
- delete pScene->mMaterials[i];
- continue;
- }
-
- // Check all previously mapped materials for a matching hash.
- // On a match we can delete this material and just make it ref to the same index.
- uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]);
- for (unsigned int a = 0; a < i;++a)
- {
- if (abReferenced[a] && me == aiHashes[a]) {
- ++redundantRemoved;
- me = 0;
- aiMappingTable[i] = aiMappingTable[a];
- delete pScene->mMaterials[i];
- break;
- }
- }
- // This is a new material that is referenced, add to the map.
- if (me) {
- aiMappingTable[i] = iNewNum++;
- }
- }
- // If the new material count differs from the original,
- // we need to rebuild the material list and remap mesh material indexes.
- if (iNewNum != pScene->mNumMaterials) {
- aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
- ::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
- for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
- {
- // if the material is not referenced ... remove it
- if (!abReferenced[p]) {
- continue;
- }
-
- // generate new names for all modified materials
- const unsigned int idx = aiMappingTable[p];
- if (ppcMaterials[idx])
- {
- aiString sz;
- sz.length = ::sprintf(sz.data,"JoinedMaterial_#%i",p);
- ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
- }
- else
- ppcMaterials[idx] = pScene->mMaterials[p];
- }
- // update all material indices
- for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
- aiMesh* mesh = pScene->mMeshes[p];
- mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
- }
- // delete the old material list
- delete[] pScene->mMaterials;
- pScene->mMaterials = ppcMaterials;
- pScene->mNumMaterials = iNewNum;
- }
- // delete temporary storage
- delete[] aiHashes;
- delete[] aiMappingTable;
- }
- if (redundantRemoved == 0 && unreferencedRemoved == 0)
- {
- DefaultLogger::get()->debug("RemoveRedundantMatsProcess finished ");
- }
- else
- {
- char szBuffer[128]; // should be sufficiently large
- ::sprintf(szBuffer,"RemoveRedundantMatsProcess finished. Removed %i redundant and %i unused materials.",
- redundantRemoved,unreferencedRemoved);
- DefaultLogger::get()->info(szBuffer);
- }
+ DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin");
+
+ unsigned int redundantRemoved = 0, unreferencedRemoved = 0;
+ if (pScene->mNumMaterials)
+ {
+ // Find out which materials are referenced by meshes
+ std::vector<bool> abReferenced(pScene->mNumMaterials,false);
+ for (unsigned int i = 0;i < pScene->mNumMeshes;++i)
+ abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true;
+
+ // If a list of materials to be excluded was given, match the list with
+ // our imported materials and 'salt' all positive matches to ensure that
+ // we get unique hashes later.
+ if (configFixedMaterials.length()) {
+
+ std::list<std::string> strings;
+ ConvertListToStrings(configFixedMaterials,strings);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+ aiMaterial* mat = pScene->mMaterials[i];
+
+ aiString name;
+ mat->Get(AI_MATKEY_NAME,name);
+
+ if (name.length) {
+ std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data);
+ if (it != strings.end()) {
+
+ // Our brilliant 'salt': A single material property with ~ as first
+ // character to mark it as internal and temporary.
+ const int dummy = 1;
+ ((aiMaterial*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0);
+
+ // Keep this material even if no mesh references it
+ abReferenced[i] = true;
+ DefaultLogger::get()->debug(std::string("Found positive match in exclusion list: \'") + name.data + "\'");
+ }
+ }
+ }
+ }
+
+ // TODO: re-implement this algorithm to work in-place
+ unsigned int *aiMappingTable = new unsigned int[pScene->mNumMaterials];
+ for ( unsigned int i=0; i<pScene->mNumMaterials; i++ ) {
+ aiMappingTable[ i ] = 0;
+ }
+ unsigned int iNewNum = 0;
+
+ // Iterate through all materials and calculate a hash for them
+ // store all hashes in a list and so a quick search whether
+ // we do already have a specific hash. This allows us to
+ // determine which materials are identical.
+ uint32_t *aiHashes = new uint32_t[ pScene->mNumMaterials ];;
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+ {
+ // No mesh is referencing this material, remove it.
+ if (!abReferenced[i]) {
+ ++unreferencedRemoved;
+ delete pScene->mMaterials[i];
+ continue;
+ }
+
+ // Check all previously mapped materials for a matching hash.
+ // On a match we can delete this material and just make it ref to the same index.
+ uint32_t me = aiHashes[i] = ComputeMaterialHash(pScene->mMaterials[i]);
+ for (unsigned int a = 0; a < i;++a)
+ {
+ if (abReferenced[a] && me == aiHashes[a]) {
+ ++redundantRemoved;
+ me = 0;
+ aiMappingTable[i] = aiMappingTable[a];
+ delete pScene->mMaterials[i];
+ break;
+ }
+ }
+ // This is a new material that is referenced, add to the map.
+ if (me) {
+ aiMappingTable[i] = iNewNum++;
+ }
+ }
+ // If the new material count differs from the original,
+ // we need to rebuild the material list and remap mesh material indexes.
+ if (iNewNum != pScene->mNumMaterials) {
+ aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
+ ::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
+ for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
+ {
+ // if the material is not referenced ... remove it
+ if (!abReferenced[p]) {
+ continue;
+ }
+
+ // generate new names for all modified materials
+ const unsigned int idx = aiMappingTable[p];
+ if (ppcMaterials[idx]) {
+ aiString sz;
+ sz.length = ::ai_snprintf(sz.data,MAXLEN,"JoinedMaterial_#%u",p);
+ ((aiMaterial*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
+ } else {
+ ppcMaterials[idx] = pScene->mMaterials[p];
+ }
+ }
+ // update all material indices
+ for (unsigned int p = 0; p < pScene->mNumMeshes;++p) {
+ aiMesh* mesh = pScene->mMeshes[p];
+ ai_assert( NULL!=mesh );
+ mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex];
+ }
+ // delete the old material list
+ delete[] pScene->mMaterials;
+ pScene->mMaterials = ppcMaterials;
+ pScene->mNumMaterials = iNewNum;
+ }
+ // delete temporary storage
+ delete[] aiHashes;
+ delete[] aiMappingTable;
+ }
+ if (redundantRemoved == 0 && unreferencedRemoved == 0)
+ {
+ DefaultLogger::get()->debug("RemoveRedundantMatsProcess finished ");
+ }
+ else
+ {
+ char szBuffer[128]; // should be sufficiently large
+ ::ai_snprintf(szBuffer,128,"RemoveRedundantMatsProcess finished. Removed %u redundant and %u unused materials.",
+ redundantRemoved,unreferencedRemoved);
+ DefaultLogger::get()->info(szBuffer);
+ }
}
diff --git a/src/3rdparty/assimp/code/RemoveRedundantMaterials.h b/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
index a10634d55..60efad9a4 100644
--- a/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
+++ b/src/3rdparty/assimp/code/RemoveRedundantMaterials.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,80 +23,80 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file RemoveRedundantMaterials.h
- * @brief Defines a post processing step to remove redundant materials
+ * @brief Defines a post processing step to remove redundant materials
*/
#ifndef AI_REMOVEREDUNDANTMATERIALS_H_INC
#define AI_REMOVEREDUNDANTMATERIALS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
class RemoveRedundantMatsTest;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
-/** RemoveRedundantMatsProcess: Post-processing step to remove redundant
+/** RemoveRedundantMatsProcess: Post-processing step to remove redundant
* materials from the imported scene.
*/
class ASSIMP_API RemoveRedundantMatsProcess : public BaseProcess
{
public:
/// The default class constructor.
- RemoveRedundantMatsProcess();
+ RemoveRedundantMatsProcess();
/// The class destructor.
- ~RemoveRedundantMatsProcess();
+ ~RemoveRedundantMatsProcess();
public:
- // -------------------------------------------------------------------
- // Check whether step is active
- bool IsActive( unsigned int pFlags) const;
-
- // -------------------------------------------------------------------
- // Execute step on a given scene
- void Execute( aiScene* pScene);
-
- // -------------------------------------------------------------------
- // Setup import settings
- void SetupProperties(const Importer* pImp);
-
-
- // -------------------------------------------------------------------
- /** @brief Set list of fixed (unmutable) materials
- * @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
- */
- void SetFixedMaterialsString(const std::string& fixed = "") {
- configFixedMaterials = fixed;
- }
-
- // -------------------------------------------------------------------
- /** @brief Get list of fixed (unmutable) materials
- * @return See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
- */
- const std::string& GetFixedMaterialsString() const {
- return configFixedMaterials;
- }
+ // -------------------------------------------------------------------
+ // Check whether step is active
+ bool IsActive( unsigned int pFlags) const;
+
+ // -------------------------------------------------------------------
+ // Execute step on a given scene
+ void Execute( aiScene* pScene);
+
+ // -------------------------------------------------------------------
+ // Setup import settings
+ void SetupProperties(const Importer* pImp);
+
+
+ // -------------------------------------------------------------------
+ /** @brief Set list of fixed (unmutable) materials
+ * @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ */
+ void SetFixedMaterialsString(const std::string& fixed = "") {
+ configFixedMaterials = fixed;
+ }
+
+ // -------------------------------------------------------------------
+ /** @brief Get list of fixed (unmutable) materials
+ * @return See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
+ */
+ const std::string& GetFixedMaterialsString() const {
+ return configFixedMaterials;
+ }
private:
- //! Configuration option: list of all fixed materials
- std::string configFixedMaterials;
+ //! Configuration option: list of all fixed materials
+ std::string configFixedMaterials;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/RemoveVCProcess.cpp b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
index 7c4908fb2..473460452 100644
--- a/src/3rdparty/assimp/code/RemoveVCProcess.cpp
+++ b/src/3rdparty/assimp/code/RemoveVCProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -42,15 +42,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* any parts of the mesh structure from the imported data.
*/
-#include "AssimpPCH.h"
+
#include "RemoveVCProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
using namespace Assimp;
-
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
-RemoveVCProcess::RemoveVCProcess()
+RemoveVCProcess::RemoveVCProcess() :
+ configDeleteFlags()
+ , mScene()
{}
// ------------------------------------------------------------------------------------------------
@@ -62,7 +66,7 @@ RemoveVCProcess::~RemoveVCProcess()
// Returns whether the processing step is present in the given flag field.
bool RemoveVCProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_RemoveComponent) != 0;
+ return (pFlags & aiProcess_RemoveComponent) != 0;
}
// ------------------------------------------------------------------------------------------------
@@ -70,68 +74,68 @@ bool RemoveVCProcess::IsActive( unsigned int pFlags) const
template <typename T>
inline void ArrayDelete(T**& in, unsigned int& num)
{
- for (unsigned int i = 0; i < num; ++i)
- delete in[i];
+ for (unsigned int i = 0; i < num; ++i)
+ delete in[i];
- delete[] in;
- in = NULL;
- num = 0;
+ delete[] in;
+ in = NULL;
+ num = 0;
}
#if 0
// ------------------------------------------------------------------------------------------------
-// Updates the node graph - removes all nodes which have the "remove" flag set and the
+// Updates the node graph - removes all nodes which have the "remove" flag set and the
// "don't remove" flag not set. Nodes with meshes are never deleted.
bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
{
- bool b = false;
-
- std::list<aiNode*> mine;
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- {
- if(UpdateNodeGraph(node->mChildren[i],mine,false))
- b = true;
- }
-
- // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set,
- // so we can do a simple comparison against MSB here
- if (!root && AI_RC_UINT_MSB == node->mNumMeshes )
- {
- // this node needs to be removed
- if(node->mNumChildren)
- {
- childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
-
- // set all children to NULL to make sure they are not deleted when we delete ourself
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- node->mChildren[i] = NULL;
- }
- b = true;
- delete node;
- }
- else
- {
- AI_RC_UNMASK(node->mNumMeshes);
- childsOfParent.push_back(node);
-
- if (b)
- {
- // reallocate the array of our children here
- node->mNumChildren = (unsigned int)mine.size();
- aiNode** const children = new aiNode*[mine.size()];
- aiNode** ptr = children;
-
- for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
- it != end; ++it)
- {
- *ptr++ = *it;
- }
- delete[] node->mChildren;
- node->mChildren = children;
- return false;
- }
- }
- return b;
+ bool b = false;
+
+ std::list<aiNode*> mine;
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ {
+ if(UpdateNodeGraph(node->mChildren[i],mine,false))
+ b = true;
+ }
+
+ // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set,
+ // so we can do a simple comparison against MSB here
+ if (!root && AI_RC_UINT_MSB == node->mNumMeshes )
+ {
+ // this node needs to be removed
+ if(node->mNumChildren)
+ {
+ childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end());
+
+ // set all children to NULL to make sure they are not deleted when we delete ourself
+ for (unsigned int i = 0; i < node->mNumChildren;++i)
+ node->mChildren[i] = NULL;
+ }
+ b = true;
+ delete node;
+ }
+ else
+ {
+ AI_RC_UNMASK(node->mNumMeshes);
+ childsOfParent.push_back(node);
+
+ if (b)
+ {
+ // reallocate the array of our children here
+ node->mNumChildren = (unsigned int)mine.size();
+ aiNode** const children = new aiNode*[mine.size()];
+ aiNode** ptr = children;
+
+ for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end();
+ it != end; ++it)
+ {
+ *ptr++ = *it;
+ }
+ delete[] node->mChildren;
+ node->mChildren = children;
+ return false;
+ }
+ }
+ return b;
}
#endif
@@ -139,190 +143,190 @@ bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root)
// Executes the post processing step on the given imported data.
void RemoveVCProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("RemoveVCProcess begin");
- bool bHas = false; //,bMasked = false;
-
- mScene = pScene;
-
- // handle animations
- if ( configDeleteFlags & aiComponent_ANIMATIONS)
- {
-
- bHas = true;
- ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
- }
-
- // handle textures
- if ( configDeleteFlags & aiComponent_TEXTURES)
- {
- bHas = true;
- ArrayDelete(pScene->mTextures,pScene->mNumTextures);
- }
-
- // handle materials
- if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
- {
- bHas = true;
- for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
- delete pScene->mMaterials[i];
-
- pScene->mNumMaterials = 1;
- aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
- ai_assert(NULL != helper);
- helper->Clear();
-
- // gray
- aiColor3D clr(0.6f,0.6f,0.6f);
- helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
-
- // add a small ambient color value
- clr = aiColor3D(0.05f,0.05f,0.05f);
- helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
-
- aiString s;
- s.Set("Dummy_MaterialsRemoved");
- helper->AddProperty(&s,AI_MATKEY_NAME);
- }
-
- // handle light sources
- if ( configDeleteFlags & aiComponent_LIGHTS)
- {
- bHas = true;
- ArrayDelete(pScene->mLights,pScene->mNumLights);
- }
-
- // handle camneras
- if ( configDeleteFlags & aiComponent_CAMERAS)
- {
- bHas = true;
- ArrayDelete(pScene->mCameras,pScene->mNumCameras);
- }
-
- // handle meshes
- if (configDeleteFlags & aiComponent_MESHES)
- {
- bHas = true;
- ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
- }
- else
- {
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- {
- if( ProcessMesh( pScene->mMeshes[a]))
- bHas = true;
- }
- }
-
-
- // now check whether the result is still a full scene
- if (!pScene->mNumMeshes || !pScene->mNumMaterials)
- {
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
-
- // If we have no meshes anymore we should also clear another flag ...
- if (!pScene->mNumMeshes)
- pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
- }
-
- if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
- else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ...");
+ DefaultLogger::get()->debug("RemoveVCProcess begin");
+ bool bHas = false; //,bMasked = false;
+
+ mScene = pScene;
+
+ // handle animations
+ if ( configDeleteFlags & aiComponent_ANIMATIONS)
+ {
+
+ bHas = true;
+ ArrayDelete(pScene->mAnimations,pScene->mNumAnimations);
+ }
+
+ // handle textures
+ if ( configDeleteFlags & aiComponent_TEXTURES)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mTextures,pScene->mNumTextures);
+ }
+
+ // handle materials
+ if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials)
+ {
+ bHas = true;
+ for (unsigned int i = 1;i < pScene->mNumMaterials;++i)
+ delete pScene->mMaterials[i];
+
+ pScene->mNumMaterials = 1;
+ aiMaterial* helper = (aiMaterial*) pScene->mMaterials[0];
+ ai_assert(NULL != helper);
+ helper->Clear();
+
+ // gray
+ aiColor3D clr(0.6f,0.6f,0.6f);
+ helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+
+ // add a small ambient color value
+ clr = aiColor3D(0.05f,0.05f,0.05f);
+ helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString s;
+ s.Set("Dummy_MaterialsRemoved");
+ helper->AddProperty(&s,AI_MATKEY_NAME);
+ }
+
+ // handle light sources
+ if ( configDeleteFlags & aiComponent_LIGHTS)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mLights,pScene->mNumLights);
+ }
+
+ // handle camneras
+ if ( configDeleteFlags & aiComponent_CAMERAS)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mCameras,pScene->mNumCameras);
+ }
+
+ // handle meshes
+ if (configDeleteFlags & aiComponent_MESHES)
+ {
+ bHas = true;
+ ArrayDelete(pScene->mMeshes,pScene->mNumMeshes);
+ }
+ else
+ {
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if( ProcessMesh( pScene->mMeshes[a]))
+ bHas = true;
+ }
+ }
+
+
+ // now check whether the result is still a full scene
+ if (!pScene->mNumMeshes || !pScene->mNumMaterials)
+ {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag");
+
+ // If we have no meshes anymore we should also clear another flag ...
+ if (!pScene->mNumMeshes)
+ pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ }
+
+ if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done.");
+ else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ...");
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the step
void RemoveVCProcess::SetupProperties(const Importer* pImp)
{
- configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
- if (!configDeleteFlags)
- {
- DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
- }
+ configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0);
+ if (!configDeleteFlags)
+ {
+ DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero.");
+ }
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh)
{
- bool ret = false;
-
- // if all materials have been deleted let the material
- // index of the mesh point to the created default material
- if ( configDeleteFlags & aiComponent_MATERIALS)
- pMesh->mMaterialIndex = 0;
-
- // handle normals
- if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
- {
- delete[] pMesh->mNormals;
- pMesh->mNormals = NULL;
- ret = true;
- }
-
- // handle tangents and bitangents
- if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
- {
- delete[] pMesh->mTangents;
- pMesh->mTangents = NULL;
-
- delete[] pMesh->mBitangents;
- pMesh->mBitangents = NULL;
- ret = true;
- }
-
- // handle texture coordinates
- bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
- for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
- {
- if (!pMesh->mTextureCoords[i])break;
- if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
- {
- delete pMesh->mTextureCoords[i];
- pMesh->mTextureCoords[i] = NULL;
- ret = true;
-
- if (!b)
- {
- // collapse the rest of the array
- for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
- pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
-
- pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
- continue;
- }
- }
- ++i;
- }
-
- // handle vertex colors
- b = (0 != (configDeleteFlags & aiComponent_COLORS));
- for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
- {
- if (!pMesh->mColors[i])break;
- if (configDeleteFlags & aiComponent_COLORSn(i) || b)
- {
- delete pMesh->mColors[i];
- pMesh->mColors[i] = NULL;
- ret = true;
-
- if (!b)
- {
- // collapse the rest of the array
- for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
- pMesh->mColors[a-1] = pMesh->mColors[a];
-
- pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
- continue;
- }
- }
- ++i;
- }
-
- // handle bones
- if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
- {
- ArrayDelete(pMesh->mBones,pMesh->mNumBones);
- ret = true;
- }
- return ret;
+ bool ret = false;
+
+ // if all materials have been deleted let the material
+ // index of the mesh point to the created default material
+ if ( configDeleteFlags & aiComponent_MATERIALS)
+ pMesh->mMaterialIndex = 0;
+
+ // handle normals
+ if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals)
+ {
+ delete[] pMesh->mNormals;
+ pMesh->mNormals = NULL;
+ ret = true;
+ }
+
+ // handle tangents and bitangents
+ if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents)
+ {
+ delete[] pMesh->mTangents;
+ pMesh->mTangents = NULL;
+
+ delete[] pMesh->mBitangents;
+ pMesh->mBitangents = NULL;
+ ret = true;
+ }
+
+ // handle texture coordinates
+ bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS));
+ for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real)
+ {
+ if (!pMesh->mTextureCoords[i])break;
+ if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b)
+ {
+ delete [] pMesh->mTextureCoords[i];
+ pMesh->mTextureCoords[i] = NULL;
+ ret = true;
+
+ if (!b)
+ {
+ // collapse the rest of the array
+ for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a)
+ pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a];
+
+ pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL;
+ continue;
+ }
+ }
+ ++i;
+ }
+
+ // handle vertex colors
+ b = (0 != (configDeleteFlags & aiComponent_COLORS));
+ for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real)
+ {
+ if (!pMesh->mColors[i])break;
+ if (configDeleteFlags & aiComponent_COLORSn(i) || b)
+ {
+ delete pMesh->mColors[i];
+ pMesh->mColors[i] = NULL;
+ ret = true;
+
+ if (!b)
+ {
+ // collapse the rest of the array
+ for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a)
+ pMesh->mColors[a-1] = pMesh->mColors[a];
+
+ pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL;
+ continue;
+ }
+ }
+ ++i;
+ }
+
+ // handle bones
+ if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones)
+ {
+ ArrayDelete(pMesh->mBones,pMesh->mNumBones);
+ ret = true;
+ }
+ return ret;
}
diff --git a/src/3rdparty/assimp/code/RemoveVCProcess.h b/src/3rdparty/assimp/code/RemoveVCProcess.h
index e9f6be21b..a9173a815 100644
--- a/src/3rdparty/assimp/code/RemoveVCProcess.h
+++ b/src/3rdparty/assimp/code/RemoveVCProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_REMOVEVCPROCESS_H_INCLUDED
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
class RemoveVCProcessTest;
@@ -57,63 +57,63 @@ class ASSIMP_API RemoveVCProcess : public BaseProcess
{
public:
/// The default class constructor.
- RemoveVCProcess();
+ RemoveVCProcess();
/// The class destructor.
- ~RemoveVCProcess();
+ ~RemoveVCProcess();
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);
-
- // -------------------------------------------------------------------
- /** 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);
-
- // -------------------------------------------------------------------
- /** Manually setup the configuration flags for the step
- *
- * @param Bitwise combination of the #aiComponent enumerated values.
- */
- void SetDeleteFlags(unsigned int f)
- {
- configDeleteFlags = f;
- }
-
- // -------------------------------------------------------------------
- /** Query the current configuration.
- */
- unsigned int GetDeleteFlags() const
- {
- return configDeleteFlags;
- }
+ // -------------------------------------------------------------------
+ /** 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);
+
+ // -------------------------------------------------------------------
+ /** 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);
+
+ // -------------------------------------------------------------------
+ /** Manually setup the configuration flags for the step
+ *
+ * @param Bitwise combination of the #aiComponent enumerated values.
+ */
+ void SetDeleteFlags(unsigned int f)
+ {
+ configDeleteFlags = f;
+ }
+
+ // -------------------------------------------------------------------
+ /** Query the current configuration.
+ */
+ unsigned int GetDeleteFlags() const
+ {
+ return configDeleteFlags;
+ }
private:
- bool ProcessMesh (aiMesh* pcMesh);
+ bool ProcessMesh (aiMesh* pcMesh);
- /** Configuration flag
- */
- unsigned int configDeleteFlags;
+ /** Configuration flag
+ */
+ unsigned int configDeleteFlags;
- /** The scene we're working with
- */
- aiScene* mScene;
+ /** The scene we're working with
+ */
+ aiScene* mScene;
};
// ---------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/SGSpatialSort.cpp b/src/3rdparty/assimp/code/SGSpatialSort.cpp
index 999a1cf15..84061888e 100644
--- a/src/3rdparty/assimp/code/SGSpatialSort.cpp
+++ b/src/3rdparty/assimp/code/SGSpatialSort.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,25 +25,24 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file Implementation of the helper class to quickly find
-vertices close to a given position. Special implementation for
+/** @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 "AssimpPCH.h"
#include "SGSpatialSort.h"
using namespace Assimp;
@@ -52,118 +51,118 @@ 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();
+ // 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
+ // nothing to do here, everything destructs automatically
}
// ------------------------------------------------------------------------------------------------
void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index,
- unsigned int smoothingGroup)
+ unsigned int smoothingGroup)
{
- // store position by index and distance
- float distance = vPosition * mPlaneNormal;
- mPositions.push_back( Entry( index, vPosition,
- distance, 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());
+ // 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
+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 in this strange fashion because a simple clear() would also deallocate
- // the array which we want to avoid
- poResults.erase( poResults.begin(), poResults.end());
-
- // 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
-
- 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;
- }
- }
+ float dist = pPosition * mPlaneNormal;
+ float minDist = dist - pRadius, maxDist = dist + pRadius;
+
+ // clear the array in this strange fashion because a simple clear() would also deallocate
+ // the array which we want to avoid
+ poResults.erase( poResults.begin(), poResults.end());
+
+ // 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
+
+ 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;
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/SGSpatialSort.h b/src/3rdparty/assimp/code/SGSpatialSort.h
index a347244a6..59a5c37d6 100644
--- a/src/3rdparty/assimp/code/SGSpatialSort.h
+++ b/src/3rdparty/assimp/code/SGSpatialSort.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,34 +23,35 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** Small helper classes to optimise finding vertizes close to a given location
+/** Small helper classes to optimize finding vertices close to a given location
*/
#ifndef AI_D3DSSPATIALSORT_H_INC
#define AI_D3DSSPATIALSORT_H_INC
+#include <assimp/types.h>
#include <vector>
-#include "../include/assimp/types.h"
+#include <stdint.h>
-namespace Assimp {
+namespace Assimp {
// ----------------------------------------------------------------------------------
/** Specialized version of SpatialSort to support smoothing groups
- * This is used in by the 3DS, ASE and LWO loaders. 3DS and ASE share their
+ * This is used in by the 3DS, ASE and LWO loaders. 3DS and ASE share their
* normal computation code in SmoothingGroups.inl, the LWO loader has its own
* implementation to handle all details of its file format correctly.
*/
@@ -59,79 +60,79 @@ class SGSpatialSort
{
public:
- SGSpatialSort();
-
- // -------------------------------------------------------------------
- /** Construction from a given face array, handling smoothing groups
- * properly
- */
- SGSpatialSort(const std::vector<aiVector3D>& vPositions);
-
- // -------------------------------------------------------------------
- /** Add a vertex to the spatial sort
- * @param vPosition Vertex position to be added
- * @param index Index of the vrtex
- * @param smoothingGroup SmoothingGroup for this vertex
- */
- void Add(const aiVector3D& vPosition, unsigned int index,
- unsigned int smoothingGroup);
-
- // -------------------------------------------------------------------
- /** Prepare the spatial sorter for use. This step runs in O(logn)
- */
- void Prepare();
-
- /** Destructor */
- ~SGSpatialSort();
-
- // -------------------------------------------------------------------
- /** Returns an iterator for all positions close to the given position.
- * @param pPosition The position to look for vertices.
- * @param pSG Only included vertices with at least one shared smooth group
- * @param pRadius Maximal distance from the position a vertex may have
- * to be counted in.
- * @param poResults The container to store the indices of the found
- * positions. Will be emptied by the call so it may contain anything.
- * @param exactMatch Specifies whether smoothing groups are bit masks
- * (false) or integral values (true). In the latter case, a vertex
- * cannot belong to more than one smoothing group.
- * @return An iterator to iterate over all vertices in the given area.
- */
- // -------------------------------------------------------------------
- void FindPositions( const aiVector3D& pPosition, uint32_t pSG,
- float pRadius, std::vector<unsigned int>& poResults,
- bool exactMatch = false) const;
+ SGSpatialSort();
+
+ // -------------------------------------------------------------------
+ /** Construction from a given face array, handling smoothing groups
+ * properly
+ */
+ explicit SGSpatialSort(const std::vector<aiVector3D>& vPositions);
+
+ // -------------------------------------------------------------------
+ /** Add a vertex to the spatial sort
+ * @param vPosition Vertex position to be added
+ * @param index Index of the vrtex
+ * @param smoothingGroup SmoothingGroup for this vertex
+ */
+ void Add(const aiVector3D& vPosition, unsigned int index,
+ unsigned int smoothingGroup);
+
+ // -------------------------------------------------------------------
+ /** Prepare the spatial sorter for use. This step runs in O(logn)
+ */
+ void Prepare();
+
+ /** Destructor */
+ ~SGSpatialSort();
+
+ // -------------------------------------------------------------------
+ /** Returns an iterator for all positions close to the given position.
+ * @param pPosition The position to look for vertices.
+ * @param pSG Only included vertices with at least one shared smooth group
+ * @param pRadius Maximal distance from the position a vertex may have
+ * to be counted in.
+ * @param poResults The container to store the indices of the found
+ * positions. Will be emptied by the call so it may contain anything.
+ * @param exactMatch Specifies whether smoothing groups are bit masks
+ * (false) or integral values (true). In the latter case, a vertex
+ * cannot belong to more than one smoothing group.
+ * @return An iterator to iterate over all vertices in the given area.
+ */
+ // -------------------------------------------------------------------
+ void FindPositions( const aiVector3D& pPosition, uint32_t pSG,
+ float pRadius, std::vector<unsigned int>& poResults,
+ bool exactMatch = false) const;
protected:
- /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
- aiVector3D mPlaneNormal;
-
- // -------------------------------------------------------------------
- /** An entry in a spatially sorted position array. Consists of a
- * vertex index, its position and its precalculated distance from
- * the reference plane */
- // -------------------------------------------------------------------
- struct Entry
- {
- unsigned int mIndex; ///< The vertex referred by this entry
- aiVector3D mPosition; ///< Position
- uint32_t mSmoothGroups;
- float mDistance; ///< Distance of this vertex to the sorting plane
-
- Entry() { /** intentionally not initialized.*/ }
- Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG)
- :
- mIndex( pIndex),
- mPosition( pPosition),
- mSmoothGroups (pSG),
- mDistance( pDistance)
- { }
-
- bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
- };
-
- // all positions, sorted by distance to the sorting plane
- std::vector<Entry> mPositions;
+ /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
+ aiVector3D mPlaneNormal;
+
+ // -------------------------------------------------------------------
+ /** An entry in a spatially sorted position array. Consists of a
+ * vertex index, its position and its precalculated distance from
+ * the reference plane */
+ // -------------------------------------------------------------------
+ struct Entry
+ {
+ unsigned int mIndex; ///< The vertex referred by this entry
+ aiVector3D mPosition; ///< Position
+ uint32_t mSmoothGroups;
+ float mDistance; ///< Distance of this vertex to the sorting plane
+
+ Entry() { /** intentionally not initialized.*/ }
+ Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG)
+ :
+ mIndex( pIndex),
+ mPosition( pPosition),
+ mSmoothGroups (pSG),
+ mDistance( pDistance)
+ { }
+
+ bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
+ };
+
+ // all positions, sorted by distance to the sorting plane
+ std::vector<Entry> mPositions;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/SIBImporter.cpp b/src/3rdparty/assimp/code/SIBImporter.cpp
new file mode 100644
index 000000000..b972f28d6
--- /dev/null
+++ b/src/3rdparty/assimp/code/SIBImporter.cpp
@@ -0,0 +1,926 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+/** @file SIBImporter.cpp
+ * @brief Implementation of the SIB importer class.
+ *
+ * The Nevercenter Silo SIB format is undocumented.
+ * All details here have been reverse engineered from
+ * studying the binary files output by Silo.
+ *
+ * Nevertheless, this implementation is reasonably complete.
+ */
+
+
+#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
+
+// internal headers
+#include "SIBImporter.h"
+#include "ByteSwapper.h"
+#include "StreamReader.h"
+#include "TinyFormatter.h"
+#include "../contrib/ConvertUTF/ConvertUTF.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+ "Silo SIB Importer",
+ "Richard Mitton (http://www.codersnotes.com/about)",
+ "",
+ "Does not apply subdivision.",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0, 0,
+ 0, 0,
+ "sib"
+};
+
+struct SIBChunk
+{
+ uint32_t Tag;
+ uint32_t Size;
+} PACK_STRUCT;
+
+enum { POS, NRM, UV, N };
+
+typedef std::pair<uint32_t, uint32_t> SIBPair;
+static SIBPair makePair(uint32_t a, uint32_t b) { return (a<b) ? SIBPair(a, b) : SIBPair(b, a); }
+
+struct SIBEdge
+{
+ uint32_t faceA, faceB;
+ bool creased;
+};
+
+struct SIBMesh
+{
+ aiMatrix4x4 axis;
+ uint32_t numPts;
+ std::vector<aiVector3D> pos, nrm, uv;
+ std::vector<uint32_t> idx;
+ std::vector<uint32_t> faceStart;
+ std::vector<uint32_t> mtls;
+ std::vector<SIBEdge> edges;
+ std::map<SIBPair, uint32_t> edgeMap;
+};
+
+struct SIBObject
+{
+ aiString name;
+ aiMatrix4x4 axis;
+ size_t meshIdx, meshCount;
+};
+
+struct SIB
+{
+ std::vector<aiMaterial*> mtls;
+ std::vector<aiMesh*> meshes;
+ std::vector<aiLight*> lights;
+ std::vector<SIBObject> objs, insts;
+};
+
+// ------------------------------------------------------------------------------------------------
+static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB)
+{
+ SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA);
+ std::map<SIBPair, uint32_t>::iterator it = mesh->edgeMap.find(pair);
+ if (it != mesh->edgeMap.end())
+ return mesh->edges[it->second];
+
+ SIBEdge edge;
+ edge.creased = false;
+ edge.faceA = edge.faceB = 0xffffffff;
+ mesh->edgeMap[pair] = mesh->edges.size();
+ mesh->edges.push_back(edge);
+ return mesh->edges.back();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Helpers for reading chunked data.
+
+#define TAG(A,B,C,D) ((A << 24) | (B << 16) | (C << 8) | D)
+
+static SIBChunk ReadChunk(StreamReaderLE* stream)
+{
+ SIBChunk chunk;
+ chunk.Tag = stream->GetU4();
+ chunk.Size = stream->GetU4();
+ if (chunk.Size > stream->GetRemainingSizeToLimit())
+ DefaultLogger::get()->error("SIB: Chunk overflow");
+ ByteSwap::Swap4(&chunk.Tag);
+ return chunk;
+}
+
+static aiColor3D ReadColor(StreamReaderLE* stream)
+{
+ float r = stream->GetF4();
+ float g = stream->GetF4();
+ float b = stream->GetF4();
+ stream->GetU4(); // Colors have an unused(?) 4th component.
+ return aiColor3D(r, g, b);
+}
+
+static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk)
+{
+ char temp[5] = {
+ static_cast<char>(( chunk.Tag>>24 ) & 0xff),
+ static_cast<char>(( chunk.Tag>>16 ) & 0xff),
+ static_cast<char>(( chunk.Tag>>8 ) & 0xff),
+ static_cast<char>(chunk.Tag & 0xff), '\0'
+ };
+
+ DefaultLogger::get()->warn((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk."));
+}
+
+// Reads a UTF-16LE string and returns it at UTF-8.
+static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
+{
+ // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
+ UTF16* temp = new UTF16[numWChars];
+ UTF8* str = new UTF8[numWChars * 4 + 1];
+ for (uint32_t n=0;n<numWChars;n++)
+ temp[n] = stream->GetU2();
+
+ // Convert it and NUL-terminate.
+ const UTF16 *start = temp, *end = temp + numWChars;
+ UTF8 *dest = str, *limit = str + numWChars*4;
+ ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
+ *dest = '\0';
+
+ // Return the final string.
+ aiString result = aiString((const char *)str);
+ delete[] str;
+ delete[] temp;
+ return result;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+SIBImporter::SIBImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+SIBImporter::~SIBImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file.
+bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
+{
+ return SimpleExtensionCheck(pFile, "sib");
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc* SIBImporter::GetInfo () const
+{
+ return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count)
+{
+ mesh->pos.resize(count);
+
+ for (uint32_t n=0;n<count;n++) {
+ mesh->pos[n].x = stream->GetF4();
+ mesh->pos[n].y = stream->GetF4();
+ mesh->pos[n].z = stream->GetF4();
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream)
+{
+ uint32_t ptIdx = 0;
+ while (stream->GetRemainingSizeToLimit() > 0)
+ {
+ uint32_t numPoints = stream->GetU4();
+
+ // Store room for the N index channels, plus the point count.
+ size_t pos = mesh->idx.size() + 1;
+ mesh->idx.resize(pos + numPoints*N);
+ mesh->idx[pos-1] = numPoints;
+ uint32_t *idx = &mesh->idx[pos];
+
+ mesh->faceStart.push_back(pos-1);
+ mesh->mtls.push_back(0);
+
+ // Read all the position data.
+ // UV/normals will be supplied later.
+ // Positions are supplied indexed already, so we preserve that
+ // mapping. UVs are supplied uniquely, so we allocate unique indices.
+ for (uint32_t n=0;n<numPoints;n++,idx+=N,ptIdx++)
+ {
+ uint32_t p = stream->GetU4();
+ if (p >= mesh->pos.size())
+ throw DeadlyImportError("Vertex index is out of range.");
+ idx[POS] = p;
+ idx[NRM] = ptIdx;
+ idx[UV] = ptIdx;
+ }
+ }
+
+ // Allocate data channels for normals/UVs.
+ mesh->nrm.resize(ptIdx, aiVector3D(0,0,0));
+ mesh->uv.resize(ptIdx, aiVector3D(0,0,0));
+
+ mesh->numPts = ptIdx;
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream)
+{
+ while (stream->GetRemainingSizeToLimit() > 0)
+ {
+ uint32_t faceIdx = stream->GetU4();
+ uint32_t numPoints = stream->GetU4();
+
+ if (faceIdx >= mesh->faceStart.size())
+ throw DeadlyImportError("Invalid face index.");
+
+ uint32_t pos = mesh->faceStart[faceIdx];
+ uint32_t *idx = &mesh->idx[pos + 1];
+
+ for (uint32_t n=0;n<numPoints;n++,idx+=N)
+ {
+ uint32_t id = idx[UV];
+ mesh->uv[id].x = stream->GetF4();
+ mesh->uv[id].y = stream->GetF4();
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream)
+{
+ // Material assignments are stored run-length encoded.
+ // Also, we add 1 to each material so that we can use mtl #0
+ // as the default material.
+ uint32_t prevFace = stream->GetU4();
+ uint32_t prevMtl = stream->GetU4() + 1;
+ while (stream->GetRemainingSizeToLimit() > 0)
+ {
+ uint32_t face = stream->GetU4();
+ uint32_t mtl = stream->GetU4() + 1;
+ while (prevFace < face)
+ {
+ if (prevFace >= mesh->mtls.size())
+ throw DeadlyImportError("Invalid face index.");
+ mesh->mtls[prevFace++] = prevMtl;
+ }
+
+ prevFace = face;
+ prevMtl = mtl;
+ }
+
+ while (prevFace < mesh->mtls.size())
+ mesh->mtls[prevFace++] = prevMtl;
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream)
+{
+ axis.a4 = stream->GetF4();
+ axis.b4 = stream->GetF4();
+ axis.c4 = stream->GetF4();
+ axis.d4 = 1;
+ axis.a1 = stream->GetF4();
+ axis.b1 = stream->GetF4();
+ axis.c1 = stream->GetF4();
+ axis.d1 = 0;
+ axis.a2 = stream->GetF4();
+ axis.b2 = stream->GetF4();
+ axis.c2 = stream->GetF4();
+ axis.d2 = 0;
+ axis.a3 = stream->GetF4();
+ axis.b3 = stream->GetF4();
+ axis.c3 = stream->GetF4();
+ axis.d3 = 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream)
+{
+ while (stream->GetRemainingSizeToLimit() > 0)
+ {
+ uint32_t posA = stream->GetU4();
+ uint32_t posB = stream->GetU4();
+ GetEdge(mesh, posA, posB);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream)
+{
+ while (stream->GetRemainingSizeToLimit() > 0)
+ {
+ uint32_t edge = stream->GetU4();
+ if (edge >= mesh->edges.size())
+ throw DeadlyImportError("SIB: Invalid edge index.");
+ mesh->edges[edge].creased = true;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ConnectFaces(SIBMesh* mesh)
+{
+ // Find faces connected to each edge.
+ size_t numFaces = mesh->faceStart.size();
+ for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
+ {
+ uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
+ uint32_t numPoints = *idx++;
+ uint32_t prev = idx[(numPoints-1)*N+POS];
+
+ for (uint32_t i=0;i<numPoints;i++,idx+=N)
+ {
+ uint32_t next = idx[POS];
+
+ // Find this edge.
+ SIBEdge& edge = GetEdge(mesh, prev, next);
+
+ // Link this face onto it.
+ // This gives potentially undesirable normals when used
+ // with non-2-manifold surfaces, but then so does Silo to begin with.
+ if (edge.faceA == 0xffffffff)
+ edge.faceA = faceIdx;
+ else
+ edge.faceB = faceIdx;
+
+ prev = next;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_t pos,
+ const std::vector<aiVector3D>& faceNormals)
+{
+ // Creased edges complicate this. We need to find the start/end range of the
+ // ring of faces that touch this position.
+ // We do this in two passes. The first pass is to find the end of the range,
+ // the second is to work backwards to the start and calculate the final normal.
+ aiVector3D vtxNormal;
+ for (int pass=0;pass<2;pass++)
+ {
+ vtxNormal = aiVector3D(0, 0, 0);
+ uint32_t startFaceIdx = faceIdx;
+ uint32_t prevFaceIdx = faceIdx;
+
+ // Process each connected face.
+ while (true)
+ {
+ // Accumulate the face normal.
+ vtxNormal += faceNormals[faceIdx];
+
+ uint32_t nextFaceIdx = 0xffffffff;
+
+ // Move to the next edge sharing this position.
+ uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
+ uint32_t numPoints = *idx++;
+ uint32_t posA = idx[(numPoints-1)*N+POS];
+ for (uint32_t n=0;n<numPoints;n++,idx+=N)
+ {
+ uint32_t posB = idx[POS];
+
+ // Test if this edge shares our target position.
+ if (posA == pos || posB == pos)
+ {
+ SIBEdge& edge = GetEdge(mesh, posA, posB);
+
+ // Move to whichever side we didn't just come from.
+ if (!edge.creased) {
+ if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx)
+ nextFaceIdx = edge.faceA;
+ else if (edge.faceB != prevFaceIdx && edge.faceB != faceIdx)
+ nextFaceIdx = edge.faceB;
+ }
+ }
+
+ posA = posB;
+ }
+
+ // Stop once we hit either an creased/unconnected edge, or we
+ // wrapped around and hit our start point.
+ if (nextFaceIdx == 0xffffffff || nextFaceIdx == startFaceIdx)
+ break;
+
+ prevFaceIdx = faceIdx;
+ faceIdx = nextFaceIdx;
+ }
+ }
+
+ // Normalize it.
+ float len = vtxNormal.Length();
+ if (len > 0.000000001f)
+ vtxNormal /= len;
+ return vtxNormal;
+}
+
+// ------------------------------------------------------------------------------------------------
+static void CalculateNormals(SIBMesh* mesh)
+{
+ size_t numFaces = mesh->faceStart.size();
+
+ // Calculate face normals.
+ std::vector<aiVector3D> faceNormals(numFaces);
+ for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
+ {
+ uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
+ uint32_t numPoints = *idx++;
+
+ aiVector3D faceNormal(0, 0, 0);
+
+ uint32_t *prev = &idx[(numPoints-1)*N];
+
+ for (uint32_t i=0;i<numPoints;i++)
+ {
+ uint32_t *next = &idx[i*N];
+
+ faceNormal += mesh->pos[prev[POS]] ^ mesh->pos[next[POS]];
+ prev = next;
+ }
+
+ faceNormals[faceIdx] = faceNormal;
+ }
+
+ // Calculate vertex normals.
+ for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
+ {
+ uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
+ uint32_t numPoints = *idx++;
+
+ for (uint32_t i=0;i<numPoints;i++)
+ {
+ uint32_t pos = idx[i*N+POS];
+ uint32_t nrm = idx[i*N+NRM];
+ aiVector3D vtxNorm = CalculateVertexNormal(mesh, faceIdx, pos, faceNormals);
+ mesh->nrm[nrm] = vtxNorm;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+struct TempMesh
+{
+ std::vector<aiVector3D> vtx;
+ std::vector<aiVector3D> nrm;
+ std::vector<aiVector3D> uv;
+ std::vector<aiFace> faces;
+};
+
+static void ReadShape(SIB* sib, StreamReaderLE* stream)
+{
+ SIBMesh smesh;
+ aiString name;
+
+ while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
+ {
+ SIBChunk chunk = ReadChunk(stream);
+ unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
+
+ switch (chunk.Tag)
+ {
+ case TAG('M','I','R','P'): break; // mirror plane maybe?
+ case TAG('I','M','R','P'): break; // instance mirror? (not supported here yet)
+ case TAG('D','I','N','F'): break; // display info, not needed
+ case TAG('P','I','N','F'): break; // ?
+ case TAG('V','M','I','R'): break; // ?
+ case TAG('F','M','I','R'): break; // ?
+ case TAG('T','X','S','M'): break; // ?
+ case TAG('F','A','H','S'): break; // ?
+ case TAG('V','R','T','S'): ReadVerts(&smesh, stream, chunk.Size/12); break;
+ case TAG('F','A','C','S'): ReadFaces(&smesh, stream); break;
+ case TAG('F','T','V','S'): ReadUVs(&smesh, stream); break;
+ case TAG('S','N','A','M'): name = ReadString(stream, chunk.Size/2); break;
+ case TAG('F','A','M','A'): ReadMtls(&smesh, stream); break;
+ case TAG('A','X','I','S'): ReadAxis(smesh.axis, stream); break;
+ case TAG('E','D','G','S'): ReadEdges(&smesh, stream); break;
+ case TAG('E','C','R','S'): ReadCreases(&smesh, stream); break;
+ default: UnknownChunk(stream, chunk); break;
+ }
+
+ stream->SetCurrentPos(stream->GetReadLimit());
+ stream->SetReadLimit(oldLimit);
+ }
+
+ assert(smesh.faceStart.size() == smesh.mtls.size()); // sanity check
+
+ // Silo doesn't store any normals in the file - we need to compute
+ // them ourselves. We can't let AssImp handle it as AssImp doesn't
+ // know about our creased edges.
+ ConnectFaces(&smesh);
+ CalculateNormals(&smesh);
+
+ // Construct the transforms.
+ aiMatrix4x4 worldToLocal = smesh.axis;
+ worldToLocal.Inverse();
+ aiMatrix4x4 worldToLocalN = worldToLocal;
+ worldToLocalN.a4 = worldToLocalN.b4 = worldToLocalN.c4 = 0.0f;
+ worldToLocalN.Inverse().Transpose();
+
+ // Allocate final mesh data.
+ // We'll allocate one mesh for each material. (we'll strip unused ones after)
+ std::vector<TempMesh> meshes(sib->mtls.size());
+
+ // Un-index the source data and apply to each vertex.
+ for (unsigned fi=0;fi<smesh.faceStart.size();fi++)
+ {
+ uint32_t start = smesh.faceStart[fi];
+ uint32_t mtl = smesh.mtls[fi];
+ uint32_t *idx = &smesh.idx[start];
+
+ if (mtl >= meshes.size())
+ {
+ DefaultLogger::get()->error("SIB: Face material index is invalid.");
+ mtl = 0;
+ }
+
+ TempMesh& dest = meshes[mtl];
+
+ aiFace face;
+ face.mNumIndices = *idx++;
+ face.mIndices = new unsigned[face.mNumIndices];
+ for (unsigned pt=0;pt<face.mNumIndices;pt++,idx+=N)
+ {
+ size_t vtxIdx = dest.vtx.size();
+ face.mIndices[pt] = vtxIdx;
+
+ // De-index it. We don't need to validate here as
+ // we did it when creating the data.
+ aiVector3D pos = smesh.pos[idx[POS]];
+ aiVector3D nrm = smesh.nrm[idx[NRM]];
+ aiVector3D uv = smesh.uv[idx[UV]];
+
+ // The verts are supplied in world-space, so let's
+ // transform them back into the local space of this mesh:
+ pos = worldToLocal * pos;
+ nrm = worldToLocalN * nrm;
+
+ dest.vtx.push_back(pos);
+ dest.nrm.push_back(nrm);
+ dest.uv.push_back(uv);
+ }
+ dest.faces.push_back(face);
+ }
+
+ SIBObject obj;
+ obj.name = name;
+ obj.axis = smesh.axis;
+ obj.meshIdx = sib->meshes.size();
+
+ // Now that we know the size of everything,
+ // we can build the final one-material-per-mesh data.
+ for (size_t n=0;n<meshes.size();n++)
+ {
+ TempMesh& src = meshes[n];
+ if (src.faces.empty())
+ continue;
+
+ aiMesh* mesh = new aiMesh;
+ mesh->mName = name;
+ mesh->mNumFaces = src.faces.size();
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+ mesh->mNumVertices = src.vtx.size();
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+ mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+ mesh->mNumUVComponents[0] = 2;
+ mesh->mMaterialIndex = n;
+
+ for (unsigned i=0;i<mesh->mNumVertices;i++)
+ {
+ mesh->mVertices[i] = src.vtx[i];
+ mesh->mNormals[i] = src.nrm[i];
+ mesh->mTextureCoords[0][i] = src.uv[i];
+ }
+ for (unsigned i=0;i<mesh->mNumFaces;i++)
+ {
+ mesh->mFaces[i] = src.faces[i];
+ }
+
+ sib->meshes.push_back(mesh);
+ }
+
+ obj.meshCount = sib->meshes.size() - obj.meshIdx;
+ sib->objs.push_back(obj);
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadMaterial(SIB* sib, StreamReaderLE* stream)
+{
+ aiColor3D diff = ReadColor(stream);
+ aiColor3D ambi = ReadColor(stream);
+ aiColor3D spec = ReadColor(stream);
+ aiColor3D emis = ReadColor(stream);
+ float shiny = (float)stream->GetU4();
+
+ uint32_t nameLen = stream->GetU4();
+ aiString name = ReadString(stream, nameLen/2);
+ uint32_t texLen = stream->GetU4();
+ aiString tex = ReadString(stream, texLen/2);
+
+ aiMaterial* mtl = new aiMaterial();
+ mtl->AddProperty(&diff, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mtl->AddProperty(&ambi, 1, AI_MATKEY_COLOR_AMBIENT);
+ mtl->AddProperty(&spec, 1, AI_MATKEY_COLOR_SPECULAR);
+ mtl->AddProperty(&emis, 1, AI_MATKEY_COLOR_EMISSIVE);
+ mtl->AddProperty(&shiny, 1, AI_MATKEY_SHININESS);
+ mtl->AddProperty(&name, AI_MATKEY_NAME);
+ if (tex.length > 0) {
+ mtl->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ mtl->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(0));
+ }
+
+ sib->mtls.push_back(mtl);
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
+{
+ uint32_t type = stream->GetU4();
+ switch (type) {
+ case 0: light->mType = aiLightSource_POINT; break;
+ case 1: light->mType = aiLightSource_SPOT; break;
+ case 2: light->mType = aiLightSource_DIRECTIONAL; break;
+ default: light->mType = aiLightSource_UNDEFINED; break;
+ }
+
+ light->mPosition.x = stream->GetF4();
+ light->mPosition.y = stream->GetF4();
+ light->mPosition.z = stream->GetF4();
+ light->mDirection.x = stream->GetF4();
+ light->mDirection.y = stream->GetF4();
+ light->mDirection.z = stream->GetF4();
+ light->mColorDiffuse = ReadColor(stream);
+ light->mColorAmbient = ReadColor(stream);
+ light->mColorSpecular = ReadColor(stream);
+ float spotExponent = stream->GetF4();
+ float spotCutoff = stream->GetF4();
+ light->mAttenuationConstant = stream->GetF4();
+ light->mAttenuationLinear = stream->GetF4();
+ light->mAttenuationQuadratic = stream->GetF4();
+
+ // Silo uses the OpenGL default lighting model for it's
+ // spot cutoff/exponent. AssImp unfortunately, does not.
+ // Let's try and approximate it by solving for the
+ // 99% and 1% percentiles.
+ // OpenGL: I = cos(angle)^E
+ // Solving: angle = acos(I^(1/E))
+ float E = 1.0f / std::max(spotExponent, 0.00001f);
+ float inner = acosf(powf(0.99f, E));
+ float outer = acosf(powf(0.01f, E));
+
+ // Apply the cutoff.
+ outer = std::min(outer, AI_DEG_TO_RAD(spotCutoff));
+
+ light->mAngleInnerCone = std::min(inner, outer);
+ light->mAngleOuterCone = outer;
+}
+
+static void ReadLight(SIB* sib, StreamReaderLE* stream)
+{
+ aiLight* light = new aiLight();
+
+ while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
+ {
+ SIBChunk chunk = ReadChunk(stream);
+ unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
+
+ switch (chunk.Tag)
+ {
+ case TAG('L','N','F','O'): ReadLightInfo(light, stream); break;
+ case TAG('S','N','A','M'): light->mName = ReadString(stream, chunk.Size/2); break;
+ default: UnknownChunk(stream, chunk); break;
+ }
+
+ stream->SetCurrentPos(stream->GetReadLimit());
+ stream->SetReadLimit(oldLimit);
+ }
+
+ sib->lights.push_back(light);
+}
+
+// ------------------------------------------------------------------------------------------------
+static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream)
+{
+ aiMatrix4x4 scale;
+ scale.a1 = stream->GetF4();
+ scale.b1 = stream->GetF4();
+ scale.c1 = stream->GetF4();
+ scale.d1 = stream->GetF4();
+ scale.a2 = stream->GetF4();
+ scale.b2 = stream->GetF4();
+ scale.c2 = stream->GetF4();
+ scale.d2 = stream->GetF4();
+ scale.a3 = stream->GetF4();
+ scale.b3 = stream->GetF4();
+ scale.c3 = stream->GetF4();
+ scale.d3 = stream->GetF4();
+ scale.a4 = stream->GetF4();
+ scale.b4 = stream->GetF4();
+ scale.c4 = stream->GetF4();
+ scale.d4 = stream->GetF4();
+
+ axis = axis * scale;
+}
+
+static void ReadInstance(SIB* sib, StreamReaderLE* stream)
+{
+ SIBObject inst;
+ uint32_t shapeIndex = 0;
+
+ while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
+ {
+ SIBChunk chunk = ReadChunk(stream);
+ unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
+
+ switch (chunk.Tag)
+ {
+ case TAG('D','I','N','F'): break; // display info, not needed
+ case TAG('P','I','N','F'): break; // ?
+ case TAG('A','X','I','S'): ReadAxis(inst.axis, stream); break;
+ case TAG('I','N','S','I'): shapeIndex = stream->GetU4(); break;
+ case TAG('S','M','T','X'): ReadScale(inst.axis, stream); break;
+ case TAG('S','N','A','M'): inst.name = ReadString(stream, chunk.Size/2); break;
+ default: UnknownChunk(stream, chunk); break;
+ }
+
+ stream->SetCurrentPos(stream->GetReadLimit());
+ stream->SetReadLimit(oldLimit);
+ }
+
+ if (shapeIndex >= sib->objs.size())
+ throw DeadlyImportError("SIB: Invalid shape index.");
+
+ const SIBObject& src = sib->objs[shapeIndex];
+ inst.meshIdx = src.meshIdx;
+ inst.meshCount = src.meshCount;
+ sib->insts.push_back(inst);
+}
+
+// ------------------------------------------------------------------------------------------------
+static void CheckVersion(StreamReaderLE* stream)
+{
+ uint32_t version = stream->GetU4();
+ if (version != 1)
+ throw DeadlyImportError("SIB: Unsupported file version.");
+}
+
+static void ReadScene(SIB* sib, StreamReaderLE* stream)
+{
+ // Parse each chunk in turn.
+ while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
+ {
+ SIBChunk chunk = ReadChunk(stream);
+ unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
+
+ switch (chunk.Tag)
+ {
+ case TAG('H','E','A','D'): CheckVersion(stream); break;
+ case TAG('S','H','A','P'): ReadShape(sib, stream); break;
+ case TAG('G','R','P','S'): break; // group assignment, we don't import this
+ case TAG('T','E','X','P'): break; // ?
+ case TAG('I','N','S','T'): ReadInstance(sib, stream); break;
+ case TAG('M','A','T','R'): ReadMaterial(sib, stream); break;
+ case TAG('L','G','H','T'): ReadLight(sib, stream); break;
+ default: UnknownChunk(stream, chunk); break;
+ }
+
+ stream->SetCurrentPos(stream->GetReadLimit());
+ stream->SetReadLimit(oldLimit);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void SIBImporter::InternReadFile(const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
+{
+ StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
+
+ // We should have at least one chunk
+ if (stream.GetRemainingSize() < 16)
+ throw DeadlyImportError("SIB file is either empty or corrupt: " + pFile);
+
+ SIB sib;
+
+ // Default material.
+ aiMaterial* defmtl = new aiMaterial;
+ aiString defname = aiString(AI_DEFAULT_MATERIAL_NAME);
+ defmtl->AddProperty(&defname, AI_MATKEY_NAME);
+ sib.mtls.push_back(defmtl);
+
+ // Read it all.
+ ReadScene(&sib, &stream);
+
+ // Join the instances and objects together.
+ size_t firstInst = sib.objs.size();
+ sib.objs.insert(sib.objs.end(), sib.insts.begin(), sib.insts.end());
+ sib.insts.clear();
+
+ // Transfer to the aiScene.
+ pScene->mNumMaterials = sib.mtls.size();
+ pScene->mNumMeshes = sib.meshes.size();
+ pScene->mNumLights = sib.lights.size();
+ pScene->mMaterials = pScene->mNumMaterials ? new aiMaterial*[pScene->mNumMaterials] : NULL;
+ pScene->mMeshes = pScene->mNumMeshes ? new aiMesh*[pScene->mNumMeshes] : NULL;
+ pScene->mLights = pScene->mNumLights ? new aiLight*[pScene->mNumLights] : NULL;
+ if (pScene->mNumMaterials)
+ memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial*) * pScene->mNumMaterials);
+ if (pScene->mNumMeshes)
+ memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh*) * pScene->mNumMeshes);
+ if (pScene->mNumLights)
+ memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight*) * pScene->mNumLights);
+
+ // Construct the root node.
+ size_t childIdx = 0;
+ aiNode *root = new aiNode();
+ root->mName.Set("<SIBRoot>");
+ root->mNumChildren = sib.objs.size() + sib.lights.size();
+ root->mChildren = root->mNumChildren ? new aiNode*[root->mNumChildren] : NULL;
+ pScene->mRootNode = root;
+
+ // Add nodes for each object.
+ for (size_t n=0;n<sib.objs.size();n++)
+ {
+ SIBObject& obj = sib.objs[n];
+ aiNode* node = new aiNode;
+ root->mChildren[childIdx++] = node;
+ node->mName = obj.name;
+ node->mParent = root;
+ node->mTransformation = obj.axis;
+
+ node->mNumMeshes = obj.meshCount;
+ node->mMeshes = node->mNumMeshes ? new unsigned[node->mNumMeshes] : NULL;
+ for (unsigned i=0;i<node->mNumMeshes;i++)
+ node->mMeshes[i] = obj.meshIdx + i;
+
+ // Mark instanced objects as being so.
+ if (n >= firstInst)
+ {
+ node->mMetaData = new aiMetadata;
+ node->mMetaData->mNumProperties = 1;
+ node->mMetaData->mKeys = new aiString[1];
+ node->mMetaData->mValues = new aiMetadataEntry[1];
+ node->mMetaData->Set(0, "IsInstance", true);
+ }
+ }
+
+ // Add nodes for each light.
+ // (no transformation as the light is already in world space)
+ for (size_t n=0;n<sib.lights.size();n++)
+ {
+ aiLight* light = sib.lights[n];
+ if ( nullptr != light ) {
+ aiNode* node = new aiNode;
+ root->mChildren[ childIdx++ ] = node;
+ node->mName = light->mName;
+ node->mParent = root;
+ }
+ }
+}
+
+#endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER
diff --git a/src/3rdparty/assimp/code/SIBImporter.h b/src/3rdparty/assimp/code/SIBImporter.h
new file mode 100644
index 000000000..d82a40da0
--- /dev/null
+++ b/src/3rdparty/assimp/code/SIBImporter.h
@@ -0,0 +1,119 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file SIBImporter.h
+ * @brief Declaration of the SIB importer class.
+ */
+#ifndef AI_SIBIMPORTER_H_INCLUDED
+#define AI_SIBIMPORTER_H_INCLUDED
+
+#include "BaseImporter.h"
+#include <assimp/types.h>
+#include <vector>
+
+namespace Assimp {
+
+// ---------------------------------------------------------------------------
+/** Importer class for the Nevercenter Silo SIB scene format
+*/
+class SIBImporter : public BaseImporter
+{
+public:
+ SIBImporter();
+ ~SIBImporter();
+
+
+public:
+
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
+
+protected:
+
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
+
+private:
+
+ struct MeshInformation
+ {
+ explicit MeshInformation(const std::string& _name)
+ : name(_name)
+ {
+ vertices.reserve(100);
+ colors.reserve(100);
+ }
+
+ std::string name;
+
+ std::vector<aiVector3D> vertices;
+ std::vector<aiColor4D> colors;
+ };
+
+ struct GroupInformation
+ {
+ explicit GroupInformation(const std::string& _name)
+ : name(_name)
+ {
+ meshes.reserve(10);
+ }
+
+ std::string name;
+ std::vector<MeshInformation> meshes;
+ };
+};
+
+} // end of namespace Assimp
+
+#endif // AI_SIBIMPORTER_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/SMDLoader.cpp b/src/3rdparty/assimp/code/SMDLoader.cpp
index 4717e5f15..7aef7bc56 100644
--- a/src/3rdparty/assimp/code/SMDLoader.cpp
+++ b/src/3rdparty/assimp/code/SMDLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,1117 +25,1130 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
-/** @file SMDLoader.cpp
- * @brief Implementation of the SMD importer class
+/** @file SMDLoader.cpp
+ * @brief Implementation of the SMD importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
// internal headers
#include "SMDLoader.h"
#include "fast_atof.h"
#include "SkeletonMeshBuilder.h"
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <memory>
using namespace Assimp;
static const aiImporterDesc desc = {
- "Valve SMD Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "smd vta"
+ "Valve SMD Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "smd vta"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SMDImporter::SMDImporter()
+ : configFrameID(),
+ mBuffer(),
+ pScene(),
+ iFileSize(),
+ iSmallestFrame(),
+ dLengthOfAnim(),
+ bHasUVs(),
+ iLineNumber()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
SMDImporter::~SMDImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const
{
- // fixme: auto format detection
- return SimpleExtensionCheck(pFile,"smd","vta");
+ // fixme: auto format detection
+ return SimpleExtensionCheck(pFile,"smd","vta");
}
// ------------------------------------------------------------------------------------------------
// Get a list of all supported file extensions
const aiImporterDesc* SMDImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties
void SMDImporter::SetupProperties(const Importer* pImp)
{
- // The
- // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_SMD_KEYFRAME,-1);
- if(static_cast<unsigned int>(-1) == configFrameID) {
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
+ // The
+ // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_SMD_KEYFRAME,-1);
+ if(static_cast<unsigned int>(-1) == configFrameID) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
+// Imports the given file into the given scene structure.
void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open SMD/VTA file " + pFile + ".");
- }
-
- iFileSize = (unsigned int)file->FileSize();
-
- // Allocate storage and copy the contents of the file to a memory buffer
- this->pScene = pScene;
-
- std::vector<char> buff(iFileSize+1);
- TextFileToBuffer(file.get(),buff);
- mBuffer = &buff[0];
-
- iSmallestFrame = (1 << 31);
- bHasUVs = true;
- iLineNumber = 1;
-
- // Reserve enough space for ... hm ... 10 textures
- aszTextures.reserve(10);
-
- // Reserve enough space for ... hm ... 1000 triangles
- asTriangles.reserve(1000);
-
- // Reserve enough space for ... hm ... 20 bones
- asBones.reserve(20);
-
-
- // parse the file ...
- ParseFile();
-
- // If there are no triangles it seems to be an animation SMD,
- // containing only the animation skeleton.
- if (asTriangles.empty())
- {
- if (asBones.empty())
- {
- throw DeadlyImportError("SMD: No triangles and no bones have "
- "been found in the file. This file seems to be invalid.");
- }
-
- // Set the flag in the scene structure which indicates
- // that there is nothing than an animation skeleton
- pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
- }
-
- if (!asBones.empty())
- {
- // Check whether all bones have been initialized
- for (std::vector<SMD::Bone>::const_iterator
- i = asBones.begin();
- i != asBones.end();++i)
- {
- if (!(*i).mName.length())
- {
- DefaultLogger::get()->warn("SMD: Not all bones have been initialized");
- break;
- }
- }
-
- // now fix invalid time values and make sure the animation starts at frame 0
- FixTimeValues();
-
- // compute absolute bone transformation matrices
- // ComputeAbsoluteBoneTransformations();
- }
-
- if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
- {
- // create output meshes
- CreateOutputMeshes();
-
- // build an output material list
- CreateOutputMaterials();
- }
-
- // build the output animation
- CreateOutputAnimations();
-
- // build output nodes (bones are added as empty dummy nodes)
- CreateOutputNodes();
-
- if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)
- {
- SkeletonMeshBuilder skeleton(pScene);
- }
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open SMD/VTA file " + pFile + ".");
+ }
+
+ iFileSize = (unsigned int)file->FileSize();
+
+ // Allocate storage and copy the contents of the file to a memory buffer
+ this->pScene = pScene;
+
+ std::vector<char> buff(iFileSize+1);
+ TextFileToBuffer(file.get(),buff);
+ mBuffer = &buff[0];
+
+ iSmallestFrame = (1 << 31);
+ bHasUVs = true;
+ iLineNumber = 1;
+
+ // Reserve enough space for ... hm ... 10 textures
+ aszTextures.reserve(10);
+
+ // Reserve enough space for ... hm ... 1000 triangles
+ asTriangles.reserve(1000);
+
+ // Reserve enough space for ... hm ... 20 bones
+ asBones.reserve(20);
+
+
+ // parse the file ...
+ ParseFile();
+
+ // If there are no triangles it seems to be an animation SMD,
+ // containing only the animation skeleton.
+ if (asTriangles.empty())
+ {
+ if (asBones.empty())
+ {
+ throw DeadlyImportError("SMD: No triangles and no bones have "
+ "been found in the file. This file seems to be invalid.");
+ }
+
+ // Set the flag in the scene structure which indicates
+ // that there is nothing than an animation skeleton
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+
+ if (!asBones.empty())
+ {
+ // Check whether all bones have been initialized
+ for (std::vector<SMD::Bone>::const_iterator
+ i = asBones.begin();
+ i != asBones.end();++i)
+ {
+ if (!(*i).mName.length())
+ {
+ DefaultLogger::get()->warn("SMD: Not all bones have been initialized");
+ break;
+ }
+ }
+
+ // now fix invalid time values and make sure the animation starts at frame 0
+ FixTimeValues();
+
+ // compute absolute bone transformation matrices
+ // ComputeAbsoluteBoneTransformations();
+ }
+
+ if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
+ {
+ // create output meshes
+ CreateOutputMeshes();
+
+ // build an output material list
+ CreateOutputMaterials();
+ }
+
+ // build the output animation
+ CreateOutputAnimations();
+
+ // build output nodes (bones are added as empty dummy nodes)
+ CreateOutputNodes();
+
+ if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)
+ {
+ SkeletonMeshBuilder skeleton(pScene);
+ }
}
// ------------------------------------------------------------------------------------------------
// Write an error message with line number to the log file
void SMDImporter::LogErrorNoThrow(const char* msg)
{
- char szTemp[1024];
- sprintf(szTemp,"Line %i: %s",iLineNumber,msg);
- DefaultLogger::get()->error(szTemp);
+ char szTemp[1024];
+ ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg);
+ DefaultLogger::get()->error(szTemp);
}
// ------------------------------------------------------------------------------------------------
// Write a warning with line number to the log file
void SMDImporter::LogWarning(const char* msg)
{
- char szTemp[1024];
- ai_assert(strlen(msg) < 1000);
- sprintf(szTemp,"Line %i: %s",iLineNumber,msg);
- DefaultLogger::get()->warn(szTemp);
+ char szTemp[1024];
+ ai_assert(strlen(msg) < 1000);
+ ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg);
+ DefaultLogger::get()->warn(szTemp);
}
// ------------------------------------------------------------------------------------------------
// Fix invalid time values in the file
void SMDImporter::FixTimeValues()
{
- double dDelta = (double)iSmallestFrame;
- double dMax = 0.0f;
- for (std::vector<SMD::Bone>::iterator
- iBone = asBones.begin();
- iBone != asBones.end();++iBone)
- {
- for (std::vector<SMD::Bone::Animation::MatrixKey>::iterator
- iKey = (*iBone).sAnim.asKeys.begin();
- iKey != (*iBone).sAnim.asKeys.end();++iKey)
- {
- (*iKey).dTime -= dDelta;
- dMax = std::max(dMax, (*iKey).dTime);
- }
- }
- dLengthOfAnim = dMax;
+ double dDelta = (double)iSmallestFrame;
+ double dMax = 0.0f;
+ for (std::vector<SMD::Bone>::iterator
+ iBone = asBones.begin();
+ iBone != asBones.end();++iBone)
+ {
+ for (std::vector<SMD::Bone::Animation::MatrixKey>::iterator
+ iKey = (*iBone).sAnim.asKeys.begin();
+ iKey != (*iBone).sAnim.asKeys.end();++iKey)
+ {
+ (*iKey).dTime -= dDelta;
+ dMax = std::max(dMax, (*iKey).dTime);
+ }
+ }
+ dLengthOfAnim = dMax;
}
// ------------------------------------------------------------------------------------------------
// create output meshes
void SMDImporter::CreateOutputMeshes()
{
- if (aszTextures.empty())
- aszTextures.push_back(std::string());
-
- // we need to sort all faces by their material index
- // in opposition to other loaders we can be sure that each
- // material is at least used once.
- pScene->mNumMeshes = (unsigned int) aszTextures.size();
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-
- typedef std::vector<unsigned int> FaceList;
- FaceList* aaiFaces = new FaceList[pScene->mNumMeshes];
-
- // approximate the space that will be required
- unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes;
- iNum += iNum >> 1;
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- aaiFaces[i].reserve(iNum);
-
-
- // collect all faces
- iNum = 0;
- for (std::vector<SMD::Face>::const_iterator
- iFace = asTriangles.begin();
- iFace != asTriangles.end();++iFace,++iNum)
- {
- if (UINT_MAX == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 );
- else if ((*iFace).iTexture >= aszTextures.size())
- {
- DefaultLogger::get()->error("[SMD/VTA] Material index overflow in face");
- aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1);
- }
- else aaiFaces[(*iFace).iTexture].push_back(iNum);
- }
-
- // now create the output meshes
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- {
- aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh();
- ai_assert(!aaiFaces[i].empty()); // should not be empty ...
-
- pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
- pcMesh->mNumVertices = (unsigned int)aaiFaces[i].size()*3;
- pcMesh->mNumFaces = (unsigned int)aaiFaces[i].size();
- pcMesh->mMaterialIndex = i;
-
- // storage for bones
- typedef std::pair<unsigned int,float> TempWeightListEntry;
- typedef std::vector< TempWeightListEntry > TempBoneWeightList;
-
- TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()]();
-
- // try to reserve enough memory without wasting too much
- for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
- {
- aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size());
- }
-
- // allocate storage
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
-
- aiVector3D* pcUVs = NULL;
- if (bHasUVs)
- {
- pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
- }
-
- iNum = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
- {
- pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
- pcMesh->mFaces[iFace].mNumIndices = 3;
-
- // fill the vertices
- unsigned int iSrcFace = aaiFaces[i][iFace];
- SMD::Face& face = asTriangles[iSrcFace];
-
- *pcVerts++ = face.avVertices[0].pos;
- *pcVerts++ = face.avVertices[1].pos;
- *pcVerts++ = face.avVertices[2].pos;
-
- // fill the normals
- *pcNormals++ = face.avVertices[0].nor;
- *pcNormals++ = face.avVertices[1].nor;
- *pcNormals++ = face.avVertices[2].nor;
-
- // fill the texture coordinates
- if (pcUVs)
- {
- *pcUVs++ = face.avVertices[0].uv;
- *pcUVs++ = face.avVertices[1].uv;
- *pcUVs++ = face.avVertices[2].uv;
- }
-
- for (unsigned int iVert = 0; iVert < 3;++iVert)
- {
- float fSum = 0.0f;
- for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
- {
- TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
-
- // FIX: The second check is here just to make sure we won't
- // assign more than one weight to a single vertex index
- if (pairval.first >= asBones.size() ||
- pairval.first == face.avVertices[iVert].iParentNode)
- {
- DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
- "The bone index will be ignored, the weight will be assigned "
- "to the vertex' parent node");
- continue;
- }
- aaiBones[pairval.first].push_back(TempWeightListEntry(iNum,pairval.second));
- fSum += pairval.second;
- }
- // ******************************************************************
- // If the sum of all vertex weights is not 1.0 we must assign
- // the rest to the vertex' parent node. Well, at least the doc says
- // we should ...
- // FIX: We use 0.975 as limit, floating-point inaccuracies seem to
- // be very strong in some SMD exporters. Furthermore it is possible
- // that the parent of a vertex is 0xffffffff (if the corresponding
- // entry in the file was unreadable)
- // ******************************************************************
- if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX)
- {
- if (face.avVertices[iVert].iParentNode >= asBones.size())
- {
- DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
- "The index of the vertex parent bone is invalid. "
- "The remaining weights will be normalized to 1.0");
-
- if (fSum)
- {
- fSum = 1 / fSum;
- for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
- {
- TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
- if (pairval.first >= asBones.size())continue;
- aaiBones[pairval.first].back().second *= fSum;
- }
- }
- }
- else
- {
- aaiBones[face.avVertices[iVert].iParentNode].push_back(
- TempWeightListEntry(iNum,1.0f-fSum));
- }
- }
- pcMesh->mFaces[iFace].mIndices[iVert] = iNum++;
- }
- }
-
- // now build all bones of the mesh
- iNum = 0;
- for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
- if (!aaiBones[iBone].empty())++iNum;
-
- if (false && iNum)
- {
- pcMesh->mNumBones = iNum;
- pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
- iNum = 0;
- for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
- {
- if (aaiBones[iBone].empty())continue;
- aiBone*& bone = pcMesh->mBones[iNum] = new aiBone();
-
- bone->mNumWeights = (unsigned int)aaiBones[iBone].size();
- bone->mWeights = new aiVertexWeight[bone->mNumWeights];
- bone->mOffsetMatrix = asBones[iBone].mOffsetMatrix;
- bone->mName.Set( asBones[iBone].mName );
-
- asBones[iBone].bIsUsed = true;
-
- for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight)
- {
- bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first;
- bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second;
- }
- ++iNum;
- }
- }
- delete[] aaiBones;
- }
- delete[] aaiFaces;
+ if (aszTextures.empty())
+ aszTextures.push_back(std::string());
+
+ // we need to sort all faces by their material index
+ // in opposition to other loaders we can be sure that each
+ // material is at least used once.
+ pScene->mNumMeshes = (unsigned int) aszTextures.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+
+ typedef std::vector<unsigned int> FaceList;
+ FaceList* aaiFaces = new FaceList[pScene->mNumMeshes];
+
+ // approximate the space that will be required
+ unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes;
+ iNum += iNum >> 1;
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ aaiFaces[i].reserve(iNum);
+
+
+ // collect all faces
+ iNum = 0;
+ for (std::vector<SMD::Face>::const_iterator
+ iFace = asTriangles.begin();
+ iFace != asTriangles.end();++iFace,++iNum)
+ {
+ if (UINT_MAX == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 );
+ else if ((*iFace).iTexture >= aszTextures.size())
+ {
+ DefaultLogger::get()->error("[SMD/VTA] Material index overflow in face");
+ aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1);
+ }
+ else aaiFaces[(*iFace).iTexture].push_back(iNum);
+ }
+
+ // now create the output meshes
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh();
+ ai_assert(!aaiFaces[i].empty()); // should not be empty ...
+
+ pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+ pcMesh->mNumVertices = (unsigned int)aaiFaces[i].size()*3;
+ pcMesh->mNumFaces = (unsigned int)aaiFaces[i].size();
+ pcMesh->mMaterialIndex = i;
+
+ // storage for bones
+ typedef std::pair<unsigned int,float> TempWeightListEntry;
+ typedef std::vector< TempWeightListEntry > TempBoneWeightList;
+
+ TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()]();
+
+ // try to reserve enough memory without wasting too much
+ for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
+ {
+ aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size());
+ }
+
+ // allocate storage
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+ aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
+ aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
+
+ aiVector3D* pcUVs = NULL;
+ if (bHasUVs)
+ {
+ pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
+ pcMesh->mNumUVComponents[0] = 2;
+ }
+
+ iNum = 0;
+ for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
+ {
+ pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
+ pcMesh->mFaces[iFace].mNumIndices = 3;
+
+ // fill the vertices
+ unsigned int iSrcFace = aaiFaces[i][iFace];
+ SMD::Face& face = asTriangles[iSrcFace];
+
+ *pcVerts++ = face.avVertices[0].pos;
+ *pcVerts++ = face.avVertices[1].pos;
+ *pcVerts++ = face.avVertices[2].pos;
+
+ // fill the normals
+ *pcNormals++ = face.avVertices[0].nor;
+ *pcNormals++ = face.avVertices[1].nor;
+ *pcNormals++ = face.avVertices[2].nor;
+
+ // fill the texture coordinates
+ if (pcUVs)
+ {
+ *pcUVs++ = face.avVertices[0].uv;
+ *pcUVs++ = face.avVertices[1].uv;
+ *pcUVs++ = face.avVertices[2].uv;
+ }
+
+ for (unsigned int iVert = 0; iVert < 3;++iVert)
+ {
+ float fSum = 0.0f;
+ for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
+ {
+ TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
+
+ // FIX: The second check is here just to make sure we won't
+ // assign more than one weight to a single vertex index
+ if (pairval.first >= asBones.size() ||
+ pairval.first == face.avVertices[iVert].iParentNode)
+ {
+ DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
+ "The bone index will be ignored, the weight will be assigned "
+ "to the vertex' parent node");
+ continue;
+ }
+ aaiBones[pairval.first].push_back(TempWeightListEntry(iNum,pairval.second));
+ fSum += pairval.second;
+ }
+ // ******************************************************************
+ // If the sum of all vertex weights is not 1.0 we must assign
+ // the rest to the vertex' parent node. Well, at least the doc says
+ // we should ...
+ // FIX: We use 0.975 as limit, floating-point inaccuracies seem to
+ // be very strong in some SMD exporters. Furthermore it is possible
+ // that the parent of a vertex is 0xffffffff (if the corresponding
+ // entry in the file was unreadable)
+ // ******************************************************************
+ if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX)
+ {
+ if (face.avVertices[iVert].iParentNode >= asBones.size())
+ {
+ DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
+ "The index of the vertex parent bone is invalid. "
+ "The remaining weights will be normalized to 1.0");
+
+ if (fSum)
+ {
+ fSum = 1 / fSum;
+ for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
+ {
+ TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
+ if (pairval.first >= asBones.size())continue;
+ aaiBones[pairval.first].back().second *= fSum;
+ }
+ }
+ }
+ else
+ {
+ aaiBones[face.avVertices[iVert].iParentNode].push_back(
+ TempWeightListEntry(iNum,1.0f-fSum));
+ }
+ }
+ pcMesh->mFaces[iFace].mIndices[iVert] = iNum++;
+ }
+ }
+
+ // now build all bones of the mesh
+ iNum = 0;
+ for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
+ if (!aaiBones[iBone].empty())++iNum;
+
+ if (false && iNum)
+ {
+ pcMesh->mNumBones = iNum;
+ pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
+ iNum = 0;
+ for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
+ {
+ if (aaiBones[iBone].empty())continue;
+ aiBone*& bone = pcMesh->mBones[iNum] = new aiBone();
+
+ bone->mNumWeights = (unsigned int)aaiBones[iBone].size();
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+ bone->mOffsetMatrix = asBones[iBone].mOffsetMatrix;
+ bone->mName.Set( asBones[iBone].mName );
+
+ asBones[iBone].bIsUsed = true;
+
+ for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight)
+ {
+ bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first;
+ bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second;
+ }
+ ++iNum;
+ }
+ }
+ delete[] aaiBones;
+ }
+ delete[] aaiFaces;
}
// ------------------------------------------------------------------------------------------------
// add bone child nodes
void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
{
- ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren);
-
- // first count ...
- for (unsigned int i = 0; i < asBones.size();++i)
- {
- SMD::Bone& bone = asBones[i];
- if (bone.iParent == iParent)++pcNode->mNumChildren;
- }
-
- // now allocate the output array
- pcNode->mChildren = new aiNode*[pcNode->mNumChildren];
-
- // and fill all subnodes
- unsigned int qq = 0;
- for (unsigned int i = 0; i < asBones.size();++i)
- {
- SMD::Bone& bone = asBones[i];
- if (bone.iParent != iParent)continue;
-
- aiNode* pc = pcNode->mChildren[qq++] = new aiNode();
- pc->mName.Set(bone.mName);
-
- // store the local transformation matrix of the bind pose
- pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix;
- pc->mParent = pcNode;
-
- // add children to this node, too
- AddBoneChildren(pc,i);
- }
+ ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren);
+
+ // first count ...
+ for (unsigned int i = 0; i < asBones.size();++i)
+ {
+ SMD::Bone& bone = asBones[i];
+ if (bone.iParent == iParent)++pcNode->mNumChildren;
+ }
+
+ // now allocate the output array
+ pcNode->mChildren = new aiNode*[pcNode->mNumChildren];
+
+ // and fill all subnodes
+ unsigned int qq = 0;
+ for (unsigned int i = 0; i < asBones.size();++i)
+ {
+ SMD::Bone& bone = asBones[i];
+ if (bone.iParent != iParent)continue;
+
+ aiNode* pc = pcNode->mChildren[qq++] = new aiNode();
+ pc->mName.Set(bone.mName);
+
+ // store the local transformation matrix of the bind pose
+ pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix;
+ pc->mParent = pcNode;
+
+ // add children to this node, too
+ AddBoneChildren(pc,i);
+ }
}
// ------------------------------------------------------------------------------------------------
// create output nodes
void SMDImporter::CreateOutputNodes()
{
- pScene->mRootNode = new aiNode();
- if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
- {
- // create one root node that renders all meshes
- pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
- pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- pScene->mRootNode->mMeshes[i] = i;
- }
-
- // now add all bones as dummy sub nodes to the graph
- // AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
-
- // if we have only one bone we can even remove the root node
- if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE &&
- 1 == pScene->mRootNode->mNumChildren)
- {
- aiNode* pcOldRoot = pScene->mRootNode;
- pScene->mRootNode = pcOldRoot->mChildren[0];
- pcOldRoot->mChildren[0] = NULL;
- delete pcOldRoot;
-
- pScene->mRootNode->mParent = NULL;
- }
- else
- {
- ::strcpy(pScene->mRootNode->mName.data, "<SMD_root>");
- pScene->mRootNode->mName.length = 10;
- }
+ pScene->mRootNode = new aiNode();
+ if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
+ {
+ // create one root node that renders all meshes
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ pScene->mRootNode->mMeshes[i] = i;
+ }
+
+ // now add all bones as dummy sub nodes to the graph
+ // AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
+
+ // if we have only one bone we can even remove the root node
+ if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE &&
+ 1 == pScene->mRootNode->mNumChildren)
+ {
+ aiNode* pcOldRoot = pScene->mRootNode;
+ pScene->mRootNode = pcOldRoot->mChildren[0];
+ pcOldRoot->mChildren[0] = NULL;
+ delete pcOldRoot;
+
+ pScene->mRootNode->mParent = NULL;
+ }
+ else
+ {
+ ::strcpy(pScene->mRootNode->mName.data, "<SMD_root>");
+ pScene->mRootNode->mName.length = 10;
+ }
}
// ------------------------------------------------------------------------------------------------
// create output animations
void SMDImporter::CreateOutputAnimations()
{
- unsigned int iNumBones = 0;
- for (std::vector<SMD::Bone>::const_iterator
- i = asBones.begin();
- i != asBones.end();++i)
- {
- if ((*i).bIsUsed)++iNumBones;
- }
- if (!iNumBones)
- {
- // just make sure this case doesn't occur ... (it could occur
- // if the file was invalid)
- return;
- }
-
- pScene->mNumAnimations = 1;
- pScene->mAnimations = new aiAnimation*[1];
- aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation();
-
- anim->mDuration = dLengthOfAnim;
- anim->mNumChannels = iNumBones;
- anim->mTicksPerSecond = 25.0; // FIXME: is this correct?
-
- aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-
- // now build valid keys
- unsigned int a = 0;
- for (std::vector<SMD::Bone>::const_iterator
- i = asBones.begin();
- i != asBones.end();++i)
- {
- if (!(*i).bIsUsed)continue;
-
- aiNodeAnim* p = pp[a] = new aiNodeAnim();
-
- // copy the name of the bone
- p->mNodeName.Set( i->mName);
-
- p->mNumRotationKeys = (unsigned int) (*i).sAnim.asKeys.size();
- if (p->mNumRotationKeys)
- {
- p->mNumPositionKeys = p->mNumRotationKeys;
- aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys];
- aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys];
-
- for (std::vector<SMD::Bone::Animation::MatrixKey>::const_iterator
- qq = (*i).sAnim.asKeys.begin();
- qq != (*i).sAnim.asKeys.end(); ++qq)
- {
- pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime;
-
- // compute the rotation quaternion from the euler angles
- pRotKeys->mValue = aiQuaternion( (*qq).vRot.x, (*qq).vRot.y, (*qq).vRot.z );
- pVecKeys->mValue = (*qq).vPos;
-
- ++pVecKeys; ++pRotKeys;
- }
- }
- ++a;
-
- // there are no scaling keys ...
- }
+ unsigned int iNumBones = 0;
+ for (std::vector<SMD::Bone>::const_iterator
+ i = asBones.begin();
+ i != asBones.end();++i)
+ {
+ if ((*i).bIsUsed)++iNumBones;
+ }
+ if (!iNumBones)
+ {
+ // just make sure this case doesn't occur ... (it could occur
+ // if the file was invalid)
+ return;
+ }
+
+ pScene->mNumAnimations = 1;
+ pScene->mAnimations = new aiAnimation*[1];
+ aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation();
+
+ anim->mDuration = dLengthOfAnim;
+ anim->mNumChannels = iNumBones;
+ anim->mTicksPerSecond = 25.0; // FIXME: is this correct?
+
+ aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+ // now build valid keys
+ unsigned int a = 0;
+ for (std::vector<SMD::Bone>::const_iterator
+ i = asBones.begin();
+ i != asBones.end();++i)
+ {
+ if (!(*i).bIsUsed)continue;
+
+ aiNodeAnim* p = pp[a] = new aiNodeAnim();
+
+ // copy the name of the bone
+ p->mNodeName.Set( i->mName);
+
+ p->mNumRotationKeys = (unsigned int) (*i).sAnim.asKeys.size();
+ if (p->mNumRotationKeys)
+ {
+ p->mNumPositionKeys = p->mNumRotationKeys;
+ aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys];
+ aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys];
+
+ for (std::vector<SMD::Bone::Animation::MatrixKey>::const_iterator
+ qq = (*i).sAnim.asKeys.begin();
+ qq != (*i).sAnim.asKeys.end(); ++qq)
+ {
+ pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime;
+
+ // compute the rotation quaternion from the euler angles
+ pRotKeys->mValue = aiQuaternion( (*qq).vRot.x, (*qq).vRot.y, (*qq).vRot.z );
+ pVecKeys->mValue = (*qq).vPos;
+
+ ++pVecKeys; ++pRotKeys;
+ }
+ }
+ ++a;
+
+ // there are no scaling keys ...
+ }
}
// ------------------------------------------------------------------------------------------------
void SMDImporter::ComputeAbsoluteBoneTransformations()
{
- // For each bone: determine the key with the lowest time value
- // theoretically the SMD format should have all keyframes
- // in order. However, I've seen a file where this wasn't true.
- for (unsigned int i = 0; i < asBones.size();++i)
- {
- SMD::Bone& bone = asBones[i];
-
- uint32_t iIndex = 0;
- double dMin = 10e10;
- for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i)
- {
- double d = std::min(bone.sAnim.asKeys[i].dTime,dMin);
- if (d < dMin)
- {
- dMin = d;
- iIndex = i;
- }
- }
- bone.sAnim.iFirstTimeKey = iIndex;
- }
-
- unsigned int iParent = 0;
- while (iParent < asBones.size())
- {
- for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
- {
- SMD::Bone& bone = asBones[iBone];
-
- if (iParent == bone.iParent)
- {
- SMD::Bone& parentBone = asBones[iParent];
-
-
- uint32_t iIndex = bone.sAnim.iFirstTimeKey;
- const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix;
- aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute;
-
- // The same for the parent bone ...
- iIndex = parentBone.sAnim.iFirstTimeKey;
- const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute;
-
- // Compute the absolute transformation matrix
- matOut = mat * mat2;
- }
- }
- ++iParent;
- }
-
- // Store the inverse of the absolute transformation matrix
- // of the first key as bone offset matrix
- for (iParent = 0; iParent < asBones.size();++iParent)
- {
- SMD::Bone& bone = asBones[iParent];
- bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute;
- bone.mOffsetMatrix.Inverse();
- }
+ // For each bone: determine the key with the lowest time value
+ // theoretically the SMD format should have all keyframes
+ // in order. However, I've seen a file where this wasn't true.
+ for (unsigned int i = 0; i < asBones.size();++i)
+ {
+ SMD::Bone& bone = asBones[i];
+
+ uint32_t iIndex = 0;
+ double dMin = 10e10;
+ for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i)
+ {
+ double d = std::min(bone.sAnim.asKeys[i].dTime,dMin);
+ if (d < dMin)
+ {
+ dMin = d;
+ iIndex = i;
+ }
+ }
+ bone.sAnim.iFirstTimeKey = iIndex;
+ }
+
+ unsigned int iParent = 0;
+ while (iParent < asBones.size())
+ {
+ for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
+ {
+ SMD::Bone& bone = asBones[iBone];
+
+ if (iParent == bone.iParent)
+ {
+ SMD::Bone& parentBone = asBones[iParent];
+
+
+ uint32_t iIndex = bone.sAnim.iFirstTimeKey;
+ const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix;
+ aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute;
+
+ // The same for the parent bone ...
+ iIndex = parentBone.sAnim.iFirstTimeKey;
+ const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute;
+
+ // Compute the absolute transformation matrix
+ matOut = mat * mat2;
+ }
+ }
+ ++iParent;
+ }
+
+ // Store the inverse of the absolute transformation matrix
+ // of the first key as bone offset matrix
+ for (iParent = 0; iParent < asBones.size();++iParent)
+ {
+ SMD::Bone& bone = asBones[iParent];
+ bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute;
+ bone.mOffsetMatrix.Inverse();
+ }
}
// ------------------------------------------------------------------------------------------------
// create output materials
void SMDImporter::CreateOutputMaterials()
{
- pScene->mNumMaterials = (unsigned int)aszTextures.size();
- pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)];
-
- for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat)
- {
- aiMaterial* pcMat = new aiMaterial();
- pScene->mMaterials[iMat] = pcMat;
-
- aiString szName;
- szName.length = (size_t)::sprintf(szName.data,"Texture_%i",iMat);
- pcMat->AddProperty(&szName,AI_MATKEY_NAME);
-
- if (aszTextures[iMat].length())
- {
- ::strcpy(szName.data, aszTextures[iMat].c_str() );
- szName.length = aszTextures[iMat].length();
- pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- }
-
- // create a default material if necessary
- if (0 == pScene->mNumMaterials)
- {
- pScene->mNumMaterials = 1;
-
- aiMaterial* pcHelper = new aiMaterial();
- pScene->mMaterials[0] = pcHelper;
-
- int iMode = (int)aiShadingMode_Gouraud;
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
-
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.7f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
-
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
-
- aiString szName;
- szName.Set(AI_DEFAULT_MATERIAL_NAME);
- pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
- }
+ pScene->mNumMaterials = (unsigned int)aszTextures.size();
+ pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)];
+
+ for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat)
+ {
+ aiMaterial* pcMat = new aiMaterial();
+ pScene->mMaterials[iMat] = pcMat;
+
+ aiString szName;
+ szName.length = (size_t)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat);
+ pcMat->AddProperty(&szName,AI_MATKEY_NAME);
+
+ if (aszTextures[iMat].length())
+ {
+ ::strcpy(szName.data, aszTextures[iMat].c_str() );
+ szName.length = aszTextures[iMat].length();
+ pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
+
+ // create a default material if necessary
+ if (0 == pScene->mNumMaterials)
+ {
+ pScene->mNumMaterials = 1;
+
+ aiMaterial* pcHelper = new aiMaterial();
+ pScene->mMaterials[0] = pcHelper;
+
+ int iMode = (int)aiShadingMode_Gouraud;
+ pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
+
+ aiColor3D clr;
+ clr.b = clr.g = clr.r = 0.7f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+
+ clr.b = clr.g = clr.r = 0.05f;
+ pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+
+ aiString szName;
+ szName.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+ }
}
// ------------------------------------------------------------------------------------------------
// Parse the file
void SMDImporter::ParseFile()
{
- const char* szCurrent = mBuffer;
-
- // read line per line ...
- for ( ;; )
- {
- if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
-
- // "version <n> \n", <n> should be 1 for hl and hl² SMD files
- if (TokenMatch(szCurrent,"version",7))
- {
- if(!SkipSpaces(szCurrent,&szCurrent)) break;
- if (1 != strtoul10(szCurrent,&szCurrent))
- {
- DefaultLogger::get()->warn("SMD.version is not 1. This "
- "file format is not known. Continuing happily ...");
- }
- continue;
- }
- // "nodes\n" - Starts the node section
- if (TokenMatch(szCurrent,"nodes",5))
- {
- ParseNodesSection(szCurrent,&szCurrent);
- continue;
- }
- // "triangles\n" - Starts the triangle section
- if (TokenMatch(szCurrent,"triangles",9))
- {
- ParseTrianglesSection(szCurrent,&szCurrent);
- continue;
- }
- // "vertexanimation\n" - Starts the vertex animation section
- if (TokenMatch(szCurrent,"vertexanimation",15))
- {
- bHasUVs = false;
- ParseVASection(szCurrent,&szCurrent);
- continue;
- }
- // "skeleton\n" - Starts the skeleton section
- if (TokenMatch(szCurrent,"skeleton",8))
- {
- ParseSkeletonSection(szCurrent,&szCurrent);
- continue;
- }
- SkipLine(szCurrent,&szCurrent);
- }
- return;
+ const char* szCurrent = mBuffer;
+
+ // read line per line ...
+ for ( ;; )
+ {
+ if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
+
+ // "version <n> \n", <n> should be 1 for hl and hl� SMD files
+ if (TokenMatch(szCurrent,"version",7))
+ {
+ if(!SkipSpaces(szCurrent,&szCurrent)) break;
+ if (1 != strtoul10(szCurrent,&szCurrent))
+ {
+ DefaultLogger::get()->warn("SMD.version is not 1. This "
+ "file format is not known. Continuing happily ...");
+ }
+ continue;
+ }
+ // "nodes\n" - Starts the node section
+ if (TokenMatch(szCurrent,"nodes",5))
+ {
+ ParseNodesSection(szCurrent,&szCurrent);
+ continue;
+ }
+ // "triangles\n" - Starts the triangle section
+ if (TokenMatch(szCurrent,"triangles",9))
+ {
+ ParseTrianglesSection(szCurrent,&szCurrent);
+ continue;
+ }
+ // "vertexanimation\n" - Starts the vertex animation section
+ if (TokenMatch(szCurrent,"vertexanimation",15))
+ {
+ bHasUVs = false;
+ ParseVASection(szCurrent,&szCurrent);
+ continue;
+ }
+ // "skeleton\n" - Starts the skeleton section
+ if (TokenMatch(szCurrent,"skeleton",8))
+ {
+ ParseSkeletonSection(szCurrent,&szCurrent);
+ continue;
+ }
+ SkipLine(szCurrent,&szCurrent);
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
unsigned int SMDImporter::GetTextureIndex(const std::string& filename)
{
- unsigned int iIndex = 0;
- for (std::vector<std::string>::const_iterator
- i = aszTextures.begin();
- i != aszTextures.end();++i,++iIndex)
- {
- // case-insensitive ... it's a path
- if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex;
- }
- iIndex = (unsigned int)aszTextures.size();
- aszTextures.push_back(filename);
- return iIndex;
+ unsigned int iIndex = 0;
+ for (std::vector<std::string>::const_iterator
+ i = aszTextures.begin();
+ i != aszTextures.end();++i,++iIndex)
+ {
+ // case-insensitive ... it's a path
+ if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex;
+ }
+ iIndex = (unsigned int)aszTextures.size();
+ aszTextures.push_back(filename);
+ return iIndex;
}
// ------------------------------------------------------------------------------------------------
// Parse the nodes section of the file
void SMDImporter::ParseNodesSection(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- for ( ;; )
- {
- // "end\n" - Ends the nodes section
- if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
- IsSpaceOrNewLine(*(szCurrent+3)))
- {
- szCurrent += 4;
- break;
- }
- ParseNodeInfo(szCurrent,&szCurrent);
- }
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
- *szCurrentOut = szCurrent;
+ for ( ;; )
+ {
+ // "end\n" - Ends the nodes section
+ if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
+ IsSpaceOrNewLine(*(szCurrent+3)))
+ {
+ szCurrent += 4;
+ break;
+ }
+ ParseNodeInfo(szCurrent,&szCurrent);
+ }
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
// Parse the triangles section of the file
void SMDImporter::ParseTrianglesSection(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- // Parse a triangle, parse another triangle, parse the next triangle ...
- // and so on until we reach a token that looks quite similar to "end"
- for ( ;; )
- {
- if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
-
- // "end\n" - Ends the triangles section
- if (TokenMatch(szCurrent,"end",3))
- break;
- ParseTriangle(szCurrent,&szCurrent);
- }
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
- *szCurrentOut = szCurrent;
+ // Parse a triangle, parse another triangle, parse the next triangle ...
+ // and so on until we reach a token that looks quite similar to "end"
+ for ( ;; )
+ {
+ if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
+
+ // "end\n" - Ends the triangles section
+ if (TokenMatch(szCurrent,"end",3))
+ break;
+ ParseTriangle(szCurrent,&szCurrent);
+ }
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
// Parse the vertex animation section of the file
void SMDImporter::ParseVASection(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- unsigned int iCurIndex = 0;
- for ( ;; )
- {
- if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
-
- // "end\n" - Ends the "vertexanimation" section
- if (TokenMatch(szCurrent,"end",3))
- break;
-
- // "time <n>\n"
- if (TokenMatch(szCurrent,"time",4))
- {
- // NOTE: The doc says that time values COULD be negative ...
- // NOTE2: this is the shape key -> valve docs
- int iTime = 0;
- if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break;
- SkipLine(szCurrent,&szCurrent);
- }
- else
- {
- if(0 == iCurIndex)
- {
- asTriangles.push_back(SMD::Face());
- }
- if (++iCurIndex == 3)iCurIndex = 0;
- ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true);
- }
- }
-
- if (iCurIndex != 2 && !asTriangles.empty())
- {
- // we want to no degenerates, so throw this triangle away
- asTriangles.pop_back();
- }
-
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
- *szCurrentOut = szCurrent;
+ unsigned int iCurIndex = 0;
+ for ( ;; )
+ {
+ if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
+
+ // "end\n" - Ends the "vertexanimation" section
+ if (TokenMatch(szCurrent,"end",3))
+ break;
+
+ // "time <n>\n"
+ if (TokenMatch(szCurrent,"time",4))
+ {
+ // NOTE: The doc says that time values COULD be negative ...
+ // NOTE2: this is the shape key -> valve docs
+ int iTime = 0;
+ if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break;
+ SkipLine(szCurrent,&szCurrent);
+ }
+ else
+ {
+ if(0 == iCurIndex)
+ {
+ asTriangles.push_back(SMD::Face());
+ }
+ if (++iCurIndex == 3)iCurIndex = 0;
+ ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true);
+ }
+ }
+
+ if (iCurIndex != 2 && !asTriangles.empty())
+ {
+ // we want to no degenerates, so throw this triangle away
+ asTriangles.pop_back();
+ }
+
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
// Parse the skeleton section of the file
void SMDImporter::ParseSkeletonSection(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- int iTime = 0;
- for ( ;; )
- {
- if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
-
- // "end\n" - Ends the skeleton section
- if (TokenMatch(szCurrent,"end",3))
- break;
-
- // "time <n>\n" - Specifies the current animation frame
- else if (TokenMatch(szCurrent,"time",4))
- {
- // NOTE: The doc says that time values COULD be negative ...
- if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break;
-
- iSmallestFrame = std::min(iSmallestFrame,iTime);
- SkipLine(szCurrent,&szCurrent);
- }
- else ParseSkeletonElement(szCurrent,&szCurrent,iTime);
- }
- *szCurrentOut = szCurrent;
+ int iTime = 0;
+ for ( ;; )
+ {
+ if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
+
+ // "end\n" - Ends the skeleton section
+ if (TokenMatch(szCurrent,"end",3))
+ break;
+
+ // "time <n>\n" - Specifies the current animation frame
+ else if (TokenMatch(szCurrent,"time",4))
+ {
+ // NOTE: The doc says that time values COULD be negative ...
+ if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break;
+
+ iSmallestFrame = std::min(iSmallestFrame,iTime);
+ SkipLine(szCurrent,&szCurrent);
+ }
+ else ParseSkeletonElement(szCurrent,&szCurrent,iTime);
+ }
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
#define SMDI_PARSE_RETURN { \
- SkipLine(szCurrent,&szCurrent); \
- *szCurrentOut = szCurrent; \
- return; \
+ SkipLine(szCurrent,&szCurrent); \
+ *szCurrentOut = szCurrent; \
+ return; \
}
// ------------------------------------------------------------------------------------------------
// Parse a node line
void SMDImporter::ParseNodeInfo(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- unsigned int iBone = 0;
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
- if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index");
- SMDI_PARSE_RETURN;
- }
- // add our bone to the list
- if (iBone >= asBones.size())asBones.resize(iBone+1);
- SMD::Bone& bone = asBones[iBone];
-
- bool bQuota = true;
- if ('\"' != *szCurrent)
- {
- LogWarning("Bone name is expcted to be enclosed in "
- "double quotation marks. ");
- bQuota = false;
- }
- else ++szCurrent;
-
- const char* szEnd = szCurrent;
- for ( ;; )
- {
- if (bQuota && '\"' == *szEnd)
- {
- iBone = (unsigned int)(szEnd - szCurrent);
- ++szEnd;
- break;
- }
- else if (IsSpaceOrNewLine(*szEnd))
- {
- iBone = (unsigned int)(szEnd - szCurrent);
- break;
- }
- else if (!(*szEnd))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name");
- SMDI_PARSE_RETURN;
- }
- ++szEnd;
- }
- bone.mName = std::string(szCurrent,iBone);
- szCurrent = szEnd;
-
- // the only negative bone parent index that could occur is -1 AFAIK
- if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1");
- SMDI_PARSE_RETURN;
- }
-
- // go to the beginning of the next line
- SMDI_PARSE_RETURN;
+ unsigned int iBone = 0;
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+ if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index");
+ SMDI_PARSE_RETURN;
+ }
+ // add our bone to the list
+ if (iBone >= asBones.size())asBones.resize(iBone+1);
+ SMD::Bone& bone = asBones[iBone];
+
+ bool bQuota = true;
+ if ('\"' != *szCurrent)
+ {
+ LogWarning("Bone name is expcted to be enclosed in "
+ "double quotation marks. ");
+ bQuota = false;
+ }
+ else ++szCurrent;
+
+ const char* szEnd = szCurrent;
+ for ( ;; )
+ {
+ if (bQuota && '\"' == *szEnd)
+ {
+ iBone = (unsigned int)(szEnd - szCurrent);
+ ++szEnd;
+ break;
+ }
+ else if (IsSpaceOrNewLine(*szEnd))
+ {
+ iBone = (unsigned int)(szEnd - szCurrent);
+ break;
+ }
+ else if (!(*szEnd))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name");
+ SMDI_PARSE_RETURN;
+ }
+ ++szEnd;
+ }
+ bone.mName = std::string(szCurrent,iBone);
+ szCurrent = szEnd;
+
+ // the only negative bone parent index that could occur is -1 AFAIK
+ if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1");
+ SMDI_PARSE_RETURN;
+ }
+
+ // go to the beginning of the next line
+ SMDI_PARSE_RETURN;
}
// ------------------------------------------------------------------------------------------------
// Parse a skeleton element
void SMDImporter::ParseSkeletonElement(const char* szCurrent,
- const char** szCurrentOut,int iTime)
+ const char** szCurrentOut,int iTime)
{
- aiVector3D vPos;
- aiVector3D vRot;
-
- unsigned int iBone = 0;
- if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone))
- {
- DefaultLogger::get()->error("Unexpected EOF/EOL while parsing bone index");
- SMDI_PARSE_RETURN;
- }
- if (iBone >= asBones.size())
- {
- LogErrorNoThrow("Bone index in skeleton section is out of range");
- SMDI_PARSE_RETURN;
- }
- SMD::Bone& bone = asBones[iBone];
-
- bone.sAnim.asKeys.push_back(SMD::Bone::Animation::MatrixKey());
- SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back();
-
- key.dTime = (double)iTime;
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z");
- SMDI_PARSE_RETURN;
- }
- // build the transformation matrix of the key
- key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z);
- {
- aiMatrix4x4 mTemp;
- mTemp.a4 = vPos.x;
- mTemp.b4 = vPos.y;
- mTemp.c4 = vPos.z;
- key.matrix = key.matrix * mTemp;
- }
-
- // go to the beginning of the next line
- SMDI_PARSE_RETURN;
+ aiVector3D vPos;
+ aiVector3D vRot;
+
+ unsigned int iBone = 0;
+ if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone))
+ {
+ DefaultLogger::get()->error("Unexpected EOF/EOL while parsing bone index");
+ SMDI_PARSE_RETURN;
+ }
+ if (iBone >= asBones.size())
+ {
+ LogErrorNoThrow("Bone index in skeleton section is out of range");
+ SMDI_PARSE_RETURN;
+ }
+ SMD::Bone& bone = asBones[iBone];
+
+ bone.sAnim.asKeys.push_back(SMD::Bone::Animation::MatrixKey());
+ SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back();
+
+ key.dTime = (double)iTime;
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z");
+ SMDI_PARSE_RETURN;
+ }
+ // build the transformation matrix of the key
+ key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z);
+ {
+ aiMatrix4x4 mTemp;
+ mTemp.a4 = vPos.x;
+ mTemp.b4 = vPos.y;
+ mTemp.c4 = vPos.z;
+ key.matrix = key.matrix * mTemp;
+ }
+
+ // go to the beginning of the next line
+ SMDI_PARSE_RETURN;
}
// ------------------------------------------------------------------------------------------------
// Parse a triangle
void SMDImporter::ParseTriangle(const char* szCurrent,
- const char** szCurrentOut)
+ const char** szCurrentOut)
{
- asTriangles.push_back(SMD::Face());
- SMD::Face& face = asTriangles.back();
-
- if(!SkipSpaces(szCurrent,&szCurrent))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle");
- return;
- }
-
- // read the texture file name
- const char* szLast = szCurrent;
- while (!IsSpaceOrNewLine(*szCurrent++));
-
- // ... and get the index that belongs to this file name
- face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast));
-
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
-
- // load three vertices
- for (unsigned int iVert = 0; iVert < 3;++iVert)
- {
- ParseVertex(szCurrent,&szCurrent,
- face.avVertices[iVert]);
- }
- *szCurrentOut = szCurrent;
+ asTriangles.push_back(SMD::Face());
+ SMD::Face& face = asTriangles.back();
+
+ if(!SkipSpaces(szCurrent,&szCurrent))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle");
+ return;
+ }
+
+ // read the texture file name
+ const char* szLast = szCurrent;
+ while (!IsSpaceOrNewLine(*szCurrent++));
+
+ // ... and get the index that belongs to this file name
+ face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast));
+
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+
+ // load three vertices
+ for (unsigned int iVert = 0; iVert < 3;++iVert)
+ {
+ ParseVertex(szCurrent,&szCurrent,
+ face.avVertices[iVert]);
+ }
+ *szCurrentOut = szCurrent;
}
// ------------------------------------------------------------------------------------------------
// Parse a float
bool SMDImporter::ParseFloat(const char* szCurrent,
- const char** szCurrentOut, float& out)
+ const char** szCurrentOut, float& out)
{
- if(!SkipSpaces(&szCurrent))
- return false;
+ if(!SkipSpaces(&szCurrent))
+ return false;
- *szCurrentOut = fast_atoreal_move<float>(szCurrent,out);
- return true;
+ *szCurrentOut = fast_atoreal_move<float>(szCurrent,out);
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Parse an unsigned int
bool SMDImporter::ParseUnsignedInt(const char* szCurrent,
- const char** szCurrentOut, unsigned int& out)
+ const char** szCurrentOut, unsigned int& out)
{
- if(!SkipSpaces(&szCurrent))
- return false;
+ if(!SkipSpaces(&szCurrent))
+ return false;
- out = strtoul10(szCurrent,szCurrentOut);
- return true;
+ out = strtoul10(szCurrent,szCurrentOut);
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Parse a signed int
bool SMDImporter::ParseSignedInt(const char* szCurrent,
- const char** szCurrentOut, int& out)
+ const char** szCurrentOut, int& out)
{
- if(!SkipSpaces(&szCurrent))
- return false;
+ if(!SkipSpaces(&szCurrent))
+ return false;
- out = strtol10(szCurrent,szCurrentOut);
- return true;
+ out = strtol10(szCurrent,szCurrentOut);
+ return true;
}
// ------------------------------------------------------------------------------------------------
// Parse a vertex
void SMDImporter::ParseVertex(const char* szCurrent,
- const char** szCurrentOut, SMD::Vertex& vertex,
- bool bVASection /*= false*/)
+ const char** szCurrentOut, SMD::Vertex& vertex,
+ bool bVASection /*= false*/)
{
- if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent))
- {
- SkipSpacesAndLineEnd(szCurrent,&szCurrent);
- return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection);
- }
- if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z");
- SMDI_PARSE_RETURN;
- }
-
- if (bVASection)SMDI_PARSE_RETURN;
-
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x");
- SMDI_PARSE_RETURN;
- }
- if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y))
- {
- LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y");
- SMDI_PARSE_RETURN;
- }
-
- // now read the number of bones affecting this vertex
- // all elements from now are fully optional, we don't need them
- unsigned int iSize = 0;
- if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize))SMDI_PARSE_RETURN;
- vertex.aiBoneLinks.resize(iSize,std::pair<unsigned int, float>(0,0.0f));
-
- for (std::vector<std::pair<unsigned int, float> >::iterator
- i = vertex.aiBoneLinks.begin();
- i != vertex.aiBoneLinks.end();++i)
- {
- if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first))
- SMDI_PARSE_RETURN;
- if(!ParseFloat(szCurrent,&szCurrent,(*i).second))
- SMDI_PARSE_RETURN;
- }
-
- // go to the beginning of the next line
- SMDI_PARSE_RETURN;
+ if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent))
+ {
+ SkipSpacesAndLineEnd(szCurrent,&szCurrent);
+ return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection);
+ }
+ if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z");
+ SMDI_PARSE_RETURN;
+ }
+
+ if (bVASection)SMDI_PARSE_RETURN;
+
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x");
+ SMDI_PARSE_RETURN;
+ }
+ if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y))
+ {
+ LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y");
+ SMDI_PARSE_RETURN;
+ }
+
+ // now read the number of bones affecting this vertex
+ // all elements from now are fully optional, we don't need them
+ unsigned int iSize = 0;
+ if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize))SMDI_PARSE_RETURN;
+ vertex.aiBoneLinks.resize(iSize,std::pair<unsigned int, float>(0,0.0f));
+
+ for (std::vector<std::pair<unsigned int, float> >::iterator
+ i = vertex.aiBoneLinks.begin();
+ i != vertex.aiBoneLinks.end();++i)
+ {
+ if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first))
+ SMDI_PARSE_RETURN;
+ if(!ParseFloat(szCurrent,&szCurrent,(*i).second))
+ SMDI_PARSE_RETURN;
+ }
+
+ // go to the beginning of the next line
+ SMDI_PARSE_RETURN;
}
#endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER
diff --git a/src/3rdparty/assimp/code/SMDLoader.h b/src/3rdparty/assimp/code/SMDLoader.h
index f636be9a9..0b069cc25 100644
--- a/src/3rdparty/assimp/code/SMDLoader.h
+++ b/src/3rdparty/assimp/code/SMDLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,23 +23,23 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file SMDLoader.h
- * @brief Defintion of the Valve SMD file format
+ * @brief Definition of the Valve SMD file format
*/
#ifndef AI_SMDLOADER_H_INCLUDED
@@ -50,39 +50,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h"
// public Assimp headers
-#include "../include/assimp/types.h"
-#include "../include/assimp/texture.h"
-#include "../include/assimp/anim.h"
-#include "../include/assimp/material.h"
+#include <assimp/types.h>
+#include <assimp/texture.h>
+#include <assimp/anim.h>
+#include <assimp/material.h>
+
struct aiNode;
// STL headers
#include <vector>
-namespace Assimp {
-
+namespace Assimp {
-namespace SMD {
+namespace SMD {
// ---------------------------------------------------------------------------
/** Data structure for a vertex in a SMD file
*/
struct Vertex
{
- Vertex() : iParentNode(UINT_MAX)
- {}
+ Vertex() : iParentNode(UINT_MAX)
+ {}
- //! Vertex position, normal and texture coordinate
- aiVector3D pos,nor,uv;
+ //! Vertex position, normal and texture coordinate
+ aiVector3D pos,nor,uv;
- //! Vertex parent node
- unsigned int iParentNode;
+ //! Vertex parent node
+ unsigned int iParentNode;
- //! Links to bones: pair.first is the bone index,
- //! pair.second is the vertex weight.
- //! WARN: The remaining weight (to reach 1.0f) is assigned
- //! to the parent node/bone
- std::vector<std::pair<unsigned int, float> > aiBoneLinks;
+ //! Links to bones: pair.first is the bone index,
+ //! pair.second is the vertex weight.
+ //! WARN: The remaining weight (to reach 1.0f) is assigned
+ //! to the parent node/bone
+ std::vector<std::pair<unsigned int, float> > aiBoneLinks;
};
// ---------------------------------------------------------------------------
@@ -90,14 +90,14 @@ struct Vertex
*/
struct Face
{
- Face() : iTexture(0x0)
- {}
+ Face() : iTexture(0x0)
+ {}
- //! Texture index for the face
- unsigned int iTexture;
+ //! Texture index for the face
+ unsigned int iTexture;
- //! The three vertices of the face
- Vertex avVertices[3];
+ //! The three vertices of the face
+ Vertex avVertices[3];
};
// ---------------------------------------------------------------------------
@@ -105,64 +105,65 @@ struct Face
*/
struct Bone
{
- //! Default constructor
- Bone() : iParent(UINT_MAX), bIsUsed(false)
- {
- }
+ //! Default constructor
+ Bone() : iParent(UINT_MAX), bIsUsed(false)
+ {
+ }
- //! Destructor
- ~Bone()
- {
- }
+ //! Destructor
+ ~Bone()
+ {
+ }
- //! Name of the bone
- std::string mName;
+ //! Name of the bone
+ std::string mName;
- //! Parent of the bone
- uint32_t iParent;
+ //! Parent of the bone
+ uint32_t iParent;
- //! Animation of the bone
- struct Animation
- {
- //! Public default constructor
- Animation()
- {
- asKeys.reserve(20);
- }
+ //! Animation of the bone
+ struct Animation
+ {
+ //! Public default constructor
+ Animation()
+ : iFirstTimeKey()
+ {
+ asKeys.reserve(20);
+ }
- //! Data structure for a matrix key
- struct MatrixKey
- {
- //! Matrix at this time
- aiMatrix4x4 matrix;
+ //! Data structure for a matrix key
+ struct MatrixKey
+ {
+ //! Matrix at this time
+ aiMatrix4x4 matrix;
- //! Absolute transformation matrix
- aiMatrix4x4 matrixAbsolute;
+ //! Absolute transformation matrix
+ aiMatrix4x4 matrixAbsolute;
- //! Position
- aiVector3D vPos;
+ //! Position
+ aiVector3D vPos;
- //! Rotation (euler angles)
- aiVector3D vRot;
+ //! Rotation (euler angles)
+ aiVector3D vRot;
- //! Current time. may be negative, this
- //! will be fixed later
- double dTime;
- };
+ //! Current time. may be negative, this
+ //! will be fixed later
+ double dTime;
+ };
- //! Index of the key with the smallest time value
- uint32_t iFirstTimeKey;
+ //! Index of the key with the smallest time value
+ uint32_t iFirstTimeKey;
- //! Array of matrix keys
- std::vector<MatrixKey> asKeys;
+ //! Array of matrix keys
+ std::vector<MatrixKey> asKeys;
- } sAnim;
+ } sAnim;
- //! Offset matrix of the bone
- aiMatrix4x4 mOffsetMatrix;
+ //! Offset matrix of the bone
+ aiMatrix4x4 mOffsetMatrix;
- //! true if the bone is referenced by at least one mesh
- bool bIsUsed;
+ //! true if the bone is referenced by at least one mesh
+ bool bIsUsed;
};
} //! namespace SMD
@@ -173,241 +174,241 @@ struct Bone
class SMDImporter : public BaseImporter
{
public:
- SMDImporter();
- ~SMDImporter();
+ SMDImporter();
+ ~SMDImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
- // -------------------------------------------------------------------
- /** Called prior to ReadFile().
- * The function is a request to the importer to update its configuration
- * basing on the Importer's configuration property list.
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** Called prior to ReadFile().
+ * The function is a request to the importer to update its configuration
+ * basing on the Importer's configuration property list.
+ */
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
protected:
- // -------------------------------------------------------------------
- /** Parse the SMD file and create the output scene
- */
- void ParseFile();
-
- // -------------------------------------------------------------------
- /** Parse the triangles section of the SMD file
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives a pointer to the heading line of
- * the next section (or to EOF)
- */
- void ParseTrianglesSection(const char* szCurrent,
- const char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Parse the vertex animation section in VTA files
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives a pointer to the heading line of
- * the next section (or to EOF)
- */
- void ParseVASection(const char* szCurrent,
- const char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Parse the nodes section of the SMD file
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives a pointer to the heading line of
- * the next section (or to EOF)
- */
- void ParseNodesSection(const char* szCurrent,
- const char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Parse the skeleton section of the SMD file
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives a pointer to the heading line of
- * the next section (or to EOF)
- */
- void ParseSkeletonSection(const char* szCurrent,
- const char** szCurrentOut);
-
- // -------------------------------------------------------------------
- /** Parse a single triangle in the SMD file
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives the output cursor position
- */
- void ParseTriangle(const char* szCurrent,
- const char** szCurrentOut);
-
-
- // -------------------------------------------------------------------
- /** Parse a single vertex in the SMD file
- * \param szCurrent Current position in the file. Points to the first
- * data line of the section.
- * \param szCurrentOut Receives the output cursor position
- * \param vertex Vertex to be filled
- */
- void ParseVertex(const char* szCurrent,
- const char** szCurrentOut, SMD::Vertex& vertex,
- bool bVASection = false);
-
- // -------------------------------------------------------------------
- /** Get the index of a texture. If the texture was not yet known
- * it will be added to the internal texture list.
- * \param filename Name of the texture
- * \return Value texture index
- */
- unsigned int GetTextureIndex(const std::string& filename);
-
- // -------------------------------------------------------------------
- /** Computes absolute bone transformations
- * All output transformations are in worldspace.
- */
- void ComputeAbsoluteBoneTransformations();
-
-
- // -------------------------------------------------------------------
- /** Parse a line in the skeleton section
- */
- void ParseSkeletonElement(const char* szCurrent,
- const char** szCurrentOut,int iTime);
-
- // -------------------------------------------------------------------
- /** Parse a line in the nodes section
- */
- void ParseNodeInfo(const char* szCurrent,
- const char** szCurrentOut);
-
-
- // -------------------------------------------------------------------
- /** Parse a floating-point value
- */
- bool ParseFloat(const char* szCurrent,
- const char** szCurrentOut, float& out);
-
- // -------------------------------------------------------------------
- /** Parse an unsigned integer. There may be no sign!
- */
- bool ParseUnsignedInt(const char* szCurrent,
- const char** szCurrentOut, unsigned int& out);
-
- // -------------------------------------------------------------------
- /** Parse a signed integer. Signs (+,-) are handled.
- */
- bool ParseSignedInt(const char* szCurrent,
- const char** szCurrentOut, int& out);
-
- // -------------------------------------------------------------------
- /** Fix invalid time values in the file
- */
- void FixTimeValues();
-
- // -------------------------------------------------------------------
- /** Add all children of a bone as subnodes to a node
- * \param pcNode Parent node
- * \param iParent Parent bone index
- */
- void AddBoneChildren(aiNode* pcNode, uint32_t iParent);
-
- // -------------------------------------------------------------------
- /** Build output meshes/materials/nodes/animations
- */
- void CreateOutputMeshes();
- void CreateOutputNodes();
- void CreateOutputAnimations();
- void CreateOutputMaterials();
-
-
- // -------------------------------------------------------------------
- /** Print a log message together with the current line number
- */
- void LogErrorNoThrow(const char* msg);
- void LogWarning(const char* msg);
-
-
- // -------------------------------------------------------------------
- inline bool SkipLine( const char* in, const char** out)
- {
- Assimp::SkipLine(in,out);
- ++iLineNumber;
- return true;
- }
- // -------------------------------------------------------------------
- inline bool SkipSpacesAndLineEnd( const char* in, const char** out)
- {
- ++iLineNumber;
- return Assimp::SkipSpacesAndLineEnd(in,out);
- }
+ // -------------------------------------------------------------------
+ /** Parse the SMD file and create the output scene
+ */
+ void ParseFile();
+
+ // -------------------------------------------------------------------
+ /** Parse the triangles section of the SMD file
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives a pointer to the heading line of
+ * the next section (or to EOF)
+ */
+ void ParseTrianglesSection(const char* szCurrent,
+ const char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Parse the vertex animation section in VTA files
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives a pointer to the heading line of
+ * the next section (or to EOF)
+ */
+ void ParseVASection(const char* szCurrent,
+ const char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Parse the nodes section of the SMD file
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives a pointer to the heading line of
+ * the next section (or to EOF)
+ */
+ void ParseNodesSection(const char* szCurrent,
+ const char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Parse the skeleton section of the SMD file
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives a pointer to the heading line of
+ * the next section (or to EOF)
+ */
+ void ParseSkeletonSection(const char* szCurrent,
+ const char** szCurrentOut);
+
+ // -------------------------------------------------------------------
+ /** Parse a single triangle in the SMD file
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives the output cursor position
+ */
+ void ParseTriangle(const char* szCurrent,
+ const char** szCurrentOut);
+
+
+ // -------------------------------------------------------------------
+ /** Parse a single vertex in the SMD file
+ * \param szCurrent Current position in the file. Points to the first
+ * data line of the section.
+ * \param szCurrentOut Receives the output cursor position
+ * \param vertex Vertex to be filled
+ */
+ void ParseVertex(const char* szCurrent,
+ const char** szCurrentOut, SMD::Vertex& vertex,
+ bool bVASection = false);
+
+ // -------------------------------------------------------------------
+ /** Get the index of a texture. If the texture was not yet known
+ * it will be added to the internal texture list.
+ * \param filename Name of the texture
+ * \return Value texture index
+ */
+ unsigned int GetTextureIndex(const std::string& filename);
+
+ // -------------------------------------------------------------------
+ /** Computes absolute bone transformations
+ * All output transformations are in worldspace.
+ */
+ void ComputeAbsoluteBoneTransformations();
+
+
+ // -------------------------------------------------------------------
+ /** Parse a line in the skeleton section
+ */
+ void ParseSkeletonElement(const char* szCurrent,
+ const char** szCurrentOut,int iTime);
+
+ // -------------------------------------------------------------------
+ /** Parse a line in the nodes section
+ */
+ void ParseNodeInfo(const char* szCurrent,
+ const char** szCurrentOut);
+
+
+ // -------------------------------------------------------------------
+ /** Parse a floating-point value
+ */
+ bool ParseFloat(const char* szCurrent,
+ const char** szCurrentOut, float& out);
+
+ // -------------------------------------------------------------------
+ /** Parse an unsigned integer. There may be no sign!
+ */
+ bool ParseUnsignedInt(const char* szCurrent,
+ const char** szCurrentOut, unsigned int& out);
+
+ // -------------------------------------------------------------------
+ /** Parse a signed integer. Signs (+,-) are handled.
+ */
+ bool ParseSignedInt(const char* szCurrent,
+ const char** szCurrentOut, int& out);
+
+ // -------------------------------------------------------------------
+ /** Fix invalid time values in the file
+ */
+ void FixTimeValues();
+
+ // -------------------------------------------------------------------
+ /** Add all children of a bone as subnodes to a node
+ * \param pcNode Parent node
+ * \param iParent Parent bone index
+ */
+ void AddBoneChildren(aiNode* pcNode, uint32_t iParent);
+
+ // -------------------------------------------------------------------
+ /** Build output meshes/materials/nodes/animations
+ */
+ void CreateOutputMeshes();
+ void CreateOutputNodes();
+ void CreateOutputAnimations();
+ void CreateOutputMaterials();
+
+
+ // -------------------------------------------------------------------
+ /** Print a log message together with the current line number
+ */
+ void LogErrorNoThrow(const char* msg);
+ void LogWarning(const char* msg);
+
+
+ // -------------------------------------------------------------------
+ inline bool SkipLine( const char* in, const char** out)
+ {
+ Assimp::SkipLine(in,out);
+ ++iLineNumber;
+ return true;
+ }
+ // -------------------------------------------------------------------
+ inline bool SkipSpacesAndLineEnd( const char* in, const char** out)
+ {
+ ++iLineNumber;
+ return Assimp::SkipSpacesAndLineEnd(in,out);
+ }
private:
- /** Configuration option: frame to be loaded */
- unsigned int configFrameID;
+ /** Configuration option: frame to be loaded */
+ unsigned int configFrameID;
- /** Buffer to hold the loaded file */
- const char* mBuffer;
+ /** Buffer to hold the loaded file */
+ const char* mBuffer;
- /** Output scene to be filled
- */
- aiScene* pScene;
+ /** Output scene to be filled
+ */
+ aiScene* pScene;
- /** Size of the input file in bytes
- */
- unsigned int iFileSize;
+ /** Size of the input file in bytes
+ */
+ unsigned int iFileSize;
- /** Array of textures found in the file
- */
- std::vector<std::string> aszTextures;
+ /** Array of textures found in the file
+ */
+ std::vector<std::string> aszTextures;
- /** Array of triangles found in the file
- */
- std::vector<SMD::Face> asTriangles;
+ /** Array of triangles found in the file
+ */
+ std::vector<SMD::Face> asTriangles;
- /** Array of bones found in the file
- */
- std::vector<SMD::Bone> asBones;
+ /** Array of bones found in the file
+ */
+ std::vector<SMD::Bone> asBones;
- /** Smallest frame index found in the skeleton
- */
- int iSmallestFrame;
+ /** Smallest frame index found in the skeleton
+ */
+ int iSmallestFrame;
- /** Length of the whole animation, in frames
- */
- double dLengthOfAnim;
+ /** Length of the whole animation, in frames
+ */
+ double dLengthOfAnim;
- /** Do we have texture coordinates?
- */
- bool bHasUVs;
+ /** Do we have texture coordinates?
+ */
+ bool bHasUVs;
- /** Current line numer
- */
- unsigned int iLineNumber;
+ /** Current line numer
+ */
+ unsigned int iLineNumber;
};
diff --git a/src/3rdparty/assimp/code/STEPFile.h b/src/3rdparty/assimp/code/STEPFile.h
index b06554e76..e09add1eb 100644
--- a/src/3rdparty/assimp/code/STEPFile.h
+++ b/src/3rdparty/assimp/code/STEPFile.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,28 +41,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_STEPFILE_H
#define INCLUDED_AI_STEPFILE_H
-#include <boost/noncopyable.hpp>
#include <bitset>
#include <memory>
#include <typeinfo>
+#include <vector>
+#include <map>
+#include <set>
+
+#include "FBXDocument.h" //ObjectMap::value_type
+#include <assimp/DefaultLogger.hpp>
//
#if _MSC_VER > 1500 || (defined __GNUC___)
-# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
-# else
-# define step_unordered_map map
-# define step_unordered_multimap multimap
+# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
+# else
+# define step_unordered_map map
+# define step_unordered_multimap multimap
#endif
#ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP
-# include <unordered_map>
-# if _MSC_VER > 1600
-# define step_unordered_map unordered_map
-# define step_unordered_multimap unordered_multimap
-# else
-# define step_unordered_map tr1::unordered_map
-# define step_unordered_multimap tr1::unordered_multimap
-# endif
+# include <unordered_map>
+# if _MSC_VER > 1600
+# define step_unordered_map unordered_map
+# define step_unordered_multimap unordered_multimap
+# else
+# define step_unordered_map tr1::unordered_map
+# define step_unordered_multimap tr1::unordered_multimap
+# endif
#endif
#include "LineSplitter.h"
@@ -82,33 +87,33 @@ namespace Assimp {
namespace STEP {
- namespace EXPRESS {
-
- // base data types known by EXPRESS schemata - any custom data types will derive one of those
- class DataType;
- class UNSET; /*: public DataType */
- class ISDERIVED; /*: public DataType */
- // class REAL; /*: public DataType */
- class ENUM; /*: public DataType */
- // class STRING; /*: public DataType */
- // class INTEGER; /*: public DataType */
- class ENTITY; /*: public DataType */
- class LIST; /*: public DataType */
- // class SELECT; /*: public DataType */
-
- // a conversion schema is not exactly an EXPRESS schema, rather it
- // is a list of pointers to conversion functions to build up the
- // object tree from an input file.
- class ConversionSchema;
- }
-
- struct HeaderInfo;
- class Object;
- class LazyObject;
- class DB;
-
-
- typedef Object* (*ConvertObjectProc)(const DB& db, const EXPRESS::LIST& params);
+ namespace EXPRESS {
+
+ // base data types known by EXPRESS schemata - any custom data types will derive one of those
+ class DataType;
+ class UNSET; /*: public DataType */
+ class ISDERIVED; /*: public DataType */
+ // class REAL; /*: public DataType */
+ class ENUM; /*: public DataType */
+ // class STRING; /*: public DataType */
+ // class INTEGER; /*: public DataType */
+ class ENTITY; /*: public DataType */
+ class LIST; /*: public DataType */
+ // class SELECT; /*: public DataType */
+
+ // a conversion schema is not exactly an EXPRESS schema, rather it
+ // is a list of pointers to conversion functions to build up the
+ // object tree from an input file.
+ class ConversionSchema;
+ }
+
+ struct HeaderInfo;
+ class Object;
+ class LazyObject;
+ class DB;
+
+
+ typedef Object* (*ConvertObjectProc)(const DB& db, const EXPRESS::LIST& params);
}
// ********************************************************************************
@@ -116,902 +121,903 @@ namespace STEP {
namespace STEP {
- // -------------------------------------------------------------------------------
- /** Exception class used by the STEP loading & parsing code. It is typically
- * coupled with a line number. */
- // -------------------------------------------------------------------------------
- struct SyntaxError : DeadlyImportError
- {
- enum {
- LINE_NOT_SPECIFIED = 0xffffffffffffffffLL
- };
-
- SyntaxError (const std::string& s,uint64_t line = LINE_NOT_SPECIFIED);
- };
-
-
- // -------------------------------------------------------------------------------
- /** Exception class used by the STEP loading & parsing code when a type
- * error (i.e. an entity expects a string but receives a bool) occurs.
- * It is typically coupled with both an entity id and a line number.*/
- // -------------------------------------------------------------------------------
- struct TypeError : DeadlyImportError
- {
- enum {
- ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL
- };
-
- TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED);
- };
-
-
- // hack to make a given member template-dependent
- template <typename T, typename T2>
- T2& Couple(T2& in) {
- return in;
- }
-
-
- namespace EXPRESS {
-
- // -------------------------------------------------------------------------------
- //** Base class for all STEP data types */
- // -------------------------------------------------------------------------------
- class DataType
- {
- public:
-
- typedef boost::shared_ptr<const DataType> Out;
-
- public:
-
- virtual ~DataType() {
- }
-
- public:
-
- template <typename T>
- const T& To() const {
- return dynamic_cast<const T&>(*this);
- }
-
- template <typename T>
- T& To() {
- return dynamic_cast<T&>(*this);
- }
-
-
- template <typename T>
- const T* ToPtr() const {
- return dynamic_cast<const T*>(this);
- }
-
- template <typename T>
- T* ToPtr() {
- return dynamic_cast<T*>(this);
- }
-
- // utilities to deal with SELECT entities, which currently lack automatic
- // conversion support.
- template <typename T>
- const T& ResolveSelect(const DB& db) const {
- return Couple<T>(db).MustGetObject(To<EXPRESS::ENTITY>())->template To<T>();
- }
-
- template <typename T>
- const T* ResolveSelectPtr(const DB& db) const {
- const EXPRESS::ENTITY* e = ToPtr<EXPRESS::ENTITY>();
- return e?Couple<T>(db).MustGetObject(*e)->template ToPtr<T>():(const T*)0;
- }
-
- public:
-
- /** parse a variable from a string and set 'inout' to the character
- * behind the last consumed character. An optional schema enables,
- * if specified, automatic conversion of custom data types.
- *
- * @throw SyntaxError
- */
- static boost::shared_ptr<const EXPRESS::DataType> Parse(const char*& inout,
- uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
- const EXPRESS::ConversionSchema* schema = NULL);
-
- public:
- };
-
- typedef DataType SELECT;
- typedef DataType LOGICAL;
-
- // -------------------------------------------------------------------------------
- /** Sentinel class to represent explicitly unset (optional) fields ($) */
- // -------------------------------------------------------------------------------
- class UNSET : public DataType
- {
- public:
- private:
- };
-
- // -------------------------------------------------------------------------------
- /** Sentinel class to represent explicitly derived fields (*) */
- // -------------------------------------------------------------------------------
- class ISDERIVED : public DataType
- {
- public:
- private:
- };
-
- // -------------------------------------------------------------------------------
- /** Shared implementation for some of the primitive data type, i.e. int, float */
- // -------------------------------------------------------------------------------
- template <typename T>
- class PrimitiveDataType : public DataType
- {
- public:
-
- // This is the type that will ultimatively be used to
- // expose this data type to the user.
- typedef T Out;
-
- public:
-
- PrimitiveDataType() {}
- PrimitiveDataType(const T& val)
- : val(val)
- {}
-
- PrimitiveDataType(const PrimitiveDataType& o) {
- (*this) = o;
- }
-
-
- public:
-
- operator const T& () const {
- return val;
- }
-
- PrimitiveDataType& operator=(const PrimitiveDataType& o) {
- val = o.val;
- return *this;
- }
-
- protected:
- T val;
-
- };
-
- typedef PrimitiveDataType<int64_t> INTEGER;
- typedef PrimitiveDataType<double> REAL;
- typedef PrimitiveDataType<double> NUMBER;
- typedef PrimitiveDataType<std::string> STRING;
-
-
-
- // -------------------------------------------------------------------------------
- /** Generic base class for all enumerated types */
- // -------------------------------------------------------------------------------
- class ENUMERATION : public STRING
- {
- public:
-
- ENUMERATION (const std::string& val)
- : STRING(val)
- {}
-
- private:
- };
-
- typedef ENUMERATION BOOLEAN;
-
- // -------------------------------------------------------------------------------
- /** This is just a reference to an entity/object somewhere else */
- // -------------------------------------------------------------------------------
- class ENTITY : public PrimitiveDataType<uint64_t>
- {
- public:
-
- ENTITY(uint64_t val)
- : PrimitiveDataType<uint64_t>(val)
- {
- ai_assert(val!=0);
- }
-
- ENTITY()
- : PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED)
- {
- }
-
- private:
- };
-
- // -------------------------------------------------------------------------------
- /** Wrap any STEP aggregate: LIST, SET, ... */
- // -------------------------------------------------------------------------------
- class LIST : public DataType
- {
- public:
-
- // access a particular list index, throw std::range_error for wrong indices
- boost::shared_ptr<const DataType> operator[] (size_t index) const {
- return members[index];
- }
-
- size_t GetSize() const {
- return members.size();
- }
+ // -------------------------------------------------------------------------------
+ /** Exception class used by the STEP loading & parsing code. It is typically
+ * coupled with a line number. */
+ // -------------------------------------------------------------------------------
+ struct SyntaxError : DeadlyImportError
+ {
+ enum {
+ LINE_NOT_SPECIFIED = 0xffffffffffffffffLL
+ };
+
+ SyntaxError (const std::string& s,uint64_t line = LINE_NOT_SPECIFIED);
+ };
+
+
+ // -------------------------------------------------------------------------------
+ /** Exception class used by the STEP loading & parsing code when a type
+ * error (i.e. an entity expects a string but receives a bool) occurs.
+ * It is typically coupled with both an entity id and a line number.*/
+ // -------------------------------------------------------------------------------
+ struct TypeError : DeadlyImportError
+ {
+ enum {
+ ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL
+ };
+
+ TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED);
+ };
+
+
+ // hack to make a given member template-dependent
+ template <typename T, typename T2>
+ T2& Couple(T2& in) {
+ return in;
+ }
+
+
+ namespace EXPRESS {
+
+ // -------------------------------------------------------------------------------
+ //** Base class for all STEP data types */
+ // -------------------------------------------------------------------------------
+ class DataType
+ {
+ public:
+
+ typedef std::shared_ptr<const DataType> Out;
+
+ public:
+
+ virtual ~DataType() {
+ }
+
+ public:
+
+ template <typename T>
+ const T& To() const {
+ return dynamic_cast<const T&>(*this);
+ }
+
+ template <typename T>
+ T& To() {
+ return dynamic_cast<T&>(*this);
+ }
+
+
+ template <typename T>
+ const T* ToPtr() const {
+ return dynamic_cast<const T*>(this);
+ }
+
+ template <typename T>
+ T* ToPtr() {
+ return dynamic_cast<T*>(this);
+ }
+
+ // utilities to deal with SELECT entities, which currently lack automatic
+ // conversion support.
+ template <typename T>
+ const T& ResolveSelect(const DB& db) const {
+ return Couple<T>(db).MustGetObject(To<EXPRESS::ENTITY>())->template To<T>();
+ }
+
+ template <typename T>
+ const T* ResolveSelectPtr(const DB& db) const {
+ const EXPRESS::ENTITY* e = ToPtr<EXPRESS::ENTITY>();
+ return e?Couple<T>(db).MustGetObject(*e)->template ToPtr<T>():(const T*)0;
+ }
+
+ public:
+
+ /** parse a variable from a string and set 'inout' to the character
+ * behind the last consumed character. An optional schema enables,
+ * if specified, automatic conversion of custom data types.
+ *
+ * @throw SyntaxError
+ */
+ static std::shared_ptr<const EXPRESS::DataType> Parse(const char*& inout,
+ uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
+ const EXPRESS::ConversionSchema* schema = NULL);
+
+ public:
+ };
+
+ typedef DataType SELECT;
+ typedef DataType LOGICAL;
+
+ // -------------------------------------------------------------------------------
+ /** Sentinel class to represent explicitly unset (optional) fields ($) */
+ // -------------------------------------------------------------------------------
+ class UNSET : public DataType
+ {
+ public:
+ private:
+ };
+
+ // -------------------------------------------------------------------------------
+ /** Sentinel class to represent explicitly derived fields (*) */
+ // -------------------------------------------------------------------------------
+ class ISDERIVED : public DataType
+ {
+ public:
+ private:
+ };
+
+ // -------------------------------------------------------------------------------
+ /** Shared implementation for some of the primitive data type, i.e. int, float */
+ // -------------------------------------------------------------------------------
+ template <typename T>
+ class PrimitiveDataType : public DataType
+ {
+ public:
+
+ // This is the type that will ultimatively be used to
+ // expose this data type to the user.
+ typedef T Out;
+
+ public:
+
+ PrimitiveDataType() {}
+ PrimitiveDataType(const T& val)
+ : val(val)
+ {}
+
+ PrimitiveDataType(const PrimitiveDataType& o) {
+ (*this) = o;
+ }
+
+
+ public:
+
+ operator const T& () const {
+ return val;
+ }
+
+ PrimitiveDataType& operator=(const PrimitiveDataType& o) {
+ val = o.val;
+ return *this;
+ }
+
+ protected:
+ T val;
+
+ };
+
+ typedef PrimitiveDataType<int64_t> INTEGER;
+ typedef PrimitiveDataType<double> REAL;
+ typedef PrimitiveDataType<double> NUMBER;
+ typedef PrimitiveDataType<std::string> STRING;
+
+
+
+ // -------------------------------------------------------------------------------
+ /** Generic base class for all enumerated types */
+ // -------------------------------------------------------------------------------
+ class ENUMERATION : public STRING
+ {
+ public:
+
+ ENUMERATION (const std::string& val)
+ : STRING(val)
+ {}
- public:
-
- /** @see DaraType::Parse */
- static boost::shared_ptr<const EXPRESS::LIST> Parse(const char*& inout,
- uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
- const EXPRESS::ConversionSchema* schema = NULL);
+ private:
+ };
+
+ typedef ENUMERATION BOOLEAN;
+ // -------------------------------------------------------------------------------
+ /** This is just a reference to an entity/object somewhere else */
+ // -------------------------------------------------------------------------------
+ class ENTITY : public PrimitiveDataType<uint64_t>
+ {
+ public:
+
+ ENTITY(uint64_t val)
+ : PrimitiveDataType<uint64_t>(val)
+ {
+ ai_assert(val!=0);
+ }
- private:
- typedef std::vector< boost::shared_ptr<const DataType> > MemberList;
- MemberList members;
- };
+ ENTITY()
+ : PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED)
+ {
+ }
+ private:
+ };
- // -------------------------------------------------------------------------------
- /* Not exactly a full EXPRESS schema but rather a list of conversion functions
- * to extract valid C++ objects out of a STEP file. Those conversion functions
- * may, however, perform further schema validations. */
- // -------------------------------------------------------------------------------
- class ConversionSchema
- {
+ // -------------------------------------------------------------------------------
+ /** Wrap any STEP aggregate: LIST, SET, ... */
+ // -------------------------------------------------------------------------------
+ class LIST : public DataType
+ {
+ public:
- public:
+ // access a particular list index, throw std::range_error for wrong indices
+ std::shared_ptr<const DataType> operator[] (size_t index) const {
+ return members[index];
+ }
- struct SchemaEntry {
- SchemaEntry(const char* name,ConvertObjectProc func)
- : name(name)
- , func(func)
- {}
-
- const char* name;
- ConvertObjectProc func;
- };
+ size_t GetSize() const {
+ return members.size();
+ }
- typedef std::map<std::string,ConvertObjectProc> ConverterMap;
-
- public:
+ public:
- template <size_t N>
- explicit ConversionSchema( const SchemaEntry (& schemas)[N]) {
- *this = schemas;
- }
-
- ConversionSchema() {}
-
- public:
-
- ConvertObjectProc GetConverterProc(const std::string& name) const {
- ConverterMap::const_iterator it = converters.find(name);
- return it == converters.end() ? NULL : (*it).second;
- }
+ /** @see DaraType::Parse */
+ static std::shared_ptr<const EXPRESS::LIST> Parse(const char*& inout,
+ uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
+ const EXPRESS::ConversionSchema* schema = NULL);
- bool IsKnownToken(const std::string& name) const {
- return converters.find(name) != converters.end();
- }
+ private:
+ typedef std::vector< std::shared_ptr<const DataType> > MemberList;
+ MemberList members;
+ };
- const char* GetStaticStringForToken(const std::string& token) const {
- ConverterMap::const_iterator it = converters.find(token);
- return it == converters.end() ? NULL : (*it).first.c_str();
- }
+ // -------------------------------------------------------------------------------
+ /* Not exactly a full EXPRESS schema but rather a list of conversion functions
+ * to extract valid C++ objects out of a STEP file. Those conversion functions
+ * may, however, perform further schema validations. */
+ // -------------------------------------------------------------------------------
+ class ConversionSchema
+ {
- template <size_t N>
- const ConversionSchema& operator=( const SchemaEntry (& schemas)[N]) {
- for(size_t i = 0; i < N; ++i ) {
- const SchemaEntry& schema = schemas[i];
- converters[schema.name] = schema.func;
- }
- return *this;
- }
-
- private:
-
- ConverterMap converters;
- };
- }
-
-
-
- // ------------------------------------------------------------------------------
- /** Bundle all the relevant info from a STEP header, parts of which may later
- * be plainly dumped to the logfile, whereas others may help the caller pick an
- * appropriate loading strategy.*/
- // ------------------------------------------------------------------------------
- struct HeaderInfo
- {
- std::string timestamp;
- std::string app;
- std::string fileSchema;
- };
-
-
- // ------------------------------------------------------------------------------
- /** Base class for all concrete object instances */
- // ------------------------------------------------------------------------------
- class Object
- {
- public:
-
- virtual ~Object() {}
- Object(const char* classname = "unknown")
- : classname(classname) {}
-
- public:
-
- // utilities to simplify casting to concrete types
- template <typename T>
- const T& To() const {
- return dynamic_cast<const T&>(*this);
- }
-
- template <typename T>
- T& To() {
- return dynamic_cast<T&>(*this);
- }
-
-
- template <typename T>
- const T* ToPtr() const {
- return dynamic_cast<const T*>(this);
- }
-
- template <typename T>
- T* ToPtr() {
- return dynamic_cast<T*>(this);
- }
-
- public:
-
- uint64_t GetID() const {
- return id;
- }
-
- std::string GetClassName() const {
- return classname;
- }
-
- void SetID(uint64_t newval) {
- id = newval;
- }
-
- private:
- uint64_t id;
- const char* const classname;
- };
-
-
- template <typename T>
- size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in);
- // (intentionally undefined)
-
-
- // ------------------------------------------------------------------------------
- /** CRTP shared base class for use by concrete entity implementation classes */
- // ------------------------------------------------------------------------------
- template <typename TDerived, size_t arg_count>
- struct ObjectHelper : virtual Object
- {
- ObjectHelper() : aux_is_derived(0) {}
-
- static Object* Construct(const STEP::DB& db, const EXPRESS::LIST& params) {
- // make sure we don't leak if Fill() throws an exception
- std::auto_ptr<TDerived> impl(new TDerived());
-
- // GenericFill<T> is undefined so we need to have a specialization
- const size_t num_args = GenericFill<TDerived>(db,params,&*impl);
- (void)num_args;
-
- // the following check is commented because it will always trigger if
- // parts of the entities are generated with dummy wrapper code.
- // This is currently done to reduce the size of the loader
- // code.
- //if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") {
- // DefaultLogger::get()->debug("STEP: not all parameters consumed");
- //}
- return impl.release();
- }
-
- // note that this member always exists multiple times within the hierarchy
- // of an individual object, so any access to it must be disambiguated.
- std::bitset<arg_count> aux_is_derived;
- };
-
- // ------------------------------------------------------------------------------
- /** Class template used to represent OPTIONAL data members in the converted schema */
- // ------------------------------------------------------------------------------
- template <typename T>
- struct Maybe
- {
- Maybe() : have() {}
- explicit Maybe(const T& ptr) : ptr(ptr), have(true) {
- }
-
-
- void flag_invalid() {
- have = false;
- }
-
- void flag_valid() {
- have = true;
- }
-
-
- bool operator! () const {
- return !have;
- }
-
- operator bool() const {
- return have;
- }
-
- operator const T&() const {
- return Get();
- }
-
- const T& Get() const {
- ai_assert(have);
- return ptr;
- }
-
- Maybe& operator=(const T& _ptr) {
- ptr = _ptr;
- have = true;
- return *this;
- }
-
- private:
-
- template <typename T2> friend struct InternGenericConvert;
-
- operator T&() {
- return ptr;
- }
-
- T ptr;
- bool have;
- };
-
- // ------------------------------------------------------------------------------
- /** A LazyObject is created when needed. Before this happens, we just keep
- the text line that contains the object definition. */
- // -------------------------------------------------------------------------------
- class LazyObject : public boost::noncopyable
- {
- friend class DB;
- public:
-
- LazyObject(DB& db, uint64_t id, uint64_t line, const char* type,const char* args);
- ~LazyObject();
-
- public:
-
- Object& operator * () {
- if (!obj) {
- LazyInit();
- ai_assert(obj);
- }
- return *obj;
- }
-
- const Object& operator * () const {
- if (!obj) {
- LazyInit();
- ai_assert(obj);
- }
- return *obj;
- }
-
- template <typename T>
- const T& To() const {
- return dynamic_cast<const T&>( **this );
- }
-
- template <typename T>
- T& To() {
- return dynamic_cast<T&>( **this );
- }
-
- template <typename T>
- const T* ToPtr() const {
- return dynamic_cast<const T*>( &**this );
- }
-
- template <typename T>
- T* ToPtr() {
- return dynamic_cast<T*>( &**this );
- }
-
- Object* operator -> () {
- return &**this;
- }
-
- const Object* operator -> () const {
- return &**this;
- }
-
- bool operator== (const std::string& atype) const {
- return type == atype;
- }
-
- bool operator!= (const std::string& atype) const {
- return type != atype;
- }
-
- uint64_t GetID() const {
- return id;
- }
-
- private:
-
- void LazyInit() const;
-
- private:
-
- mutable uint64_t id;
- const char* const type;
- DB& db;
-
- mutable const char* args;
- mutable Object* obj;
- };
-
- template <typename T>
- inline bool operator==( boost::shared_ptr<LazyObject> lo, T whatever ) {
- return *lo == whatever; // XXX use std::forward if we have 0x
- }
-
- template <typename T>
- inline bool operator==( const std::pair<uint64_t, boost::shared_ptr<LazyObject> >& lo, T whatever ) {
- return *(lo.second) == whatever; // XXX use std::forward if we have 0x
- }
-
-
- // ------------------------------------------------------------------------------
- /** Class template used to represent lazily evaluated object references in the converted schema */
- // ------------------------------------------------------------------------------
- template <typename T>
- struct Lazy
- {
- typedef Lazy Out;
- Lazy(const LazyObject* obj = NULL) : obj(obj) {
- }
-
- operator const T*() const {
- return obj->ToPtr<T>();
- }
-
- operator const T&() const {
- return obj->To<T>();
- }
-
- const T& operator * () const {
- return obj->To<T>();
- }
-
- const T* operator -> () const {
- return &obj->To<T>();
- }
-
- const LazyObject* obj;
- };
-
- // ------------------------------------------------------------------------------
- /** Class template used to represent LIST and SET data members in the converted schema */
- // ------------------------------------------------------------------------------
- template <typename T, uint64_t min_cnt, uint64_t max_cnt=0uL>
- struct ListOf : public std::vector<typename T::Out>
- {
- typedef typename T::Out OutScalar;
- typedef ListOf Out;
-
-
- ListOf() {
- BOOST_STATIC_ASSERT(min_cnt <= max_cnt || !max_cnt);
- }
-
- };
-
-
- // ------------------------------------------------------------------------------
- template <typename TOut>
- struct PickBaseType {
- typedef EXPRESS::PrimitiveDataType<TOut> Type;
- };
-
- template <typename TOut>
- struct PickBaseType< Lazy<TOut> > {
- typedef EXPRESS::ENTITY Type;
- };
-
- template <> struct PickBaseType< boost::shared_ptr< const EXPRESS::DataType > >;
-
- // ------------------------------------------------------------------------------
- template <typename T>
- struct InternGenericConvert {
- void operator()(T& out, const boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) {
- try{
- out = dynamic_cast< const typename PickBaseType<T>::Type& > ( *in );
- }
- catch(std::bad_cast&) {
- throw TypeError("type error reading literal field");
- }
- }
- };
-
- template <>
- struct InternGenericConvert< boost::shared_ptr< const EXPRESS::DataType > > {
- void operator()(boost::shared_ptr< const EXPRESS::DataType >& out, const boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) {
- out = in;
- }
- };
-
- template <typename T>
- struct InternGenericConvert< Maybe<T> > {
- void operator()(Maybe<T>& out, const boost::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) {
- GenericConvert((T&)out,in,db);
- out.flag_valid();
- }
- };
-
- template <typename T,uint64_t min_cnt, uint64_t max_cnt>
- struct InternGenericConvertList {
- void operator()(ListOf<T, min_cnt, max_cnt>& out, const boost::shared_ptr< const EXPRESS::DataType >& inp_base, const STEP::DB& db) {
-
- const EXPRESS::LIST* inp = dynamic_cast<const EXPRESS::LIST*>(inp_base.get());
- if (!inp) {
- throw TypeError("type error reading aggregate");
- }
-
- // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended?
- if (max_cnt && inp->GetSize() > max_cnt) {
- DefaultLogger::get()->warn("too many aggregate elements");
- }
- else if (inp->GetSize() < min_cnt) {
- DefaultLogger::get()->warn("too few aggregate elements");
- }
-
- out.reserve(inp->GetSize());
- for(size_t i = 0; i < inp->GetSize(); ++i) {
-
- out.push_back( typename ListOf<T, min_cnt, max_cnt>::OutScalar() );
- try{
- GenericConvert(out.back(),(*inp)[i], db);
- }
- catch(const TypeError& t) {
- throw TypeError(t.what() +std::string(" of aggregate"));
- }
- }
- }
- };
-
- template <typename T>
- struct InternGenericConvert< Lazy<T> > {
- void operator()(Lazy<T>& out, const boost::shared_ptr< const EXPRESS::DataType >& in_base, const STEP::DB& db) {
- const EXPRESS::ENTITY* in = dynamic_cast<const EXPRESS::ENTITY*>(in_base.get());
- if (!in) {
- throw TypeError("type error reading entity");
- }
- out = Couple<T>(db).GetObject(*in);
- }
- };
-
- template <typename T1>
- inline void GenericConvert(T1& a, const boost::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
- return InternGenericConvert<T1>()(a,b,db);
- }
-
- template <typename T1,uint64_t N1, uint64_t N2>
- inline void GenericConvert(ListOf<T1,N1,N2>& a, const boost::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
- return InternGenericConvertList<T1,N1,N2>()(a,b,db);
- }
-
-
- // ------------------------------------------------------------------------------
- /** Lightweight manager class that holds the map of all objects in a
- * STEP file. DB's are exclusively maintained by the functions in
- * STEPFileReader.h*/
- // -------------------------------------------------------------------------------
- class DB
- {
- friend DB* ReadFileHeader(boost::shared_ptr<IOStream> stream);
- friend void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
- const char* const* types_to_track, size_t len,
- const char* const* inverse_indices_to_track, size_t len2
- );
-
- friend class LazyObject;
-
- public:
-
- // objects indexed by ID - this can grow pretty large (i.e some hundred million
- // entries), so use raw pointers to avoid *any* overhead.
- typedef std::map<uint64_t,const LazyObject* > ObjectMap;
-
- // objects indexed by their declarative type, but only for those that we truly want
- typedef std::set< const LazyObject*> ObjectSet;
- typedef std::map<std::string, ObjectSet > ObjectMapByType;
-
- // list of types for which to keep inverse indices for all references
- // that the respective objects keep.
- // the list keeps pointers to strings in static storage
- typedef std::set<const char*> InverseWhitelist;
-
- // references - for each object id the ids of all objects which reference it
- // this is used to simulate STEP inverse indices for selected types.
- typedef std::step_unordered_multimap<uint64_t, uint64_t > RefMap;
- typedef std::pair<RefMap::const_iterator,RefMap::const_iterator> RefMapRange;
-
- private:
-
- DB(boost::shared_ptr<StreamReaderLE> reader)
- : reader(reader)
- , splitter(*reader,true,true)
- , evaluated_count()
- {}
-
- public:
-
- ~DB() {
- BOOST_FOREACH(ObjectMap::value_type& o, objects) {
- delete o.second;
- }
- }
-
- public:
-
- uint64_t GetObjectCount() const {
- return objects.size();
- }
-
- uint64_t GetEvaluatedObjectCount() const {
- return evaluated_count;
- }
-
- const HeaderInfo& GetHeader() const {
- return header;
- }
-
- const EXPRESS::ConversionSchema& GetSchema() const {
- return *schema;
- }
-
- const ObjectMap& GetObjects() const {
- return objects;
- }
-
- const ObjectMapByType& GetObjectsByType() const {
- return objects_bytype;
- }
-
- const RefMap& GetRefs() const {
- return refs;
- }
-
-
- bool KeepInverseIndicesForType(const char* const type) const {
- return inv_whitelist.find(type) != inv_whitelist.end();
- }
-
-
- // get the yet unevaluated object record with a given id
- const LazyObject* GetObject(uint64_t id) const {
- const ObjectMap::const_iterator it = objects.find(id);
- if (it != objects.end()) {
- return (*it).second;
- }
- return NULL;
- }
-
-
- // get an arbitrary object out of the soup with the only restriction being its type.
- const LazyObject* GetObject(const std::string& type) const {
- const ObjectMapByType::const_iterator it = objects_bytype.find(type);
- if (it != objects_bytype.end() && (*it).second.size()) {
- return *(*it).second.begin();
- }
- return NULL;
- }
-
- // same, but raise an exception if the object doesn't exist and return a reference
- const LazyObject& MustGetObject(uint64_t id) const {
- const LazyObject* o = GetObject(id);
- if (!o) {
- throw TypeError("requested entity is not present",id);
- }
- return *o;
- }
+ public:
+
+ struct SchemaEntry {
+ SchemaEntry(const char* name,ConvertObjectProc func)
+ : name(name)
+ , func(func)
+ {}
+
+ const char* name;
+ ConvertObjectProc func;
+ };
+
+ typedef std::map<std::string,ConvertObjectProc> ConverterMap;
+
+ public:
+
+ template <size_t N>
+ explicit ConversionSchema( const SchemaEntry (& schemas)[N]) {
+ *this = schemas;
+ }
+
+ ConversionSchema() {}
+
+ public:
+
+ ConvertObjectProc GetConverterProc(const std::string& name) const {
+ ConverterMap::const_iterator it = converters.find(name);
+ return it == converters.end() ? NULL : (*it).second;
+ }
+
+
+ bool IsKnownToken(const std::string& name) const {
+ return converters.find(name) != converters.end();
+ }
+
+ const char* GetStaticStringForToken(const std::string& token) const {
+ ConverterMap::const_iterator it = converters.find(token);
+ return it == converters.end() ? NULL : (*it).first.c_str();
+ }
+
+
+ template <size_t N>
+ const ConversionSchema& operator=( const SchemaEntry (& schemas)[N]) {
+ for(size_t i = 0; i < N; ++i ) {
+ const SchemaEntry& schema = schemas[i];
+ converters[schema.name] = schema.func;
+ }
+ return *this;
+ }
+
+ private:
+
+ ConverterMap converters;
+ };
+ }
+
+
+
+ // ------------------------------------------------------------------------------
+ /** Bundle all the relevant info from a STEP header, parts of which may later
+ * be plainly dumped to the logfile, whereas others may help the caller pick an
+ * appropriate loading strategy.*/
+ // ------------------------------------------------------------------------------
+ struct HeaderInfo
+ {
+ std::string timestamp;
+ std::string app;
+ std::string fileSchema;
+ };
+
+
+ // ------------------------------------------------------------------------------
+ /** Base class for all concrete object instances */
+ // ------------------------------------------------------------------------------
+ class Object
+ {
+ public:
+
+ virtual ~Object() {}
+ Object(const char* classname = "unknown")
+ : classname(classname) {}
- const LazyObject& MustGetObject(const std::string& type) const {
- const LazyObject* o = GetObject(type);
- if (!o) {
- throw TypeError("requested entity of type "+type+"is not present");
- }
- return *o;
- }
+ public:
+
+ // utilities to simplify casting to concrete types
+ template <typename T>
+ const T& To() const {
+ return dynamic_cast<const T&>(*this);
+ }
+
+ template <typename T>
+ T& To() {
+ return dynamic_cast<T&>(*this);
+ }
+
+
+ template <typename T>
+ const T* ToPtr() const {
+ return dynamic_cast<const T*>(this);
+ }
+
+ template <typename T>
+ T* ToPtr() {
+ return dynamic_cast<T*>(this);
+ }
+
+ public:
+
+ uint64_t GetID() const {
+ return id;
+ }
+
+ std::string GetClassName() const {
+ return classname;
+ }
+
+ void SetID(uint64_t newval) {
+ id = newval;
+ }
+
+ private:
+ uint64_t id;
+ const char* const classname;
+ };
+
+
+ template <typename T>
+ size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in);
+ // (intentionally undefined)
+
+
+ // ------------------------------------------------------------------------------
+ /** CRTP shared base class for use by concrete entity implementation classes */
+ // ------------------------------------------------------------------------------
+ template <typename TDerived, size_t arg_count>
+ struct ObjectHelper : virtual Object
+ {
+ ObjectHelper() : aux_is_derived(0) {}
+
+ static Object* Construct(const STEP::DB& db, const EXPRESS::LIST& params) {
+ // make sure we don't leak if Fill() throws an exception
+ std::unique_ptr<TDerived> impl(new TDerived());
+
+ // GenericFill<T> is undefined so we need to have a specialization
+ const size_t num_args = GenericFill<TDerived>(db,params,&*impl);
+ (void)num_args;
+
+ // the following check is commented because it will always trigger if
+ // parts of the entities are generated with dummy wrapper code.
+ // This is currently done to reduce the size of the loader
+ // code.
+ //if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") {
+ // DefaultLogger::get()->debug("STEP: not all parameters consumed");
+ //}
+ return impl.release();
+ }
+
+ // note that this member always exists multiple times within the hierarchy
+ // of an individual object, so any access to it must be disambiguated.
+ std::bitset<arg_count> aux_is_derived;
+ };
+
+ // ------------------------------------------------------------------------------
+ /** Class template used to represent OPTIONAL data members in the converted schema */
+ // ------------------------------------------------------------------------------
+ template <typename T>
+ struct Maybe
+ {
+ Maybe() : have() {}
+ explicit Maybe(const T& ptr) : ptr(ptr), have(true) {
+ }
+
+
+ void flag_invalid() {
+ have = false;
+ }
+
+ void flag_valid() {
+ have = true;
+ }
+
+
+ bool operator! () const {
+ return !have;
+ }
+
+ operator bool() const {
+ return have;
+ }
+
+ operator const T&() const {
+ return Get();
+ }
+
+ const T& Get() const {
+ ai_assert(have);
+ return ptr;
+ }
+
+ Maybe& operator=(const T& _ptr) {
+ ptr = _ptr;
+ have = true;
+ return *this;
+ }
+
+ private:
+
+ template <typename T2> friend struct InternGenericConvert;
+
+ operator T&() {
+ return ptr;
+ }
+
+ T ptr;
+ bool have;
+ };
+
+ // ------------------------------------------------------------------------------
+ /** A LazyObject is created when needed. Before this happens, we just keep
+ the text line that contains the object definition. */
+ // -------------------------------------------------------------------------------
+ class LazyObject
+ {
+ friend class DB;
+ public:
+
+ LazyObject(DB& db, uint64_t id, uint64_t line, const char* type,const char* args);
+ ~LazyObject();
+
+ public:
+
+ Object& operator * () {
+ if (!obj) {
+ LazyInit();
+ ai_assert(obj);
+ }
+ return *obj;
+ }
+
+ const Object& operator * () const {
+ if (!obj) {
+ LazyInit();
+ ai_assert(obj);
+ }
+ return *obj;
+ }
+
+ template <typename T>
+ const T& To() const {
+ return dynamic_cast<const T&>( **this );
+ }
+
+ template <typename T>
+ T& To() {
+ return dynamic_cast<T&>( **this );
+ }
+
+ template <typename T>
+ const T* ToPtr() const {
+ return dynamic_cast<const T*>( &**this );
+ }
+
+ template <typename T>
+ T* ToPtr() {
+ return dynamic_cast<T*>( &**this );
+ }
+
+ Object* operator -> () {
+ return &**this;
+ }
+
+ const Object* operator -> () const {
+ return &**this;
+ }
+
+ bool operator== (const std::string& atype) const {
+ return type == atype;
+ }
+
+ bool operator!= (const std::string& atype) const {
+ return type != atype;
+ }
+
+ uint64_t GetID() const {
+ return id;
+ }
+
+ private:
+
+ void LazyInit() const;
+
+ private:
+
+ mutable uint64_t id;
+ const char* const type;
+ DB& db;
+
+ mutable const char* args;
+ mutable Object* obj;
+ };
+
+ template <typename T>
+ inline bool operator==( std::shared_ptr<LazyObject> lo, T whatever ) {
+ return *lo == whatever; // XXX use std::forward if we have 0x
+ }
+
+ template <typename T>
+ inline bool operator==( const std::pair<uint64_t, std::shared_ptr<LazyObject> >& lo, T whatever ) {
+ return *(lo.second) == whatever; // XXX use std::forward if we have 0x
+ }
+
+
+ // ------------------------------------------------------------------------------
+ /** Class template used to represent lazily evaluated object references in the converted schema */
+ // ------------------------------------------------------------------------------
+ template <typename T>
+ struct Lazy
+ {
+ typedef Lazy Out;
+ Lazy(const LazyObject* obj = NULL) : obj(obj) {
+ }
+
+ operator const T*() const {
+ return obj->ToPtr<T>();
+ }
+
+ operator const T&() const {
+ return obj->To<T>();
+ }
+
+ const T& operator * () const {
+ return obj->To<T>();
+ }
+
+ const T* operator -> () const {
+ return &obj->To<T>();
+ }
+
+ const LazyObject* obj;
+ };
+
+ // ------------------------------------------------------------------------------
+ /** Class template used to represent LIST and SET data members in the converted schema */
+ // ------------------------------------------------------------------------------
+ template <typename T, uint64_t min_cnt, uint64_t max_cnt=0uL>
+ struct ListOf : public std::vector<typename T::Out>
+ {
+ typedef typename T::Out OutScalar;
+ typedef ListOf Out;
+
+
+ ListOf() {
+ static_assert(min_cnt <= max_cnt || !max_cnt, "min_cnt <= max_cnt || !max_cnt");
+ }
+
+ };
+
+
+ // ------------------------------------------------------------------------------
+ template <typename TOut>
+ struct PickBaseType {
+ typedef EXPRESS::PrimitiveDataType<TOut> Type;
+ };
+
+ template <typename TOut>
+ struct PickBaseType< Lazy<TOut> > {
+ typedef EXPRESS::ENTITY Type;
+ };
+
+ template <> struct PickBaseType< std::shared_ptr< const EXPRESS::DataType > >;
+
+ // ------------------------------------------------------------------------------
+ template <typename T>
+ struct InternGenericConvert {
+ void operator()(T& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) {
+ try{
+ out = dynamic_cast< const typename PickBaseType<T>::Type& > ( *in );
+ }
+ catch(std::bad_cast&) {
+ throw TypeError("type error reading literal field");
+ }
+ }
+ };
+
+ template <>
+ struct InternGenericConvert< std::shared_ptr< const EXPRESS::DataType > > {
+ void operator()(std::shared_ptr< const EXPRESS::DataType >& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) {
+ out = in;
+ }
+ };
+
+ template <typename T>
+ struct InternGenericConvert< Maybe<T> > {
+ void operator()(Maybe<T>& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) {
+ GenericConvert((T&)out,in,db);
+ out.flag_valid();
+ }
+ };
+
+ template <typename T,uint64_t min_cnt, uint64_t max_cnt>
+ struct InternGenericConvertList {
+ void operator()(ListOf<T, min_cnt, max_cnt>& out, const std::shared_ptr< const EXPRESS::DataType >& inp_base, const STEP::DB& db) {
+
+ const EXPRESS::LIST* inp = dynamic_cast<const EXPRESS::LIST*>(inp_base.get());
+ if (!inp) {
+ throw TypeError("type error reading aggregate");
+ }
+
+ // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended?
+ if (max_cnt && inp->GetSize() > max_cnt) {
+ DefaultLogger::get()->warn("too many aggregate elements");
+ }
+ else if (inp->GetSize() < min_cnt) {
+ DefaultLogger::get()->warn("too few aggregate elements");
+ }
+
+ out.reserve(inp->GetSize());
+ for(size_t i = 0; i < inp->GetSize(); ++i) {
+
+ out.push_back( typename ListOf<T, min_cnt, max_cnt>::OutScalar() );
+ try{
+ GenericConvert(out.back(),(*inp)[i], db);
+ }
+ catch(const TypeError& t) {
+ throw TypeError(t.what() +std::string(" of aggregate"));
+ }
+ }
+ }
+ };
+
+ template <typename T>
+ struct InternGenericConvert< Lazy<T> > {
+ void operator()(Lazy<T>& out, const std::shared_ptr< const EXPRESS::DataType >& in_base, const STEP::DB& db) {
+ const EXPRESS::ENTITY* in = dynamic_cast<const EXPRESS::ENTITY*>(in_base.get());
+ if (!in) {
+ throw TypeError("type error reading entity");
+ }
+ out = Couple<T>(db).GetObject(*in);
+ }
+ };
+
+ template <typename T1>
+ inline void GenericConvert(T1& a, const std::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
+ return InternGenericConvert<T1>()(a,b,db);
+ }
+
+ template <typename T1,uint64_t N1, uint64_t N2>
+ inline void GenericConvert(ListOf<T1,N1,N2>& a, const std::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) {
+ return InternGenericConvertList<T1,N1,N2>()(a,b,db);
+ }
+
+
+ // ------------------------------------------------------------------------------
+ /** Lightweight manager class that holds the map of all objects in a
+ * STEP file. DB's are exclusively maintained by the functions in
+ * STEPFileReader.h*/
+ // -------------------------------------------------------------------------------
+ class DB
+ {
+ friend DB* ReadFileHeader(std::shared_ptr<IOStream> stream);
+ friend void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
+ const char* const* types_to_track, size_t len,
+ const char* const* inverse_indices_to_track, size_t len2
+ );
+
+ friend class LazyObject;
+
+ public:
+
+ // objects indexed by ID - this can grow pretty large (i.e some hundred million
+ // entries), so use raw pointers to avoid *any* overhead.
+ typedef std::map<uint64_t,const LazyObject* > ObjectMap;
+
+ // objects indexed by their declarative type, but only for those that we truly want
+ typedef std::set< const LazyObject*> ObjectSet;
+ typedef std::map<std::string, ObjectSet > ObjectMapByType;
+
+ // list of types for which to keep inverse indices for all references
+ // that the respective objects keep.
+ // the list keeps pointers to strings in static storage
+ typedef std::set<const char*> InverseWhitelist;
+
+ // references - for each object id the ids of all objects which reference it
+ // this is used to simulate STEP inverse indices for selected types.
+ typedef std::step_unordered_multimap<uint64_t, uint64_t > RefMap;
+ typedef std::pair<RefMap::const_iterator,RefMap::const_iterator> RefMapRange;
+
+ private:
+
+ DB(std::shared_ptr<StreamReaderLE> reader)
+ : reader(reader)
+ , splitter(*reader,true,true)
+ , evaluated_count()
+ , schema( NULL )
+ {}
+
+ public:
+
+ ~DB() {
+ for(ObjectMap::value_type& o : objects) {
+ delete o.second;
+ }
+ }
+
+ public:
+
+ uint64_t GetObjectCount() const {
+ return objects.size();
+ }
+
+ uint64_t GetEvaluatedObjectCount() const {
+ return evaluated_count;
+ }
+
+ const HeaderInfo& GetHeader() const {
+ return header;
+ }
+
+ const EXPRESS::ConversionSchema& GetSchema() const {
+ return *schema;
+ }
+
+ const ObjectMap& GetObjects() const {
+ return objects;
+ }
+
+ const ObjectMapByType& GetObjectsByType() const {
+ return objects_bytype;
+ }
+
+ const RefMap& GetRefs() const {
+ return refs;
+ }
+
+
+ bool KeepInverseIndicesForType(const char* const type) const {
+ return inv_whitelist.find(type) != inv_whitelist.end();
+ }
+
+
+ // get the yet unevaluated object record with a given id
+ const LazyObject* GetObject(uint64_t id) const {
+ const ObjectMap::const_iterator it = objects.find(id);
+ if (it != objects.end()) {
+ return (*it).second;
+ }
+ return NULL;
+ }
+
+
+ // get an arbitrary object out of the soup with the only restriction being its type.
+ const LazyObject* GetObject(const std::string& type) const {
+ const ObjectMapByType::const_iterator it = objects_bytype.find(type);
+ if (it != objects_bytype.end() && (*it).second.size()) {
+ return *(*it).second.begin();
+ }
+ return NULL;
+ }
+
+ // same, but raise an exception if the object doesn't exist and return a reference
+ const LazyObject& MustGetObject(uint64_t id) const {
+ const LazyObject* o = GetObject(id);
+ if (!o) {
+ throw TypeError("requested entity is not present",id);
+ }
+ return *o;
+ }
+
+ const LazyObject& MustGetObject(const std::string& type) const {
+ const LazyObject* o = GetObject(type);
+ if (!o) {
+ throw TypeError("requested entity of type "+type+"is not present");
+ }
+ return *o;
+ }
#ifdef ASSIMP_IFC_TEST
- // evaluate *all* entities in the file. this is a power test for the loader
- void EvaluateAll() {
- BOOST_FOREACH(ObjectMap::value_type& e,objects) {
- **e.second;
- }
- ai_assert(evaluated_count == objects.size());
- }
+ // evaluate *all* entities in the file. this is a power test for the loader
+ void EvaluateAll() {
+ for(ObjectMap::value_type& e :objects) {
+ **e.second;
+ }
+ ai_assert(evaluated_count == objects.size());
+ }
#endif
- private:
+ private:
+
+ // full access only offered to close friends - they should
+ // use the provided getters rather than messing around with
+ // the members directly.
+ LineSplitter& GetSplitter() {
+ return splitter;
+ }
- // full access only offered to close friends - they should
- // use the provided getters rather than messing around with
- // the members directly.
- LineSplitter& GetSplitter() {
- return splitter;
- }
+ void InternInsert(const LazyObject* lz) {
+ objects[lz->GetID()] = lz;
- void InternInsert(const LazyObject* lz) {
- objects[lz->GetID()] = lz;
+ const ObjectMapByType::iterator it = objects_bytype.find( lz->type );
+ if (it != objects_bytype.end()) {
+ (*it).second.insert(lz);
+ }
+ }
- const ObjectMapByType::iterator it = objects_bytype.find( lz->type );
- if (it != objects_bytype.end()) {
- (*it).second.insert(lz);
- }
- }
+ void SetSchema(const EXPRESS::ConversionSchema& _schema) {
+ schema = &_schema;
+ }
- void SetSchema(const EXPRESS::ConversionSchema& _schema) {
- schema = &_schema;
- }
-
- void SetTypesToTrack(const char* const* types, size_t N) {
- for(size_t i = 0; i < N;++i) {
- objects_bytype[types[i]] = ObjectSet();
- }
- }
+ void SetTypesToTrack(const char* const* types, size_t N) {
+ for(size_t i = 0; i < N;++i) {
+ objects_bytype[types[i]] = ObjectSet();
+ }
+ }
- void SetInverseIndicesToTrack( const char* const* types, size_t N ) {
- for(size_t i = 0; i < N;++i) {
- const char* const sz = schema->GetStaticStringForToken(types[i]);
- ai_assert(sz);
- inv_whitelist.insert(sz);
- }
- }
+ void SetInverseIndicesToTrack( const char* const* types, size_t N ) {
+ for(size_t i = 0; i < N;++i) {
+ const char* const sz = schema->GetStaticStringForToken(types[i]);
+ ai_assert(sz);
+ inv_whitelist.insert(sz);
+ }
+ }
- HeaderInfo& GetHeader() {
- return header;
- }
+ HeaderInfo& GetHeader() {
+ return header;
+ }
- void MarkRef(uint64_t who, uint64_t by_whom) {
- refs.insert(std::make_pair(who,by_whom));
- }
+ void MarkRef(uint64_t who, uint64_t by_whom) {
+ refs.insert(std::make_pair(who,by_whom));
+ }
- private:
+ private:
- HeaderInfo header;
- ObjectMap objects;
- ObjectMapByType objects_bytype;
- RefMap refs;
- InverseWhitelist inv_whitelist;
+ HeaderInfo header;
+ ObjectMap objects;
+ ObjectMapByType objects_bytype;
+ RefMap refs;
+ InverseWhitelist inv_whitelist;
- boost::shared_ptr<StreamReaderLE> reader;
- LineSplitter splitter;
+ std::shared_ptr<StreamReaderLE> reader;
+ LineSplitter splitter;
- uint64_t evaluated_count;
+ uint64_t evaluated_count;
- const EXPRESS::ConversionSchema* schema;
- };
+ const EXPRESS::ConversionSchema* schema;
+ };
}
diff --git a/src/3rdparty/assimp/code/STEPFileEncoding.cpp b/src/3rdparty/assimp/code/STEPFileEncoding.cpp
index e56a1ba42..aff0b618d 100644
--- a/src/3rdparty/assimp/code/STEPFileEncoding.cpp
+++ b/src/3rdparty/assimp/code/STEPFileEncoding.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,393 +41,393 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file STEPFileEncoding.cpp
* @brief STEP character handling, string unescaping
*/
-#include "AssimpPCH.h"
#include "STEPFileEncoding.h"
#include "fast_atof.h"
#include "../contrib/ConvertUTF/ConvertUTF.h"
+#include <memory>
using namespace Assimp;
// roman1 to utf16 table
static const UTF16 mac_codetable[] = {
- // 0x20 unassig./nonprint. slots
- 0x0020 ,
- 0x0021 ,
- 0x0022 ,
- 0x0023 ,
- 0x0024 ,
- 0x0025 ,
- 0x0026 ,
- 0x0027 ,
- 0x0028 ,
- 0x0029 ,
- 0x002A ,
- 0x002B ,
- 0x002C ,
- 0x002D ,
- 0x002E ,
- 0x002F ,
- 0x0030 ,
- 0x0031 ,
- 0x0032 ,
- 0x0033 ,
- 0x0034 ,
- 0x0035 ,
- 0x0036 ,
- 0x0037 ,
- 0x0038 ,
- 0x0039 ,
- 0x003A ,
- 0x003B ,
- 0x003C ,
- 0x003D ,
- 0x003E ,
- 0x003F ,
- 0x0040 ,
- 0x0041 ,
- 0x0042 ,
- 0x0043 ,
- 0x0044 ,
- 0x0045 ,
- 0x0046 ,
- 0x0047 ,
- 0x0048 ,
- 0x0049 ,
- 0x004A ,
- 0x004B ,
- 0x004C ,
- 0x004D ,
- 0x004E ,
- 0x004F ,
- 0x0050 ,
- 0x0051 ,
- 0x0052 ,
- 0x0053 ,
- 0x0054 ,
- 0x0055 ,
- 0x0056 ,
- 0x0057 ,
- 0x0058 ,
- 0x0059 ,
- 0x005A ,
- 0x005B ,
- 0x005C ,
- 0x005D ,
- 0x005E ,
- 0x005F ,
- 0x0060 ,
- 0x0061 ,
- 0x0062 ,
- 0x0063 ,
- 0x0064 ,
- 0x0065 ,
- 0x0066 ,
- 0x0067 ,
- 0x0068 ,
- 0x0069 ,
- 0x006A ,
- 0x006B ,
- 0x006C ,
- 0x006D ,
- 0x006E ,
- 0x006F ,
- 0x0070 ,
- 0x0071 ,
- 0x0072 ,
- 0x0073 ,
- 0x0074 ,
- 0x0075 ,
- 0x0076 ,
- 0x0077 ,
- 0x0078 ,
- 0x0079 ,
- 0x007A ,
- 0x007B ,
- 0x007C ,
- 0x007D ,
- 0x007E ,
- 0x0000 , // unassig.
- 0x00C4 ,
- 0x00C5 ,
- 0x00C7 ,
- 0x00C9 ,
- 0x00D1 ,
- 0x00D6 ,
- 0x00DC ,
- 0x00E1 ,
- 0x00E0 ,
- 0x00E2 ,
- 0x00E4 ,
- 0x00E3 ,
- 0x00E5 ,
- 0x00E7 ,
- 0x00E9 ,
- 0x00E8 ,
- 0x00EA ,
- 0x00EB ,
- 0x00ED ,
- 0x00EC ,
- 0x00EE ,
- 0x00EF ,
- 0x00F1 ,
- 0x00F3 ,
- 0x00F2 ,
- 0x00F4 ,
- 0x00F6 ,
- 0x00F5 ,
- 0x00FA ,
- 0x00F9 ,
- 0x00FB ,
- 0x00FC ,
- 0x2020 ,
- 0x00B0 ,
- 0x00A2 ,
- 0x00A3 ,
- 0x00A7 ,
- 0x2022 ,
- 0x00B6 ,
- 0x00DF ,
- 0x00AE ,
- 0x00A9 ,
- 0x2122 ,
- 0x00B4 ,
- 0x00A8 ,
- 0x2260 ,
- 0x00C6 ,
- 0x00D8 ,
- 0x221E ,
- 0x00B1 ,
- 0x2264 ,
- 0x2265 ,
- 0x00A5 ,
- 0x00B5 ,
- 0x2202 ,
- 0x2211 ,
- 0x220F ,
- 0x03C0 ,
- 0x222B ,
- 0x00AA ,
- 0x00BA ,
- 0x03A9 ,
- 0x00E6 ,
- 0x00F8 ,
- 0x00BF ,
- 0x00A1 ,
- 0x00AC ,
- 0x221A ,
- 0x0192 ,
- 0x2248 ,
- 0x2206 ,
- 0x00AB ,
- 0x00BB ,
- 0x2026 ,
- 0x00A0 ,
- 0x00C0 ,
- 0x00C3 ,
- 0x00D5 ,
- 0x0152 ,
- 0x0153 ,
- 0x2013 ,
- 0x2014 ,
- 0x201C ,
- 0x201D ,
- 0x2018 ,
- 0x2019 ,
- 0x00F7 ,
- 0x25CA ,
- 0x00FF ,
- 0x0178 ,
- 0x2044 ,
- 0x20AC ,
- 0x2039 ,
- 0x203A ,
- 0xFB01 ,
- 0xFB02 ,
- 0x2021 ,
- 0x00B7 ,
- 0x201A ,
- 0x201E ,
- 0x2030 ,
- 0x00C2 ,
- 0x00CA ,
- 0x00C1 ,
- 0x00CB ,
- 0x00C8 ,
- 0x00CD ,
- 0x00CE ,
- 0x00CF ,
- 0x00CC ,
- 0x00D3 ,
- 0x00D4 ,
- 0xF8FF ,
- 0x00D2 ,
- 0x00DA ,
- 0x00DB ,
- 0x00D9 ,
- 0x0131 ,
- 0x02C6 ,
- 0x02DC ,
- 0x00AF ,
- 0x02D8 ,
- 0x02D9 ,
- 0x02DA ,
- 0x00B8 ,
- 0x02DD ,
- 0x02DB ,
- 0x02C7
+ // 0x20 unassig./nonprint. slots
+ 0x0020 ,
+ 0x0021 ,
+ 0x0022 ,
+ 0x0023 ,
+ 0x0024 ,
+ 0x0025 ,
+ 0x0026 ,
+ 0x0027 ,
+ 0x0028 ,
+ 0x0029 ,
+ 0x002A ,
+ 0x002B ,
+ 0x002C ,
+ 0x002D ,
+ 0x002E ,
+ 0x002F ,
+ 0x0030 ,
+ 0x0031 ,
+ 0x0032 ,
+ 0x0033 ,
+ 0x0034 ,
+ 0x0035 ,
+ 0x0036 ,
+ 0x0037 ,
+ 0x0038 ,
+ 0x0039 ,
+ 0x003A ,
+ 0x003B ,
+ 0x003C ,
+ 0x003D ,
+ 0x003E ,
+ 0x003F ,
+ 0x0040 ,
+ 0x0041 ,
+ 0x0042 ,
+ 0x0043 ,
+ 0x0044 ,
+ 0x0045 ,
+ 0x0046 ,
+ 0x0047 ,
+ 0x0048 ,
+ 0x0049 ,
+ 0x004A ,
+ 0x004B ,
+ 0x004C ,
+ 0x004D ,
+ 0x004E ,
+ 0x004F ,
+ 0x0050 ,
+ 0x0051 ,
+ 0x0052 ,
+ 0x0053 ,
+ 0x0054 ,
+ 0x0055 ,
+ 0x0056 ,
+ 0x0057 ,
+ 0x0058 ,
+ 0x0059 ,
+ 0x005A ,
+ 0x005B ,
+ 0x005C ,
+ 0x005D ,
+ 0x005E ,
+ 0x005F ,
+ 0x0060 ,
+ 0x0061 ,
+ 0x0062 ,
+ 0x0063 ,
+ 0x0064 ,
+ 0x0065 ,
+ 0x0066 ,
+ 0x0067 ,
+ 0x0068 ,
+ 0x0069 ,
+ 0x006A ,
+ 0x006B ,
+ 0x006C ,
+ 0x006D ,
+ 0x006E ,
+ 0x006F ,
+ 0x0070 ,
+ 0x0071 ,
+ 0x0072 ,
+ 0x0073 ,
+ 0x0074 ,
+ 0x0075 ,
+ 0x0076 ,
+ 0x0077 ,
+ 0x0078 ,
+ 0x0079 ,
+ 0x007A ,
+ 0x007B ,
+ 0x007C ,
+ 0x007D ,
+ 0x007E ,
+ 0x0000 , // unassig.
+ 0x00C4 ,
+ 0x00C5 ,
+ 0x00C7 ,
+ 0x00C9 ,
+ 0x00D1 ,
+ 0x00D6 ,
+ 0x00DC ,
+ 0x00E1 ,
+ 0x00E0 ,
+ 0x00E2 ,
+ 0x00E4 ,
+ 0x00E3 ,
+ 0x00E5 ,
+ 0x00E7 ,
+ 0x00E9 ,
+ 0x00E8 ,
+ 0x00EA ,
+ 0x00EB ,
+ 0x00ED ,
+ 0x00EC ,
+ 0x00EE ,
+ 0x00EF ,
+ 0x00F1 ,
+ 0x00F3 ,
+ 0x00F2 ,
+ 0x00F4 ,
+ 0x00F6 ,
+ 0x00F5 ,
+ 0x00FA ,
+ 0x00F9 ,
+ 0x00FB ,
+ 0x00FC ,
+ 0x2020 ,
+ 0x00B0 ,
+ 0x00A2 ,
+ 0x00A3 ,
+ 0x00A7 ,
+ 0x2022 ,
+ 0x00B6 ,
+ 0x00DF ,
+ 0x00AE ,
+ 0x00A9 ,
+ 0x2122 ,
+ 0x00B4 ,
+ 0x00A8 ,
+ 0x2260 ,
+ 0x00C6 ,
+ 0x00D8 ,
+ 0x221E ,
+ 0x00B1 ,
+ 0x2264 ,
+ 0x2265 ,
+ 0x00A5 ,
+ 0x00B5 ,
+ 0x2202 ,
+ 0x2211 ,
+ 0x220F ,
+ 0x03C0 ,
+ 0x222B ,
+ 0x00AA ,
+ 0x00BA ,
+ 0x03A9 ,
+ 0x00E6 ,
+ 0x00F8 ,
+ 0x00BF ,
+ 0x00A1 ,
+ 0x00AC ,
+ 0x221A ,
+ 0x0192 ,
+ 0x2248 ,
+ 0x2206 ,
+ 0x00AB ,
+ 0x00BB ,
+ 0x2026 ,
+ 0x00A0 ,
+ 0x00C0 ,
+ 0x00C3 ,
+ 0x00D5 ,
+ 0x0152 ,
+ 0x0153 ,
+ 0x2013 ,
+ 0x2014 ,
+ 0x201C ,
+ 0x201D ,
+ 0x2018 ,
+ 0x2019 ,
+ 0x00F7 ,
+ 0x25CA ,
+ 0x00FF ,
+ 0x0178 ,
+ 0x2044 ,
+ 0x20AC ,
+ 0x2039 ,
+ 0x203A ,
+ 0xFB01 ,
+ 0xFB02 ,
+ 0x2021 ,
+ 0x00B7 ,
+ 0x201A ,
+ 0x201E ,
+ 0x2030 ,
+ 0x00C2 ,
+ 0x00CA ,
+ 0x00C1 ,
+ 0x00CB ,
+ 0x00C8 ,
+ 0x00CD ,
+ 0x00CE ,
+ 0x00CF ,
+ 0x00CC ,
+ 0x00D3 ,
+ 0x00D4 ,
+ 0xF8FF ,
+ 0x00D2 ,
+ 0x00DA ,
+ 0x00DB ,
+ 0x00D9 ,
+ 0x0131 ,
+ 0x02C6 ,
+ 0x02DC ,
+ 0x00AF ,
+ 0x02D8 ,
+ 0x02D9 ,
+ 0x02DA ,
+ 0x00B8 ,
+ 0x02DD ,
+ 0x02DB ,
+ 0x02C7
};
// ------------------------------------------------------------------------------------------------
-bool STEP::StringToUTF8(std::string& s)
+bool STEP::StringToUTF8(std::string& s)
{
- // very basic handling for escaped string sequences
- // http://doc.spatial.com/index.php?title=InterOp:Connect/STEP&redirect=no
-
- for (size_t i = 0; i < s.size(); ) {
- if (s[i] == '\\') {
- // \S\X - cp1252 (X is the character remapped to [0,127])
- if (i+3 < s.size() && s[i+1] == 'S' && s[i+2] == '\\') {
- // http://stackoverflow.com/questions/5586214/how-to-convert-char-from-iso-8859-1-to-utf-8-in-c-multiplatformly
- ai_assert((uint8_t)s[i+3] < 0x80);
- const uint8_t ch = s[i+3] + 0x80;
-
- s[i] = 0xc0 | (ch & 0xc0) >> 6;
- s[i+1] = 0x80 | (ch & 0x3f);
-
- s.erase(i + 2,2);
- ++i;
- }
- // \X\xx - mac/roman (xx is a hex sequence)
- else if (i+4 < s.size() && s[i+1] == 'X' && s[i+2] == '\\') {
-
- const uint8_t macval = HexOctetToDecimal(s.c_str() + i + 3);
- if(macval < 0x20) {
- return false;
- }
-
- ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20);
-
- const UTF32 unival = mac_codetable[macval - 0x20], *univalp = &unival;
-
- UTF8 temp[5], *tempp = temp;
- ai_assert(sizeof(UTF8) == 1);
-
- if(ConvertUTF32toUTF8(&univalp, univalp+1, &tempp, tempp+sizeof(temp), lenientConversion) != conversionOK) {
- return false;
- }
-
- const size_t outcount = static_cast<size_t>(tempp-temp);
-
- s.erase(i,5);
- s.insert(i, reinterpret_cast<char*>(temp), outcount);
- i += outcount;
- }
- // \Xn\ .. \X0\ - various unicode encodings (n=2: utf16; n=4: utf32)
- else if (i+3 < s.size() && s[i+1] == 'X' && s[i+2] >= '0' && s[i+2] <= '9') {
- switch(s[i+2]) {
- // utf16
- case '2':
- // utf32
- case '4':
- if (s[i+3] == '\\') {
- const size_t basei = i+4;
- size_t j = basei, jend = s.size()-4;
-
- for (; j < jend; ++j) {
- if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') {
- break;
- }
- }
- if (j == jend) {
- return false;
- }
-
- if (j == basei) {
- s.erase(i,8);
- continue;
- }
-
- if (s[i+2] == '2') {
- if (((j - basei) % 4) != 0) {
- return false;
- }
-
- const size_t count = (j-basei)/4;
- boost::scoped_array<UTF16> src(new UTF16[count]);
-
- const char* cur = s.c_str() + basei;
- for (size_t k = 0; k < count; ++k, cur += 4) {
- src[k] = (static_cast<UTF16>(HexOctetToDecimal(cur)) << 8u) |
- static_cast<UTF16>(HexOctetToDecimal(cur+2));
- }
-
- const size_t dcount = count * 3; // this is enough to hold all possible outputs
- boost::scoped_array<UTF8> dest(new UTF8[dcount]);
-
- const UTF16* srct = src.get();
- UTF8* destt = dest.get();
- if(ConvertUTF16toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
- return false;
- }
-
- const size_t outcount = static_cast<size_t>(destt-dest.get());
-
- s.erase(i,(j+4-i));
-
- ai_assert(sizeof(UTF8) == 1);
- s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
-
- i += outcount;
- continue;
- }
- else if (s[i+2] == '4') {
- if (((j - basei) % 8) != 0) {
- return false;
- }
-
- const size_t count = (j-basei)/8;
- boost::scoped_array<UTF32> src(new UTF32[count]);
-
- const char* cur = s.c_str() + basei;
- for (size_t k = 0; k < count; ++k, cur += 8) {
- src[k] = (static_cast<UTF32>(HexOctetToDecimal(cur )) << 24u) |
- (static_cast<UTF32>(HexOctetToDecimal(cur+2)) << 16u) |
- (static_cast<UTF32>(HexOctetToDecimal(cur+4)) << 8u) |
- (static_cast<UTF32>(HexOctetToDecimal(cur+6)));
- }
-
- const size_t dcount = count * 5; // this is enough to hold all possible outputs
- boost::scoped_array<UTF8> dest(new UTF8[dcount]);
-
- const UTF32* srct = src.get();
- UTF8* destt = dest.get();
- if(ConvertUTF32toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
- return false;
- }
-
- const size_t outcount = static_cast<size_t>(destt-dest.get());
-
- s.erase(i,(j+4-i));
-
- ai_assert(sizeof(UTF8) == 1);
- s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
-
- i += outcount;
- continue;
- }
- }
-
- break;
-
- // TODO: other encoding patterns?
-
- default:
- return false;
- }
- }
- }
- ++i;
- }
- return true;
+ // very basic handling for escaped string sequences
+ // http://doc.spatial.com/index.php?title=InterOp:Connect/STEP&redirect=no
+
+ for (size_t i = 0; i < s.size(); ) {
+ if (s[i] == '\\') {
+ // \S\X - cp1252 (X is the character remapped to [0,127])
+ if (i+3 < s.size() && s[i+1] == 'S' && s[i+2] == '\\') {
+ // http://stackoverflow.com/questions/5586214/how-to-convert-char-from-iso-8859-1-to-utf-8-in-c-multiplatformly
+ ai_assert((uint8_t)s[i+3] < 0x80);
+ const uint8_t ch = s[i+3] + 0x80;
+
+ s[i] = 0xc0 | (ch & 0xc0) >> 6;
+ s[i+1] = 0x80 | (ch & 0x3f);
+
+ s.erase(i + 2,2);
+ ++i;
+ }
+ // \X\xx - mac/roman (xx is a hex sequence)
+ else if (i+4 < s.size() && s[i+1] == 'X' && s[i+2] == '\\') {
+
+ const uint8_t macval = HexOctetToDecimal(s.c_str() + i + 3);
+ if(macval < 0x20) {
+ return false;
+ }
+
+ ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20);
+
+ const UTF32 unival = mac_codetable[macval - 0x20], *univalp = &unival;
+
+ UTF8 temp[5], *tempp = temp;
+ ai_assert(sizeof(UTF8) == 1);
+
+ if(ConvertUTF32toUTF8(&univalp, univalp+1, &tempp, tempp+sizeof(temp), lenientConversion) != conversionOK) {
+ return false;
+ }
+
+ const size_t outcount = static_cast<size_t>(tempp-temp);
+
+ s.erase(i,5);
+ s.insert(i, reinterpret_cast<char*>(temp), outcount);
+ i += outcount;
+ }
+ // \Xn\ .. \X0\ - various unicode encodings (n=2: utf16; n=4: utf32)
+ else if (i+3 < s.size() && s[i+1] == 'X' && s[i+2] >= '0' && s[i+2] <= '9') {
+ switch(s[i+2]) {
+ // utf16
+ case '2':
+ // utf32
+ case '4':
+ if (s[i+3] == '\\') {
+ const size_t basei = i+4;
+ size_t j = basei, jend = s.size()-3;
+
+ for (; j < jend; ++j) {
+ if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') {
+ break;
+ }
+ }
+ if (j == jend) {
+ return false;
+ }
+
+ if (j == basei) {
+ s.erase(i,8);
+ continue;
+ }
+
+ if (s[i+2] == '2') {
+ if (((j - basei) % 4) != 0) {
+ return false;
+ }
+
+ const size_t count = (j-basei)/4;
+ std::unique_ptr<UTF16[]> src(new UTF16[count]);
+
+ const char* cur = s.c_str() + basei;
+ for (size_t k = 0; k < count; ++k, cur += 4) {
+ src[k] = (static_cast<UTF16>(HexOctetToDecimal(cur)) << 8u) |
+ static_cast<UTF16>(HexOctetToDecimal(cur+2));
+ }
+
+ const size_t dcount = count * 3; // this is enough to hold all possible outputs
+ std::unique_ptr<UTF8[]> dest(new UTF8[dcount]);
+
+ const UTF16* srct = src.get();
+ UTF8* destt = dest.get();
+ if(ConvertUTF16toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
+ return false;
+ }
+
+ const size_t outcount = static_cast<size_t>(destt-dest.get());
+
+ s.erase(i,(j+4-i));
+
+ ai_assert(sizeof(UTF8) == 1);
+ s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
+
+ i += outcount;
+ continue;
+ }
+ else if (s[i+2] == '4') {
+ if (((j - basei) % 8) != 0) {
+ return false;
+ }
+
+ const size_t count = (j-basei)/8;
+ std::unique_ptr<UTF32[]> src(new UTF32[count]);
+
+ const char* cur = s.c_str() + basei;
+ for (size_t k = 0; k < count; ++k, cur += 8) {
+ src[k] = (static_cast<UTF32>(HexOctetToDecimal(cur )) << 24u) |
+ (static_cast<UTF32>(HexOctetToDecimal(cur+2)) << 16u) |
+ (static_cast<UTF32>(HexOctetToDecimal(cur+4)) << 8u) |
+ (static_cast<UTF32>(HexOctetToDecimal(cur+6)));
+ }
+
+ const size_t dcount = count * 5; // this is enough to hold all possible outputs
+ std::unique_ptr<UTF8[]> dest(new UTF8[dcount]);
+
+ const UTF32* srct = src.get();
+ UTF8* destt = dest.get();
+ if(ConvertUTF32toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) {
+ return false;
+ }
+
+ const size_t outcount = static_cast<size_t>(destt-dest.get());
+
+ s.erase(i,(j+4-i));
+
+ ai_assert(sizeof(UTF8) == 1);
+ s.insert(i, reinterpret_cast<char*>(dest.get()), outcount);
+
+ i += outcount;
+ continue;
+ }
+ }
+
+ break;
+
+ // TODO: other encoding patterns?
+
+ default:
+ return false;
+ }
+ }
+ }
+ ++i;
+ }
+ return true;
}
diff --git a/src/3rdparty/assimp/code/STEPFileEncoding.h b/src/3rdparty/assimp/code/STEPFileEncoding.h
index 64b7652f3..3aec83056 100644
--- a/src/3rdparty/assimp/code/STEPFileEncoding.h
+++ b/src/3rdparty/assimp/code/STEPFileEncoding.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,15 +47,15 @@ namespace Assimp {
namespace STEP {
- // --------------------------------------------------------------------------
- // Convert an ASCII STEP identifier with possibly escaped character
- // sequences using foreign encodings to plain UTF8.
- //
- // Return false if an error occurs, s may or may not be modified in
- // this case and could still contain escape sequences (even partly
- // escaped ones).
- bool StringToUTF8(std::string& s);
-
+ // --------------------------------------------------------------------------
+ // Convert an ASCII STEP identifier with possibly escaped character
+ // sequences using foreign encodings to plain UTF8.
+ //
+ // Return false if an error occurs, s may or may not be modified in
+ // this case and could still contain escape sequences (even partly
+ // escaped ones).
+ bool StringToUTF8(std::string& s);
+
} // ! STEP
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/STEPFileReader.cpp b/src/3rdparty/assimp/code/STEPFileReader.cpp
index c9561daa9..afaa53a45 100644
--- a/src/3rdparty/assimp/code/STEPFileReader.cpp
+++ b/src/3rdparty/assimp/code/STEPFileReader.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,30 +23,31 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file STEPFileReader.cpp
- * @brief Implementation of the STEP file parser, which fills a
+ * @brief Implementation of the STEP file parser, which fills a
* STEP::DB with data read from a file.
*/
-#include "AssimpPCH.h"
+
#include "STEPFileReader.h"
#include "STEPFileEncoding.h"
#include "TinyFormatter.h"
#include "fast_atof.h"
+#include <memory>
using namespace Assimp;
@@ -55,38 +56,16 @@ namespace EXPRESS = STEP::EXPRESS;
#include <functional>
// ------------------------------------------------------------------------------------------------
-// From http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
-
-// trim from start
-static inline std::string &ltrim(std::string &s) {
- s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1( std::ptr_fun(Assimp::IsSpace<char>))));
- return s;
-}
-
-// trim from end
-static inline std::string &rtrim(std::string &s) {
- s.erase(std::find_if(s.rbegin(), s.rend(), std::not1( std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
- return s;
-}
-// trim from both ends
-static inline std::string &trim(std::string &s) {
- return ltrim(rtrim(s));
-}
-
-
-
-
-// ------------------------------------------------------------------------------------------------
-std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
+std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "")
{
- return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(line ",line,") ",s) );
+ return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(line ",line,") ",s) );
}
// ------------------------------------------------------------------------------------------------
-std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = "")
+std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = "")
{
- return entity == STEP::TypeError::ENTITY_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(entity #",entity,") ",s));
+ return entity == STEP::TypeError::ENTITY_NOT_SPECIFIED ? prefix+s : static_cast<std::string>( (Formatter::format(),prefix,"(entity #",entity,") ",s));
}
@@ -106,59 +85,59 @@ STEP::TypeError::TypeError (const std::string& s,uint64_t entity /* = ENTITY_NOT
// ------------------------------------------------------------------------------------------------
-STEP::DB* STEP::ReadFileHeader(boost::shared_ptr<IOStream> stream)
+STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream)
{
- boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
- std::auto_ptr<STEP::DB> db = std::auto_ptr<STEP::DB>(new STEP::DB(reader));
-
- LineSplitter& splitter = db->GetSplitter();
- if (!splitter || *splitter != "ISO-10303-21;") {
- throw STEP::SyntaxError("expected magic token: ISO-10303-21",1);
- }
-
- HeaderInfo& head = db->GetHeader();
- for(++splitter; splitter; ++splitter) {
- const std::string& s = *splitter;
- if (s == "DATA;") {
- // here we go, header done, start of data section
- ++splitter;
- break;
- }
-
- // want one-based line numbers for human readers, so +1
- const uint64_t line = splitter.get_index()+1;
-
- if (s.substr(0,11) == "FILE_SCHEMA") {
- const char* sz = s.c_str()+11;
- SkipSpaces(sz,&sz);
- boost::shared_ptr< const EXPRESS::DataType > schema = EXPRESS::DataType::Parse(sz);
-
- // the file schema should be a regular list entity, although it usually contains exactly one entry
- // since the list itself is contained in a regular parameter list, we actually have
- // two nested lists.
- const EXPRESS::LIST* list = dynamic_cast<const EXPRESS::LIST*>(schema.get());
- if (list && list->GetSize()) {
- list = dynamic_cast<const EXPRESS::LIST*>( (*list)[0].get() );
- if (!list) {
- throw STEP::SyntaxError("expected FILE_SCHEMA to be a list",line);
- }
-
- // XXX need support for multiple schemas?
- if (list->GetSize() > 1) {
- DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line));
- }
- const EXPRESS::STRING* string;
- if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
- throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
- }
- head.fileSchema = *string;
- }
- }
-
- // XXX handle more header fields
- }
-
- return db.release();
+ std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
+ std::unique_ptr<STEP::DB> db = std::unique_ptr<STEP::DB>(new STEP::DB(reader));
+
+ LineSplitter& splitter = db->GetSplitter();
+ if (!splitter || *splitter != "ISO-10303-21;") {
+ throw STEP::SyntaxError("expected magic token: ISO-10303-21",1);
+ }
+
+ HeaderInfo& head = db->GetHeader();
+ for(++splitter; splitter; ++splitter) {
+ const std::string& s = *splitter;
+ if (s == "DATA;") {
+ // here we go, header done, start of data section
+ ++splitter;
+ break;
+ }
+
+ // want one-based line numbers for human readers, so +1
+ const uint64_t line = splitter.get_index()+1;
+
+ if (s.substr(0,11) == "FILE_SCHEMA") {
+ const char* sz = s.c_str()+11;
+ SkipSpaces(sz,&sz);
+ std::shared_ptr< const EXPRESS::DataType > schema = EXPRESS::DataType::Parse(sz);
+
+ // the file schema should be a regular list entity, although it usually contains exactly one entry
+ // since the list itself is contained in a regular parameter list, we actually have
+ // two nested lists.
+ const EXPRESS::LIST* list = dynamic_cast<const EXPRESS::LIST*>(schema.get());
+ if (list && list->GetSize()) {
+ list = dynamic_cast<const EXPRESS::LIST*>( (*list)[0].get() );
+ if (!list) {
+ throw STEP::SyntaxError("expected FILE_SCHEMA to be a list",line);
+ }
+
+ // XXX need support for multiple schemas?
+ if (list->GetSize() > 1) {
+ DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line));
+ }
+ const EXPRESS::STRING* string( nullptr );
+ if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
+ throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line);
+ }
+ head.fileSchema = *string;
+ }
+ }
+
+ // XXX handle more header fields
+ }
+
+ return db.release();
}
@@ -168,19 +147,19 @@ namespace {
// check whether the given line contains an entity definition (i.e. starts with "#<number>=")
bool IsEntityDef(const std::string& snext)
{
- if (snext[0] == '#') {
- // it is only a new entity if it has a '=' after the
- // entity ID.
- for(std::string::const_iterator it = snext.begin()+1; it != snext.end(); ++it) {
- if (*it == '=') {
- return true;
- }
- if ((*it < '0' || *it > '9') && *it != ' ') {
- break;
- }
- }
- }
- return false;
+ if (snext[0] == '#') {
+ // it is only a new entity if it has a '=' after the
+ // entity ID.
+ for(std::string::const_iterator it = snext.begin()+1; it != snext.end(); ++it) {
+ if (*it == '=') {
+ return true;
+ }
+ if ((*it < '0' || *it > '9') && *it != ' ') {
+ break;
+ }
+ }
+ }
+ return false;
}
}
@@ -188,377 +167,377 @@ bool IsEntityDef(const std::string& snext)
// ------------------------------------------------------------------------------------------------
void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
- const char* const* types_to_track, size_t len,
- const char* const* inverse_indices_to_track, size_t len2)
+ const char* const* types_to_track, size_t len,
+ const char* const* inverse_indices_to_track, size_t len2)
{
- db.SetSchema(scheme);
- db.SetTypesToTrack(types_to_track,len);
- db.SetInverseIndicesToTrack(inverse_indices_to_track,len2);
-
- const DB::ObjectMap& map = db.GetObjects();
- LineSplitter& splitter = db.GetSplitter();
-
- while (splitter) {
- bool has_next = false;
- std::string s = *splitter;
- if (s == "ENDSEC;") {
- break;
- }
- s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
-
- // want one-based line numbers for human readers, so +1
- const uint64_t line = splitter.get_index()+1;
- // LineSplitter already ignores empty lines
- ai_assert(s.length());
- if (s[0] != '#') {
- DefaultLogger::get()->warn(AddLineNumber("expected token \'#\'",line));
- ++splitter;
- continue;
- }
- // ---
- // extract id, entity class name and argument string,
- // but don't create the actual object yet.
- // ---
- const std::string::size_type n0 = s.find_first_of('=');
- if (n0 == std::string::npos) {
- DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line));
- ++splitter;
- continue;
- }
-
- const uint64_t id = strtoul10_64(s.substr(1,n0-1).c_str());
- if (!id) {
- DefaultLogger::get()->warn(AddLineNumber("expected positive, numeric entity id",line));
- ++splitter;
- continue;
- }
- std::string::size_type n1 = s.find_first_of('(',n0);
- if (n1 == std::string::npos) {
- has_next = true;
- bool ok = false;
- for( ++splitter; splitter; ++splitter) {
- const std::string& snext = *splitter;
- if (snext.empty()) {
- continue;
- }
-
- // the next line doesn't start an entity, so maybe it is
- // just a continuation for this line, keep going
- if (!IsEntityDef(snext)) {
- s.append(snext);
- n1 = s.find_first_of('(',n0);
- ok = (n1 != std::string::npos);
- }
- else {
- break;
- }
- }
-
- if(!ok) {
- DefaultLogger::get()->warn(AddLineNumber("expected token \'(\'",line));
- continue;
- }
- }
-
- std::string::size_type n2 = s.find_last_of(')');
- if (n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';') {
-
- has_next = true;
- bool ok = false;
- for( ++splitter; splitter; ++splitter) {
- const std::string& snext = *splitter;
- if (snext.empty()) {
- continue;
- }
- // the next line doesn't start an entity, so maybe it is
- // just a continuation for this line, keep going
- if (!IsEntityDef(snext)) {
- s.append(snext);
- n2 = s.find_last_of(')');
- ok = !(n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';');
- }
- else {
- break;
- }
- }
- if(!ok) {
- DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line));
- continue;
- }
- }
-
- if (map.find(id) != map.end()) {
- DefaultLogger::get()->warn(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line));
- }
-
- std::string::size_type ns = n0;
- do ++ns; while( IsSpace(s.at(ns)));
- std::string::size_type ne = n1;
- do --ne; while( IsSpace(s.at(ne)));
- std::string type = s.substr(ns,ne-ns+1);
- std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char> );
- const char* sz = scheme.GetStaticStringForToken(type);
- if(sz) {
- const std::string::size_type len = n2-n1+1;
- char* const copysz = new char[len+1];
- std::copy(s.c_str()+n1,s.c_str()+n2+1,copysz);
- copysz[len] = '\0';
- db.InternInsert(new LazyObject(db,id,line,sz,copysz));
- }
- if(!has_next) {
- ++splitter;
- }
- }
-
- if (!splitter) {
- DefaultLogger::get()->warn("STEP: ignoring unexpected EOF");
- }
-
- if ( !DefaultLogger::isNullLogger()){
- DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records with ",
- db.GetRefs().size()," inverse index entries"));
- }
+ db.SetSchema(scheme);
+ db.SetTypesToTrack(types_to_track,len);
+ db.SetInverseIndicesToTrack(inverse_indices_to_track,len2);
+
+ const DB::ObjectMap& map = db.GetObjects();
+ LineSplitter& splitter = db.GetSplitter();
+
+ while (splitter) {
+ bool has_next = false;
+ std::string s = *splitter;
+ if (s == "ENDSEC;") {
+ break;
+ }
+ s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
+
+ // want one-based line numbers for human readers, so +1
+ const uint64_t line = splitter.get_index()+1;
+ // LineSplitter already ignores empty lines
+ ai_assert(s.length());
+ if (s[0] != '#') {
+ DefaultLogger::get()->warn(AddLineNumber("expected token \'#\'",line));
+ ++splitter;
+ continue;
+ }
+ // ---
+ // extract id, entity class name and argument string,
+ // but don't create the actual object yet.
+ // ---
+ const std::string::size_type n0 = s.find_first_of('=');
+ if (n0 == std::string::npos) {
+ DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line));
+ ++splitter;
+ continue;
+ }
+
+ const uint64_t id = strtoul10_64(s.substr(1,n0-1).c_str());
+ if (!id) {
+ DefaultLogger::get()->warn(AddLineNumber("expected positive, numeric entity id",line));
+ ++splitter;
+ continue;
+ }
+ std::string::size_type n1 = s.find_first_of('(',n0);
+ if (n1 == std::string::npos) {
+ has_next = true;
+ bool ok = false;
+ for( ++splitter; splitter; ++splitter) {
+ const std::string& snext = *splitter;
+ if (snext.empty()) {
+ continue;
+ }
+
+ // the next line doesn't start an entity, so maybe it is
+ // just a continuation for this line, keep going
+ if (!IsEntityDef(snext)) {
+ s.append(snext);
+ n1 = s.find_first_of('(',n0);
+ ok = (n1 != std::string::npos);
+ }
+ else {
+ break;
+ }
+ }
+
+ if(!ok) {
+ DefaultLogger::get()->warn(AddLineNumber("expected token \'(\'",line));
+ continue;
+ }
+ }
+
+ std::string::size_type n2 = s.find_last_of(')');
+ if (n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';') {
+
+ has_next = true;
+ bool ok = false;
+ for( ++splitter; splitter; ++splitter) {
+ const std::string& snext = *splitter;
+ if (snext.empty()) {
+ continue;
+ }
+ // the next line doesn't start an entity, so maybe it is
+ // just a continuation for this line, keep going
+ if (!IsEntityDef(snext)) {
+ s.append(snext);
+ n2 = s.find_last_of(')');
+ ok = !(n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';');
+ }
+ else {
+ break;
+ }
+ }
+ if(!ok) {
+ DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line));
+ continue;
+ }
+ }
+
+ if (map.find(id) != map.end()) {
+ DefaultLogger::get()->warn(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line));
+ }
+
+ std::string::size_type ns = n0;
+ do ++ns; while( IsSpace(s.at(ns)));
+ std::string::size_type ne = n1;
+ do --ne; while( IsSpace(s.at(ne)));
+ std::string type = s.substr(ns,ne-ns+1);
+ std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char> );
+ const char* sz = scheme.GetStaticStringForToken(type);
+ if(sz) {
+ const std::string::size_type len = n2-n1+1;
+ char* const copysz = new char[len+1];
+ std::copy(s.c_str()+n1,s.c_str()+n2+1,copysz);
+ copysz[len] = '\0';
+ db.InternInsert(new LazyObject(db,id,line,sz,copysz));
+ }
+ if(!has_next) {
+ ++splitter;
+ }
+ }
+
+ if (!splitter) {
+ DefaultLogger::get()->warn("STEP: ignoring unexpected EOF");
+ }
+
+ if ( !DefaultLogger::isNullLogger()){
+ DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records with ",
+ db.GetRefs().size()," inverse index entries"));
+ }
}
// ------------------------------------------------------------------------------------------------
-boost::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
+std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
{
- const char* cur = inout;
- SkipSpaces(&cur);
- if (*cur == ',' || IsSpaceOrNewLine(*cur)) {
- throw STEP::SyntaxError("unexpected token, expected parameter",line);
- }
-
- // just skip over constructions such as IFCPLANEANGLEMEASURE(0.01) and read only the value
- if (schema) {
- bool ok = false;
- for(const char* t = cur; *t && *t != ')' && *t != ','; ++t) {
- if (*t=='(') {
- if (!ok) {
- break;
- }
- for(--t;IsSpace(*t);--t);
- std::string s(cur,static_cast<size_t>(t-cur+1));
- std::transform(s.begin(),s.end(),s.begin(),&ToLower<char> );
- if (schema->IsKnownToken(s)) {
- for(cur = t+1;*cur++ != '(';);
- const boost::shared_ptr<const EXPRESS::DataType> dt = Parse(cur);
- inout = *cur ? cur+1 : cur;
- return dt;
- }
- break;
- }
- else if (!IsSpace(*t)) {
- ok = true;
- }
- }
- }
-
- if (*cur == '*' ) {
- inout = cur+1;
- return boost::make_shared<EXPRESS::ISDERIVED>();
- }
- else if (*cur == '$' ) {
- inout = cur+1;
- return boost::make_shared<EXPRESS::UNSET>();
- }
- else if (*cur == '(' ) {
- // start of an aggregate, further parsing is done by the LIST factory constructor
- inout = cur;
- return EXPRESS::LIST::Parse(inout,line,schema);
- }
- else if (*cur == '.' ) {
- // enum (includes boolean)
- const char* start = ++cur;
- for(;*cur != '.';++cur) {
- if (*cur == '\0') {
- throw STEP::SyntaxError("enum not closed",line);
- }
- }
- inout = cur+1;
- return boost::make_shared<EXPRESS::ENUMERATION>(std::string(start, static_cast<size_t>(cur-start) ));
- }
- else if (*cur == '#' ) {
- // object reference
- return boost::make_shared<EXPRESS::ENTITY>(strtoul10_64(++cur,&inout));
- }
- else if (*cur == '\'' ) {
- // string literal
- const char* start = ++cur;
-
- for(;*cur != '\'';++cur) {
- if (*cur == '\0') {
- throw STEP::SyntaxError("string literal not closed",line);
- }
- }
-
- if (cur[1] == '\'') {
- // Vesanen: more than 2 escaped ' in one literal!
- do {
- for(cur += 2;*cur != '\'';++cur) {
- if (*cur == '\0') {
- throw STEP::SyntaxError("string literal not closed",line);
- }
- }
- }
- while(cur[1] == '\'');
- }
-
- inout = cur + 1;
-
- // assimp is supposed to output UTF8 strings, so we have to deal
- // with foreign encodings.
- std::string stemp = std::string(start, static_cast<size_t>(cur - start));
- if(!StringToUTF8(stemp)) {
- // TODO: route this to a correct logger with line numbers etc., better error messages
- DefaultLogger::get()->error("an error occurred reading escape sequences in ASCII text");
- }
-
- return boost::make_shared<EXPRESS::STRING>(stemp);
- }
- else if (*cur == '\"' ) {
- throw STEP::SyntaxError("binary data not supported yet",line);
- }
-
- // else -- must be a number. if there is a decimal dot in it,
- // parse it as real value, otherwise as integer.
- const char* start = cur;
- for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
- if (*cur == '.') {
- double f;
- inout = fast_atoreal_move<double>(start,f);
- return boost::make_shared<EXPRESS::REAL>(f);
- }
- }
-
- bool neg = false;
- if (*start == '-') {
- neg = true;
- ++start;
- }
- else if (*start == '+') {
- ++start;
- }
- int64_t num = static_cast<int64_t>( strtoul10_64(start,&inout) );
- return boost::make_shared<EXPRESS::INTEGER>(neg?-num:num);
+ const char* cur = inout;
+ SkipSpaces(&cur);
+ if (*cur == ',' || IsSpaceOrNewLine(*cur)) {
+ throw STEP::SyntaxError("unexpected token, expected parameter",line);
+ }
+
+ // just skip over constructions such as IFCPLANEANGLEMEASURE(0.01) and read only the value
+ if (schema) {
+ bool ok = false;
+ for(const char* t = cur; *t && *t != ')' && *t != ','; ++t) {
+ if (*t=='(') {
+ if (!ok) {
+ break;
+ }
+ for(--t;IsSpace(*t);--t);
+ std::string s(cur,static_cast<size_t>(t-cur+1));
+ std::transform(s.begin(),s.end(),s.begin(),&ToLower<char> );
+ if (schema->IsKnownToken(s)) {
+ for(cur = t+1;*cur++ != '(';);
+ const std::shared_ptr<const EXPRESS::DataType> dt = Parse(cur);
+ inout = *cur ? cur+1 : cur;
+ return dt;
+ }
+ break;
+ }
+ else if (!IsSpace(*t)) {
+ ok = true;
+ }
+ }
+ }
+
+ if (*cur == '*' ) {
+ inout = cur+1;
+ return std::make_shared<EXPRESS::ISDERIVED>();
+ }
+ else if (*cur == '$' ) {
+ inout = cur+1;
+ return std::make_shared<EXPRESS::UNSET>();
+ }
+ else if (*cur == '(' ) {
+ // start of an aggregate, further parsing is done by the LIST factory constructor
+ inout = cur;
+ return EXPRESS::LIST::Parse(inout,line,schema);
+ }
+ else if (*cur == '.' ) {
+ // enum (includes boolean)
+ const char* start = ++cur;
+ for(;*cur != '.';++cur) {
+ if (*cur == '\0') {
+ throw STEP::SyntaxError("enum not closed",line);
+ }
+ }
+ inout = cur+1;
+ return std::make_shared<EXPRESS::ENUMERATION>(std::string(start, static_cast<size_t>(cur-start) ));
+ }
+ else if (*cur == '#' ) {
+ // object reference
+ return std::make_shared<EXPRESS::ENTITY>(strtoul10_64(++cur,&inout));
+ }
+ else if (*cur == '\'' ) {
+ // string literal
+ const char* start = ++cur;
+
+ for(;*cur != '\'';++cur) {
+ if (*cur == '\0') {
+ throw STEP::SyntaxError("string literal not closed",line);
+ }
+ }
+
+ if (cur[1] == '\'') {
+ // Vesanen: more than 2 escaped ' in one literal!
+ do {
+ for(cur += 2;*cur != '\'';++cur) {
+ if (*cur == '\0') {
+ throw STEP::SyntaxError("string literal not closed",line);
+ }
+ }
+ }
+ while(cur[1] == '\'');
+ }
+
+ inout = cur + 1;
+
+ // assimp is supposed to output UTF8 strings, so we have to deal
+ // with foreign encodings.
+ std::string stemp = std::string(start, static_cast<size_t>(cur - start));
+ if(!StringToUTF8(stemp)) {
+ // TODO: route this to a correct logger with line numbers etc., better error messages
+ DefaultLogger::get()->error("an error occurred reading escape sequences in ASCII text");
+ }
+
+ return std::make_shared<EXPRESS::STRING>(stemp);
+ }
+ else if (*cur == '\"' ) {
+ throw STEP::SyntaxError("binary data not supported yet",line);
+ }
+
+ // else -- must be a number. if there is a decimal dot in it,
+ // parse it as real value, otherwise as integer.
+ const char* start = cur;
+ for(;*cur && *cur != ',' && *cur != ')' && !IsSpace(*cur);++cur) {
+ if (*cur == '.') {
+ double f;
+ inout = fast_atoreal_move<double>(start,f);
+ return std::make_shared<EXPRESS::REAL>(f);
+ }
+ }
+
+ bool neg = false;
+ if (*start == '-') {
+ neg = true;
+ ++start;
+ }
+ else if (*start == '+') {
+ ++start;
+ }
+ int64_t num = static_cast<int64_t>( strtoul10_64(start,&inout) );
+ return std::make_shared<EXPRESS::INTEGER>(neg?-num:num);
}
// ------------------------------------------------------------------------------------------------
-boost::shared_ptr<const EXPRESS::LIST> EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
+std::shared_ptr<const EXPRESS::LIST> EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/)
{
- const boost::shared_ptr<EXPRESS::LIST> list = boost::make_shared<EXPRESS::LIST>();
- EXPRESS::LIST::MemberList& members = list->members;
-
- const char* cur = inout;
- if (*cur++ != '(') {
- throw STEP::SyntaxError("unexpected token, expected \'(\' token at beginning of list",line);
- }
-
- // estimate the number of items upfront - lists can grow large
- size_t count = 1;
- for(const char* c=cur; *c && *c != ')'; ++c) {
- count += (*c == ',' ? 1 : 0);
- }
-
- members.reserve(count);
-
- for(;;++cur) {
- if (!*cur) {
- throw STEP::SyntaxError("unexpected end of line while reading list");
- }
- SkipSpaces(cur,&cur);
- if (*cur == ')') {
- break;
- }
-
- members.push_back( EXPRESS::DataType::Parse(cur,line,schema));
- SkipSpaces(cur,&cur);
-
- if (*cur != ',') {
- if (*cur == ')') {
- break;
- }
- throw STEP::SyntaxError("unexpected token, expected \',\' or \')\' token after list element",line);
- }
- }
-
- inout = cur+1;
- return list;
+ const std::shared_ptr<EXPRESS::LIST> list = std::make_shared<EXPRESS::LIST>();
+ EXPRESS::LIST::MemberList& members = list->members;
+
+ const char* cur = inout;
+ if (*cur++ != '(') {
+ throw STEP::SyntaxError("unexpected token, expected \'(\' token at beginning of list",line);
+ }
+
+ // estimate the number of items upfront - lists can grow large
+ size_t count = 1;
+ for(const char* c=cur; *c && *c != ')'; ++c) {
+ count += (*c == ',' ? 1 : 0);
+ }
+
+ members.reserve(count);
+
+ for(;;++cur) {
+ if (!*cur) {
+ throw STEP::SyntaxError("unexpected end of line while reading list");
+ }
+ SkipSpaces(cur,&cur);
+ if (*cur == ')') {
+ break;
+ }
+
+ members.push_back( EXPRESS::DataType::Parse(cur,line,schema));
+ SkipSpaces(cur,&cur);
+
+ if (*cur != ',') {
+ if (*cur == ')') {
+ break;
+ }
+ throw STEP::SyntaxError("unexpected token, expected \',\' or \')\' token after list element",line);
+ }
+ }
+
+ inout = cur+1;
+ return list;
}
// ------------------------------------------------------------------------------------------------
STEP::LazyObject::LazyObject(DB& db, uint64_t id,uint64_t /*line*/, const char* const type,const char* args)
- : id(id)
- , type(type)
- , db(db)
- , args(args)
- , obj()
+ : id(id)
+ , type(type)
+ , db(db)
+ , args(args)
+ , obj()
{
- // find any external references and store them in the database.
- // this helps us emulate STEPs INVERSE fields.
- if (db.KeepInverseIndicesForType(type)) {
- const char* a = args;
-
- // do a quick scan through the argument tuple and watch out for entity references
- int64_t skip_depth = 0;
- while(*a) {
- if (*a == '(') {
- ++skip_depth;
- }
- else if (*a == ')') {
- --skip_depth;
- }
-
- if (skip_depth >= 1 && *a=='#') {
- const char* tmp;
- const int64_t num = static_cast<int64_t>( strtoul10_64(a+1,&tmp) );
- db.MarkRef(num,id);
- }
- ++a;
- }
-
- }
+ // find any external references and store them in the database.
+ // this helps us emulate STEPs INVERSE fields.
+ if (db.KeepInverseIndicesForType(type)) {
+ const char* a = args;
+
+ // do a quick scan through the argument tuple and watch out for entity references
+ int64_t skip_depth = 0;
+ while(*a) {
+ if (*a == '(') {
+ ++skip_depth;
+ }
+ else if (*a == ')') {
+ --skip_depth;
+ }
+
+ if (skip_depth >= 1 && *a=='#') {
+ const char* tmp;
+ const int64_t num = static_cast<int64_t>( strtoul10_64(a+1,&tmp) );
+ db.MarkRef(num,id);
+ }
+ ++a;
+ }
+
+ }
}
// ------------------------------------------------------------------------------------------------
-STEP::LazyObject::~LazyObject()
+STEP::LazyObject::~LazyObject()
{
- // make sure the right dtor/operator delete get called
- if (obj) {
- delete obj;
- }
- else delete[] args;
+ // make sure the right dtor/operator delete get called
+ if (obj) {
+ delete obj;
+ }
+ else delete[] args;
}
// ------------------------------------------------------------------------------------------------
void STEP::LazyObject::LazyInit() const
{
- const EXPRESS::ConversionSchema& schema = db.GetSchema();
- STEP::ConvertObjectProc proc = schema.GetConverterProc(type);
-
- if (!proc) {
- throw STEP::TypeError("unknown object type: " + std::string(type),id);
- }
-
- const char* acopy = args;
- boost::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
- delete[] args;
- args = NULL;
-
- // if the converter fails, it should throw an exception, but it should never return NULL
- try {
- obj = proc(db,*conv_args);
- }
- catch(const TypeError& t) {
- // augment line and entity information
- throw TypeError(t.what(),id);
- }
- ++db.evaluated_count;
- ai_assert(obj);
-
- // store the original id in the object instance
- obj->SetID(id);
+ const EXPRESS::ConversionSchema& schema = db.GetSchema();
+ STEP::ConvertObjectProc proc = schema.GetConverterProc(type);
+
+ if (!proc) {
+ throw STEP::TypeError("unknown object type: " + std::string(type),id);
+ }
+
+ const char* acopy = args;
+ std::shared_ptr<const EXPRESS::LIST> conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema());
+ delete[] args;
+ args = NULL;
+
+ // if the converter fails, it should throw an exception, but it should never return NULL
+ try {
+ obj = proc(db,*conv_args);
+ }
+ catch(const TypeError& t) {
+ // augment line and entity information
+ throw TypeError(t.what(),id);
+ }
+ ++db.evaluated_count;
+ ai_assert(obj);
+
+ // store the original id in the object instance
+ obj->SetID(id);
}
diff --git a/src/3rdparty/assimp/code/STEPFileReader.h b/src/3rdparty/assimp/code/STEPFileReader.h
index 432c620db..c5bc88a5e 100644
--- a/src/3rdparty/assimp/code/STEPFileReader.h
+++ b/src/3rdparty/assimp/code/STEPFileReader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,18 +46,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace STEP {
- // ### Parsing a STEP file is a twofold procedure ###
- // --------------------------------------------------------------------------
- // 1) read file header and return to caller, who checks if the
- // file is of a supported schema ..
- DB* ReadFileHeader(boost::shared_ptr<IOStream> stream);
- // --------------------------------------------------------------------------
- // 2) read the actual file contents using a user-supplied set of
- // conversion functions to interpret the data.
- void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const* types_to_track, size_t len, const char* const* inverse_indices_to_track, size_t len2);
- template <size_t N, size_t N2> inline void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const (&arr)[N], const char* const (&arr2)[N2]) {
- return ReadFile(db,scheme,arr,N,arr2,N2);
- }
+ // ### Parsing a STEP file is a twofold procedure ###
+ // --------------------------------------------------------------------------
+ // 1) read file header and return to caller, who checks if the
+ // file is of a supported schema ..
+ DB* ReadFileHeader(std::shared_ptr<IOStream> stream);
+ // --------------------------------------------------------------------------
+ // 2) read the actual file contents using a user-supplied set of
+ // conversion functions to interpret the data.
+ void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const* types_to_track, size_t len, const char* const* inverse_indices_to_track, size_t len2);
+ template <size_t N, size_t N2> inline void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const (&arr)[N], const char* const (&arr2)[N2]) {
+ return ReadFile(db,scheme,arr,N,arr2,N2);
+ }
} // ! STEP
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/STLExporter.cpp b/src/3rdparty/assimp/code/STLExporter.cpp
index 7824a68fa..09e01626d 100644
--- a/src/3rdparty/assimp/code/STLExporter.cpp
+++ b/src/3rdparty/assimp/code/STLExporter.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,58 +23,64 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
+
#if !defined(ASSIMP_BUILD_NO_EXPORT) && !defined(ASSIMP_BUILD_NO_STL_EXPORTER)
#include "STLExporter.h"
-#include "../include/assimp/version.h"
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/Exporter.hpp>
+#include <memory>
+#include "Exceptional.h"
+#include "ByteSwapper.h"
using namespace Assimp;
-namespace Assimp {
+namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp
-void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
- // invoke the exporter
- STLExporter exporter(pFile, pScene);
+ // invoke the exporter
+ STLExporter exporter(pFile, pScene);
- // we're still here - export successfully completed. Write the file.
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
- }
+ // we're still here - export successfully completed. Write the file.
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
+ }
- outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+ outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
-void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
+void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
- // invoke the exporter
- STLExporter exporter(pFile, pScene, true);
+ // invoke the exporter
+ STLExporter exporter(pFile, pScene, true);
- // we're still here - export successfully completed. Write the file.
- boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
- if(outfile == NULL) {
- throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
- }
+ // we're still here - export successfully completed. Write the file.
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wb"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
+ }
- outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
+ outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
}
} // end of namespace Assimp
@@ -83,91 +89,91 @@ void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene*
// ------------------------------------------------------------------------------------------------
STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool binary)
: filename(_filename)
-, pScene(pScene)
-, endl("\n")
+, endl("\n")
{
- // make sure that all formatting happens using the standard, C locale and not the user's current locale
- const std::locale& l = std::locale("C");
- mOutput.imbue(l);
- if (binary) {
- char buf[80] = {0} ;
- buf[0] = 'A'; buf[1] = 's'; buf[2] = 's'; buf[3] = 'i'; buf[4] = 'm'; buf[5] = 'p';
- buf[6] = 'S'; buf[7] = 'c'; buf[8] = 'e'; buf[9] = 'n'; buf[10] = 'e';
- mOutput.write(buf, 80);
- unsigned int meshnum = 0;
- for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- for (unsigned int j = 0; j < pScene->mMeshes[i]->mNumFaces; ++j) {
- meshnum++;
- }
- }
- AI_SWAP4(meshnum);
- mOutput.write((char *)&meshnum, 4);
- for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- WriteMeshBinary(pScene->mMeshes[i]);
- }
- } else {
- const std::string& name = "AssimpScene";
-
- mOutput << "solid " << name << endl;
- for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
- WriteMesh(pScene->mMeshes[i]);
- }
- mOutput << "endsolid " << name << endl;
- }
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ const std::locale& l = std::locale("C");
+ mOutput.imbue(l);
+ mOutput.precision(16);
+ if (binary) {
+ char buf[80] = {0} ;
+ buf[0] = 'A'; buf[1] = 's'; buf[2] = 's'; buf[3] = 'i'; buf[4] = 'm'; buf[5] = 'p';
+ buf[6] = 'S'; buf[7] = 'c'; buf[8] = 'e'; buf[9] = 'n'; buf[10] = 'e';
+ mOutput.write(buf, 80);
+ unsigned int meshnum = 0;
+ for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ for (unsigned int j = 0; j < pScene->mMeshes[i]->mNumFaces; ++j) {
+ meshnum++;
+ }
+ }
+ AI_SWAP4(meshnum);
+ mOutput.write((char *)&meshnum, 4);
+ for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ WriteMeshBinary(pScene->mMeshes[i]);
+ }
+ } else {
+ const std::string& name = "AssimpScene";
+
+ mOutput << "solid " << name << endl;
+ for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+ WriteMesh(pScene->mMeshes[i]);
+ }
+ mOutput << "endsolid " << name << endl;
+ }
}
// ------------------------------------------------------------------------------------------------
void STLExporter :: WriteMesh(const aiMesh* m)
{
- for (unsigned int i = 0; i < m->mNumFaces; ++i) {
- const aiFace& f = m->mFaces[i];
-
- // we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
- // but nonetheless we have to expect per-vertex normals.
- aiVector3D nor;
- if (m->mNormals) {
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- nor += m->mNormals[f.mIndices[a]];
- }
- nor.Normalize();
- }
- mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
- mOutput << " outer loop" << endl;
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- const aiVector3D& v = m->mVertices[f.mIndices[a]];
- mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl;
- }
-
- mOutput << " endloop" << endl;
- mOutput << " endfacet" << endl << endl;
- }
+ for (unsigned int i = 0; i < m->mNumFaces; ++i) {
+ const aiFace& f = m->mFaces[i];
+
+ // we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
+ // but nonetheless we have to expect per-vertex normals.
+ aiVector3D nor;
+ if (m->mNormals) {
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ nor += m->mNormals[f.mIndices[a]];
+ }
+ nor.Normalize();
+ }
+ mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
+ mOutput << " outer loop" << endl;
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ const aiVector3D& v = m->mVertices[f.mIndices[a]];
+ mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl;
+ }
+
+ mOutput << " endloop" << endl;
+ mOutput << " endfacet" << endl << endl;
+ }
}
void STLExporter :: WriteMeshBinary(const aiMesh* m)
{
- for (unsigned int i = 0; i < m->mNumFaces; ++i) {
- const aiFace& f = m->mFaces[i];
- // we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
- // but nonetheless we have to expect per-vertex normals.
- aiVector3D nor;
- if (m->mNormals) {
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- nor += m->mNormals[f.mIndices[a]];
- }
- nor.Normalize();
- }
- float nx = nor.x, ny = nor.y, nz = nor.z;
- AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
- mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
- for(unsigned int a = 0; a < f.mNumIndices; ++a) {
- const aiVector3D& v = m->mVertices[f.mIndices[a]];
- float vx = v.x, vy = v.y, vz = v.z;
- AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
- mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
- }
- char dummy[2] = {0};
- mOutput.write(dummy, 2);
- }
+ for (unsigned int i = 0; i < m->mNumFaces; ++i) {
+ const aiFace& f = m->mFaces[i];
+ // we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
+ // but nonetheless we have to expect per-vertex normals.
+ aiVector3D nor;
+ if (m->mNormals) {
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ nor += m->mNormals[f.mIndices[a]];
+ }
+ nor.Normalize();
+ }
+ float nx = nor.x, ny = nor.y, nz = nor.z;
+ AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
+ mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
+ for(unsigned int a = 0; a < f.mNumIndices; ++a) {
+ const aiVector3D& v = m->mVertices[f.mIndices[a]];
+ float vx = v.x, vy = v.y, vz = v.z;
+ AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
+ mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
+ }
+ char dummy[2] = {0};
+ mOutput.write(dummy, 2);
+ }
}
#endif
diff --git a/src/3rdparty/assimp/code/STLExporter.h b/src/3rdparty/assimp/code/STLExporter.h
index 71f065762..44b12344f 100644
--- a/src/3rdparty/assimp/code/STLExporter.h
+++ b/src/3rdparty/assimp/code/STLExporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -48,8 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene;
struct aiNode;
+struct aiMesh;
-namespace Assimp
+namespace Assimp
{
// ------------------------------------------------------------------------------------------------
@@ -58,26 +59,25 @@ namespace Assimp
class STLExporter
{
public:
- /// Constructor for a specific scene to export
- STLExporter(const char* filename, const aiScene* pScene, bool binary = false);
+ /// Constructor for a specific scene to export
+ STLExporter(const char* filename, const aiScene* pScene, bool binary = false);
public:
- /// public stringstreams to write all output into
- std::ostringstream mOutput;
+ /// public stringstreams to write all output into
+ std::ostringstream mOutput;
private:
- void WriteMesh(const aiMesh* m);
- void WriteMeshBinary(const aiMesh* m);
+ void WriteMesh(const aiMesh* m);
+ void WriteMeshBinary(const aiMesh* m);
private:
- const std::string filename;
- const aiScene* const pScene;
+ const std::string filename;
- // this endl() doesn't flush() the stream
- const std::string endl;
+ // this endl() doesn't flush() the stream
+ const std::string endl;
};
}
diff --git a/src/3rdparty/assimp/code/STLLoader.cpp b/src/3rdparty/assimp/code/STLLoader.cpp
index 567f4875b..95fce47e2 100644
--- a/src/3rdparty/assimp/code/STLLoader.cpp
+++ b/src/3rdparty/assimp/code/STLLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,428 +25,489 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the STL importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_STL_IMPORTER
// internal headers
#include "STLLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
using namespace Assimp;
namespace {
static const aiImporterDesc desc = {
- "Stereolithography (STL) Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "stl"
+ "Stereolithography (STL) Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "stl"
};
// A valid binary STL buffer should consist of the following elements, in order:
// 1) 80 byte header
// 2) 4 byte face count
// 3) 50 bytes per face
-bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
- if (fileSize < 84)
- return false;
+static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
+ if( fileSize < 84 ) {
+ return false;
+ }
- const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
- const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
+ const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
+ const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
- return expectedBinaryFileSize == fileSize;
+ return expectedBinaryFileSize == fileSize;
}
// An ascii STL buffer will begin with "solid NAME", where NAME is optional.
// Note: The "solid NAME" check is necessary, but not sufficient, to determine
// if the buffer is ASCII; a binary header could also begin with "solid NAME".
-bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
- if (IsBinarySTL(buffer, fileSize))
- return false;
-
- const char* bufferEnd = buffer + fileSize;
-
- if (!SkipSpaces(&buffer))
- return false;
-
- if (buffer + 5 >= bufferEnd)
- return false;
-
- return strncmp(buffer, "solid", 5) == 0;
+static bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
+ if (IsBinarySTL(buffer, fileSize))
+ return false;
+
+ const char* bufferEnd = buffer + fileSize;
+
+ if (!SkipSpaces(&buffer))
+ return false;
+
+ if (buffer + 5 >= bufferEnd)
+ return false;
+
+ bool isASCII( strncmp( buffer, "solid", 5 ) == 0 );
+ if( isASCII ) {
+ // A lot of importers are write solid even if the file is binary. So we have to check for ASCII-characters.
+ if( fileSize >= 500 ) {
+ isASCII = true;
+ for( unsigned int i = 0; i < 500; i++ ) {
+ if( buffer[ i ] > 127 ) {
+ isASCII = false;
+ break;
+ }
+ }
+ }
+ }
+ return isASCII;
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
STLImporter::STLImporter()
+ : mBuffer(),
+ fileSize(),
+ pScene()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
STLImporter::~STLImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- const std::string extension = GetExtension(pFile);
-
- if (extension == "stl")
- return true;
- else if (!extension.length() || checkSig) {
- if (!pIOHandler)
- return true;
- const char* tokens[] = {"STL","solid"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
- }
- return false;
+ const std::string extension = GetExtension(pFile);
+
+ if( extension == "stl" ) {
+ return true;
+ } else if (!extension.length() || checkSig) {
+ if( !pIOHandler ) {
+ return true;
+ }
+ const char* tokens[] = {"STL","solid"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2);
+ }
+
+ return false;
}
// ------------------------------------------------------------------------------------------------
-const aiImporterDesc* STLImporter::GetInfo () const
+const aiImporterDesc* STLImporter::GetInfo () const {
+ return &desc;
+}
+
+void addFacesToMesh(aiMesh* pMesh)
{
- return &desc;
+ pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+ for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) {
+
+ aiFace& face = pMesh->mFaces[i];
+ face.mIndices = new unsigned int[face.mNumIndices = 3];
+ for (unsigned int o = 0; o < 3;++o,++p) {
+ face.mIndices[o] = p;
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void STLImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void STLImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
- // Check whether we can read from the file
- if( file.get() == NULL) {
- throw DeadlyImportError( "Failed to open STL file " + pFile + ".");
- }
-
- fileSize = (unsigned int)file->FileSize();
-
- // allocate storage and copy the contents of the file to a memory buffer
- // (terminate it with zero)
- std::vector<char> mBuffer2;
- TextFileToBuffer(file.get(),mBuffer2);
-
- this->pScene = pScene;
- this->mBuffer = &mBuffer2[0];
-
- // the default vertex color is light gray.
- clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f;
-
- // allocate one mesh
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh();
- pMesh->mMaterialIndex = 0;
-
- // allocate a single node
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
-
- bool bMatClr = false;
-
- if (IsBinarySTL(mBuffer, fileSize)) {
- bMatClr = LoadBinaryFile();
- } else if (IsAsciiSTL(mBuffer, fileSize)) {
- LoadASCIIFile();
- } else {
- throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
- }
-
- // now copy faces
- pMesh->mFaces = new aiFace[pMesh->mNumFaces];
- for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) {
-
- aiFace& face = pMesh->mFaces[i];
- face.mIndices = new unsigned int[face.mNumIndices = 3];
- for (unsigned int o = 0; o < 3;++o,++p) {
- face.mIndices[o] = p;
- }
- }
-
- // create a single default material, using a light gray diffuse color for consistency with
- // other geometric types (e.g., PLY).
- aiMaterial* pcMat = new aiMaterial();
- aiString s;
- s.Set(AI_DEFAULT_MATERIAL_NAME);
- pcMat->AddProperty(&s, AI_MATKEY_NAME);
-
- aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f);
- if (bMatClr) {
- clrDiffuse = clrColorDefault;
- }
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
- clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
- pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
-
- pScene->mNumMaterials = 1;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = pcMat;
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL) {
+ throw DeadlyImportError( "Failed to open STL file " + pFile + ".");
+ }
+
+ fileSize = (unsigned int)file->FileSize();
+
+ // allocate storage and copy the contents of the file to a memory buffer
+ // (terminate it with zero)
+ std::vector<char> mBuffer2;
+ TextFileToBuffer(file.get(),mBuffer2);
+
+ this->pScene = pScene;
+ this->mBuffer = &mBuffer2[0];
+
+ // the default vertex color is light gray.
+ clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 0.6f;
+
+ // allocate a single node
+ pScene->mRootNode = new aiNode();
+
+ bool bMatClr = false;
+
+ if (IsBinarySTL(mBuffer, fileSize)) {
+ bMatClr = LoadBinaryFile();
+ } else if (IsAsciiSTL(mBuffer, fileSize)) {
+ LoadASCIIFile();
+ } else {
+ throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
+ }
+
+ // add all created meshes to the single node
+ pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+ pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
+ pScene->mRootNode->mMeshes[i] = i;
+
+ // create a single default material, using a light gray diffuse color for consistency with
+ // other geometric types (e.g., PLY).
+ aiMaterial* pcMat = new aiMaterial();
+ aiString s;
+ s.Set(AI_DEFAULT_MATERIAL_NAME);
+ pcMat->AddProperty(&s, AI_MATKEY_NAME);
+
+ aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f);
+ if (bMatClr) {
+ clrDiffuse = clrColorDefault;
+ }
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
+ clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
+ pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
+
+ pScene->mNumMaterials = 1;
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = pcMat;
}
// ------------------------------------------------------------------------------------------------
// Read an ASCII STL file
void STLImporter::LoadASCIIFile()
{
- aiMesh* pMesh = pScene->mMeshes[0];
-
- const char* sz = mBuffer;
- SkipSpaces(&sz);
- ai_assert(!IsLineEnd(sz));
-
- sz += 5; // skip the "solid"
- SkipSpaces(&sz);
- const char* szMe = sz;
- while (!::IsSpaceOrNewLine(*sz)) {
- sz++;
- }
-
- size_t temp;
- // setup the name of the node
- if ((temp = (size_t)(sz-szMe))) {
-
- pScene->mRootNode->mName.length = temp;
- memcpy(pScene->mRootNode->mName.data,szMe,temp);
- pScene->mRootNode->mName.data[temp] = '\0';
- }
- else pScene->mRootNode->mName.Set("<STL_ASCII>");
-
- // try to guess how many vertices we could have
- // assume we'll need 160 bytes for each face
- pMesh->mNumVertices = ( pMesh->mNumFaces = std::max(1u,fileSize / 160u )) * 3;
- pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
- pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
-
- unsigned int curFace = 0, curVertex = 3;
- for ( ;; )
- {
- // go to the next token
- if(!SkipSpacesAndLineEnd(&sz))
- {
- // seems we're finished although there was no end marker
- DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected");
- break;
- }
- // facet normal -0.13 -0.13 -0.98
- if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5))) {
-
- if (3 != curVertex) {
- DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete");
- }
- if (pMesh->mNumFaces == curFace) {
- ai_assert(pMesh->mNumFaces != 0);
-
- // need to resize the arrays, our size estimate was wrong
- unsigned int iNeededSize = (unsigned int)(sz-mBuffer) / pMesh->mNumFaces;
- if (iNeededSize <= 160)iNeededSize >>= 1; // prevent endless looping
- unsigned int add = (unsigned int)((mBuffer+fileSize)-sz) / iNeededSize;
- add += add >> 3; // add 12.5% as buffer
- iNeededSize = (pMesh->mNumFaces + add)*3;
- aiVector3D* pv = new aiVector3D[iNeededSize];
- memcpy(pv,pMesh->mVertices,pMesh->mNumVertices*sizeof(aiVector3D));
- delete[] pMesh->mVertices;
- pMesh->mVertices = pv;
- pv = new aiVector3D[iNeededSize];
- memcpy(pv,pMesh->mNormals,pMesh->mNumVertices*sizeof(aiVector3D));
- delete[] pMesh->mNormals;
- pMesh->mNormals = pv;
-
- pMesh->mNumVertices = iNeededSize;
- pMesh->mNumFaces += add;
- }
- aiVector3D* vn = &pMesh->mNormals[curFace++*3];
-
- sz += 6;
- curVertex = 0;
- SkipSpaces(&sz);
- if (strncmp(sz,"normal",6)) {
- DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
- }
- else
- {
- sz += 7;
- SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->x );
- SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->y );
- SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->z );
- *(vn+1) = *vn;
- *(vn+2) = *vn;
- }
- }
- // vertex 1.50000 1.50000 0.00000
- else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
- {
- if (3 == curVertex) {
- DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
- }
- else
- {
- sz += 7;
- SkipSpaces(&sz);
- aiVector3D* vn = &pMesh->mVertices[(curFace-1)*3 + curVertex++];
- sz = fast_atoreal_move<float>(sz, (float&)vn->x );
- SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->y );
- SkipSpaces(&sz);
- sz = fast_atoreal_move<float>(sz, (float&)vn->z );
- }
- }
- else if (!::strncmp(sz,"endsolid",8)) {
- // finished!
- break;
- }
- // else skip the whole identifier
- else while (!::IsSpaceOrNewLine(*sz)) {
- ++sz;
- }
- }
-
- if (!curFace) {
- pMesh->mNumFaces = 0;
- throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded");
- }
- pMesh->mNumFaces = curFace;
- pMesh->mNumVertices = curFace*3;
- // we are finished!
+ std::vector<aiMesh*> meshes;
+ const char* sz = mBuffer;
+ const char* bufferEnd = mBuffer + fileSize;
+ std::vector<aiVector3D> positionBuffer;
+ std::vector<aiVector3D> normalBuffer;
+
+ // try to guess how many vertices we could have
+ // assume we'll need 160 bytes for each face
+ size_t sizeEstimate = std::max(1u, fileSize / 160u ) * 3;
+ positionBuffer.reserve(sizeEstimate);
+ normalBuffer.reserve(sizeEstimate);
+
+ while (IsAsciiSTL(sz, bufferEnd - sz))
+ {
+ aiMesh* pMesh = new aiMesh();
+ pMesh->mMaterialIndex = 0;
+ meshes.push_back(pMesh);
+
+ SkipSpaces(&sz);
+ ai_assert(!IsLineEnd(sz));
+
+ sz += 5; // skip the "solid"
+ SkipSpaces(&sz);
+ const char* szMe = sz;
+ while (!::IsSpaceOrNewLine(*sz)) {
+ sz++;
+ }
+
+ size_t temp;
+ // setup the name of the node
+ if ((temp = (size_t)(sz-szMe))) {
+ if (temp >= MAXLEN) {
+ throw DeadlyImportError( "STL: Node name too long" );
+ }
+
+ pScene->mRootNode->mName.length = temp;
+ memcpy(pScene->mRootNode->mName.data,szMe,temp);
+ pScene->mRootNode->mName.data[temp] = '\0';
+ }
+ else pScene->mRootNode->mName.Set("<STL_ASCII>");
+
+ unsigned int faceVertexCounter = 0;
+ for ( ;; )
+ {
+ // go to the next token
+ if(!SkipSpacesAndLineEnd(&sz))
+ {
+ // seems we're finished although there was no end marker
+ DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected");
+ break;
+ }
+ // facet normal -0.13 -0.13 -0.98
+ if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5)) && *(sz + 5) != '\0') {
+
+ if (faceVertexCounter != 3) {
+ DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete");
+ }
+ faceVertexCounter = 0;
+ normalBuffer.push_back(aiVector3D());
+ aiVector3D* vn = &normalBuffer.back();
+
+ sz += 6;
+ SkipSpaces(&sz);
+ if (strncmp(sz,"normal",6)) {
+ DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
+ }
+ else
+ {
+ if (sz[6] == '\0') {
+ throw DeadlyImportError("STL: unexpected EOF while parsing facet");
+ }
+ sz += 7;
+ SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz, (float&)vn->x );
+ SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz, (float&)vn->y );
+ SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz, (float&)vn->z );
+ normalBuffer.push_back(*vn);
+ normalBuffer.push_back(*vn);
+ }
+ }
+ // vertex 1.50000 1.50000 0.00000
+ else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
+ {
+ if (faceVertexCounter >= 3) {
+ DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
+ ++sz;
+ }
+ else
+ {
+ if (sz[6] == '\0') {
+ throw DeadlyImportError("STL: unexpected EOF while parsing facet");
+ }
+ sz += 7;
+ SkipSpaces(&sz);
+ positionBuffer.push_back(aiVector3D());
+ aiVector3D* vn = &positionBuffer.back();
+ sz = fast_atoreal_move<float>(sz, (float&)vn->x );
+ SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz, (float&)vn->y );
+ SkipSpaces(&sz);
+ sz = fast_atoreal_move<float>(sz, (float&)vn->z );
+ faceVertexCounter++;
+ }
+ }
+ else if (!::strncmp(sz,"endsolid",8)) {
+ do {
+ ++sz;
+ } while (!::IsLineEnd(*sz));
+ SkipSpacesAndLineEnd(&sz);
+ // finished!
+ break;
+ }
+ // else skip the whole identifier
+ else {
+ do {
+ ++sz;
+ } while (!::IsSpaceOrNewLine(*sz));
+ }
+ }
+
+ if (positionBuffer.empty()) {
+ pMesh->mNumFaces = 0;
+ throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded");
+ }
+ if (positionBuffer.size() % 3 != 0) {
+ pMesh->mNumFaces = 0;
+ throw DeadlyImportError("STL: Invalid number of vertices");
+ }
+ if (normalBuffer.size() != positionBuffer.size()) {
+ pMesh->mNumFaces = 0;
+ throw DeadlyImportError("Normal buffer size does not match position buffer size");
+ }
+ pMesh->mNumFaces = positionBuffer.size() / 3;
+ pMesh->mNumVertices = positionBuffer.size();
+ pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ memcpy(pMesh->mVertices, &positionBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
+ positionBuffer.clear();
+ pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ memcpy(pMesh->mNormals, &normalBuffer[0].x, pMesh->mNumVertices * sizeof(aiVector3D));
+ normalBuffer.clear();
+
+ // now copy faces
+ addFacesToMesh(pMesh);
+ }
+ // now add the loaded meshes
+ pScene->mNumMeshes = (unsigned int)meshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for (size_t i = 0; i < meshes.size(); i++)
+ {
+ pScene->mMeshes[i] = meshes[i];
+ }
}
// ------------------------------------------------------------------------------------------------
// Read a binary STL file
bool STLImporter::LoadBinaryFile()
{
- // skip the first 80 bytes
- if (fileSize < 84) {
- throw DeadlyImportError("STL: file is too small for the header");
- }
- bool bIsMaterialise = false;
-
- // search for an occurence of "COLOR=" in the header
- const char* sz2 = (const char*)mBuffer;
- const char* const szEnd = sz2+80;
- while (sz2 < szEnd) {
-
- if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&
- 'O' == *sz2++ && 'R' == *sz2++ && '=' == *sz2++) {
-
- // read the default vertex color for facets
- bIsMaterialise = true;
- DefaultLogger::get()->info("STL: Taking code path for Materialise files");
- clrColorDefault.r = (*sz2++) / 255.0f;
- clrColorDefault.g = (*sz2++) / 255.0f;
- clrColorDefault.b = (*sz2++) / 255.0f;
- clrColorDefault.a = (*sz2++) / 255.0f;
- break;
- }
- }
- const unsigned char* sz = (const unsigned char*)mBuffer + 80;
-
- // now read the number of facets
- aiMesh* pMesh = pScene->mMeshes[0];
- pScene->mRootNode->mName.Set("<STL_BINARY>");
-
- pMesh->mNumFaces = *((uint32_t*)sz);
- sz += 4;
-
- if (fileSize < 84 + pMesh->mNumFaces*50) {
- throw DeadlyImportError("STL: file is too small to hold all facets");
- }
-
- if (!pMesh->mNumFaces) {
- throw DeadlyImportError("STL: file is empty. There are no facets defined");
- }
-
- pMesh->mNumVertices = pMesh->mNumFaces*3;
-
- aiVector3D* vp,*vn;
- vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
- vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
-
- for (unsigned int i = 0; i < pMesh->mNumFaces;++i) {
-
- // NOTE: Blender sometimes writes empty normals ... this is not
- // our fault ... the RemoveInvalidData helper step should fix that
- *vn = *((aiVector3D*)sz);
- sz += sizeof(aiVector3D);
- *(vn+1) = *vn;
- *(vn+2) = *vn;
- vn += 3;
-
- *vp++ = *((aiVector3D*)sz);
- sz += sizeof(aiVector3D);
-
- *vp++ = *((aiVector3D*)sz);
- sz += sizeof(aiVector3D);
-
- *vp++ = *((aiVector3D*)sz);
- sz += sizeof(aiVector3D);
-
- uint16_t color = *((uint16_t*)sz);
- sz += 2;
-
- if (color & (1 << 15))
- {
- // seems we need to take the color
- if (!pMesh->mColors[0])
- {
- pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
- for (unsigned int i = 0; i <pMesh->mNumVertices;++i)
- *pMesh->mColors[0]++ = this->clrColorDefault;
- pMesh->mColors[0] -= pMesh->mNumVertices;
-
- DefaultLogger::get()->info("STL: Mesh has vertex colors");
- }
- aiColor4D* clr = &pMesh->mColors[0][i*3];
- clr->a = 1.0f;
- if (bIsMaterialise) // this is reversed
- {
- clr->r = (color & 0x31u) / 31.0f;
- clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;
- clr->b = ((color & (0x31u<<10))>>10u) / 31.0f;
- }
- else
- {
- clr->b = (color & 0x31u) / 31.0f;
- clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;
- clr->r = ((color & (0x31u<<10))>>10u) / 31.0f;
- }
- // assign the color to all vertices of the face
- *(clr+1) = *clr;
- *(clr+2) = *clr;
- }
- }
- if (bIsMaterialise && !pMesh->mColors[0])
- {
- // use the color as diffuse material color
- return true;
- }
- return false;
+ // allocate one mesh
+ pScene->mNumMeshes = 1;
+ pScene->mMeshes = new aiMesh*[1];
+ aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh();
+ pMesh->mMaterialIndex = 0;
+
+ // skip the first 80 bytes
+ if (fileSize < 84) {
+ throw DeadlyImportError("STL: file is too small for the header");
+ }
+ bool bIsMaterialise = false;
+
+ // search for an occurrence of "COLOR=" in the header
+ const unsigned char* sz2 = (const unsigned char*)mBuffer;
+ const unsigned char* const szEnd = sz2+80;
+ while (sz2 < szEnd) {
+
+ if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&
+ 'O' == *sz2++ && 'R' == *sz2++ && '=' == *sz2++) {
+
+ // read the default vertex color for facets
+ bIsMaterialise = true;
+ DefaultLogger::get()->info("STL: Taking code path for Materialise files");
+ clrColorDefault.r = (*sz2++) / 255.0f;
+ clrColorDefault.g = (*sz2++) / 255.0f;
+ clrColorDefault.b = (*sz2++) / 255.0f;
+ clrColorDefault.a = (*sz2++) / 255.0f;
+ break;
+ }
+ }
+ const unsigned char* sz = (const unsigned char*)mBuffer + 80;
+
+ // now read the number of facets
+ pScene->mRootNode->mName.Set("<STL_BINARY>");
+
+ pMesh->mNumFaces = *((uint32_t*)sz);
+ sz += 4;
+
+ if (fileSize < 84 + pMesh->mNumFaces*50) {
+ throw DeadlyImportError("STL: file is too small to hold all facets");
+ }
+
+ if (!pMesh->mNumFaces) {
+ throw DeadlyImportError("STL: file is empty. There are no facets defined");
+ }
+
+ pMesh->mNumVertices = pMesh->mNumFaces*3;
+
+ aiVector3D* vp,*vn;
+ vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+ vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+
+ for (unsigned int i = 0; i < pMesh->mNumFaces;++i) {
+
+ // NOTE: Blender sometimes writes empty normals ... this is not
+ // our fault ... the RemoveInvalidData helper step should fix that
+ *vn = *((aiVector3D*)sz);
+ sz += sizeof(aiVector3D);
+ *(vn+1) = *vn;
+ *(vn+2) = *vn;
+ vn += 3;
+
+ *vp++ = *((aiVector3D*)sz);
+ sz += sizeof(aiVector3D);
+
+ *vp++ = *((aiVector3D*)sz);
+ sz += sizeof(aiVector3D);
+
+ *vp++ = *((aiVector3D*)sz);
+ sz += sizeof(aiVector3D);
+
+ uint16_t color = *((uint16_t*)sz);
+ sz += 2;
+
+ if (color & (1 << 15))
+ {
+ // seems we need to take the color
+ if (!pMesh->mColors[0])
+ {
+ pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
+ for (unsigned int i = 0; i <pMesh->mNumVertices;++i)
+ *pMesh->mColors[0]++ = this->clrColorDefault;
+ pMesh->mColors[0] -= pMesh->mNumVertices;
+
+ DefaultLogger::get()->info("STL: Mesh has vertex colors");
+ }
+ aiColor4D* clr = &pMesh->mColors[0][i*3];
+ clr->a = 1.0f;
+ if (bIsMaterialise) // this is reversed
+ {
+ clr->r = (color & 0x31u) / 31.0f;
+ clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;
+ clr->b = ((color & (0x31u<<10))>>10u) / 31.0f;
+ }
+ else
+ {
+ clr->b = (color & 0x31u) / 31.0f;
+ clr->g = ((color & (0x31u<<5))>>5u) / 31.0f;
+ clr->r = ((color & (0x31u<<10))>>10u) / 31.0f;
+ }
+ // assign the color to all vertices of the face
+ *(clr+1) = *clr;
+ *(clr+2) = *clr;
+ }
+ }
+
+ // now copy faces
+ addFacesToMesh(pMesh);
+
+ if (bIsMaterialise && !pMesh->mColors[0])
+ {
+ // use the color as diffuse material color
+ return true;
+ }
+ return false;
}
#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER
diff --git a/src/3rdparty/assimp/code/STLLoader.h b/src/3rdparty/assimp/code/STLLoader.h
index 396ffd4a5..a0d82dbe8 100644
--- a/src/3rdparty/assimp/code/STLLoader.h
+++ b/src/3rdparty/assimp/code/STLLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,31 +23,31 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file STLLoader.h
- * Declaration of the STL importer class.
+ * Declaration of the STL importer class.
*/
#ifndef AI_STLLOADER_H_INCLUDED
#define AI_STLLOADER_H_INCLUDED
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** Importer class for the sterolithography STL file format
@@ -55,59 +55,59 @@ namespace Assimp {
class STLImporter : public BaseImporter
{
public:
- STLImporter();
- ~STLImporter();
+ STLImporter();
+ ~STLImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details.
- */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details.
+ */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- /** Loads a binary .stl file
- * @return true if the default vertex color must be used as material color
- */
- bool LoadBinaryFile();
+ // -------------------------------------------------------------------
+ /** Loads a binary .stl file
+ * @return true if the default vertex color must be used as material color
+ */
+ bool LoadBinaryFile();
- // -------------------------------------------------------------------
- /** Loads a ASCII text .stl file
- */
- void LoadASCIIFile();
+ // -------------------------------------------------------------------
+ /** Loads a ASCII text .stl file
+ */
+ void LoadASCIIFile();
protected:
- /** Buffer to hold the loaded file */
- const char* mBuffer;
+ /** Buffer to hold the loaded file */
+ const char* mBuffer;
- /** Size of the file, in bytes */
- unsigned int fileSize;
+ /** Size of the file, in bytes */
+ unsigned int fileSize;
- /** Output scene */
- aiScene* pScene;
+ /** Output scene */
+ aiScene* pScene;
- /** Default vertex color */
- aiColor4D clrColorDefault;
+ /** Default vertex color */
+ aiColor4D clrColorDefault;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/SceneCombiner.cpp b/src/3rdparty/assimp/code/SceneCombiner.cpp
index 26d0444a2..b39adbf78 100644
--- a/src/3rdparty/assimp/code/SceneCombiner.cpp
+++ b/src/3rdparty/assimp/code/SceneCombiner.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,1181 +23,1239 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
+// 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
+ * class that combines multiple scenes, meshes, ... into one. Currently
* these utilities are used by the IRR and LWS loaders and the
* OptimizeGraph step.
*/
// ----------------------------------------------------------------------------
-#include "AssimpPCH.h"
#include "SceneCombiner.h"
+#include "StringUtils.h"
#include "fast_atof.h"
#include "Hash.h"
#include "time.h"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+#include <stdio.h>
+#include "ScenePrivate.h"
-namespace Assimp {
+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) {
- DefaultLogger::get()->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;
+ // 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) {
+ DefaultLogger::get()->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,node->mName.length) );
- }
-
- // Process all children recursively
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- AddNodeHashes(node->mChildren[i],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,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);
+ 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);
+ // 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, name.length);
+ const unsigned int hash = SuperFastHash(name.data, name.length);
- // Check whether we find a positive match in one of the given sets
- for (unsigned int i = 0; i < input.size(); ++i) {
+ // 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;
+ 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)
+ std::vector<SceneHelper>& input, unsigned int cur)
{
- ai_assert(NULL != prefix);
- const unsigned int hash = SuperFastHash(node->mName.data,node->mName.length);
+ ai_assert(NULL != prefix);
+ const unsigned int hash = SuperFastHash(node->mName.data,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) {
+ // 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;
- }
- }
+ 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);
+ // 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->mNumMeshes;++i)
+ node->mMeshes[i] += offset;
- for (unsigned int i = 0; i < node->mNumChildren;++i)
- OffsetNodeMeshIndices(node->mChildren[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)
+ unsigned int flags)
{
- ai_assert(NULL != _dest);
-
- // 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);
+ ai_assert(NULL != _dest);
+
+ // 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;
- }
- }
- }
+ 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)
+void SceneCombiner::AttachToGraph ( aiScene* master,
+ std::vector<NodeAttachmentInfo>& src)
{
- ai_assert(NULL != master);
- AttachToGraph(master->mRootNode,src);
+ ai_assert(NULL != master);
+ AttachToGraph(master->mRootNode,src);
}
// ------------------------------------------------------------------------------------------------
-void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master,
- std::vector<AttachmentInfo>& srcList,
- unsigned int flags)
+void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master,
+ std::vector<AttachmentInfo>& srcList,
+ unsigned int flags)
{
- ai_assert(NULL != _dest);
-
- // 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)
- {
+ ai_assert(NULL != _dest);
+
+ // 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);
+ // 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 = ::sprintf(src[i].id,"$%.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,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 = 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 scenegraph 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) {
- DefaultLogger::get()->error(std::string("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
+ 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,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 = 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) {
+ DefaultLogger::get()->error(std::string("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)
+ 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;
- }
+ 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)
+ std::vector<aiMesh*>::const_iterator end)
{
- ai_assert(NULL != out && !out->mNumBones);
-
- // 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 it = asBones.begin(),end = asBones.end(); it != end;++it) {
- // Allocate a bone and setup it's name
- aiBone* pc = out->mBones[out->mNumBones++] = new aiBone();
- pc->mName = aiString( *((*it).second ));
-
- std::vector< BoneSrcIndex >::const_iterator wend = (*it).pSrcBones.end();
-
- // Loop through all bones to be joined for this bone
- for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).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 != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) {
- DefaultLogger::get()->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 coresponding mesh.
- for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) {
- 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;
- }
- }
- }
+ ai_assert(NULL != out && !out->mNumBones);
+
+ // 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 it = asBones.begin(),end = asBones.end(); it != end;++it) {
+ // Allocate a bone and setup it's name
+ aiBone* pc = out->mBones[out->mNumBones++] = new aiBone();
+ pc->mName = aiString( *((*it).second ));
+
+ std::vector< BoneSrcIndex >::const_iterator wend = (*it).pSrcBones.end();
+
+ // Loop through all bones to be joined for this bone
+ for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).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 != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) {
+ DefaultLogger::get()->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 coresponding mesh.
+ for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) {
+ 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)
+ std::vector<aiMesh*>::const_iterator begin,
+ std::vector<aiMesh*>::const_iterator end)
{
- ai_assert(NULL != _out);
-
- if (begin == end) {
- *_out = NULL; // no meshes ...
- return;
- }
-
- // Allocate the output mesh
- aiMesh* out = *_out = new aiMesh();
- out->mMaterialIndex = (*begin)->mMaterialIndex;
-
- // Find out how much output storage we'll need
- for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
- out->mNumVertices += (*it)->mNumVertices;
- out->mNumFaces += (*it)->mNumFaces;
- out->mNumBones += (*it)->mNumBones;
-
- // combine primitive type flags
- out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
- }
-
- 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 DefaultLogger::get()->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 DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals");
- pv2 += (*it)->mNumVertices;
- }
- }
- // copy tangents and bitangents
- 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 DefaultLogger::get()->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 DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs");
- pv2 += (*it)->mNumVertices;
- }
- ++n;
- }
- // copy vertex colors
- n = 0;
- while ((**begin).HasVertexColors(n)) {
- aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
- for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
-
- if ((*it)->mColors[n]) {
- ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
- }
- else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs");
- pv2 += (*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;
+ ai_assert(NULL != _out);
+
+ if (begin == end) {
+ *_out = NULL; // no meshes ...
+ return;
+ }
+
+ // Allocate the output mesh
+ aiMesh* out = *_out = new aiMesh();
+ out->mMaterialIndex = (*begin)->mMaterialIndex;
+
+ // Find out how much output storage we'll need
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+ out->mNumVertices += (*it)->mNumVertices;
+ out->mNumFaces += (*it)->mNumFaces;
+ out->mNumBones += (*it)->mNumBones;
+
+ // combine primitive type flags
+ out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
+ }
+
+ 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 DefaultLogger::get()->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 DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals");
+ pv2 += (*it)->mNumVertices;
+ }
+ }
+ // copy tangents and bitangents
+ 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 DefaultLogger::get()->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 DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs");
+ pv2 += (*it)->mNumVertices;
+ }
+ ++n;
+ }
+ // copy vertex colors
+ n = 0;
+ while ((**begin).HasVertexColors(n)) {
+ aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices];
+ for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) {
+
+ if ((*it)->mColors[n]) {
+ ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D));
+ }
+ else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs");
+ pv2 += (*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)
+ std::vector<aiMaterial*>::const_iterator begin,
+ std::vector<aiMaterial*>::const_iterator end)
{
- ai_assert(NULL != dest);
-
- if (begin == end) {
- *dest = NULL; // no materials ...
- return;
- }
-
- // Allocate the output material
- aiMaterial* out = *dest = new aiMaterial();
-
- // Get the maximal number of properties
- unsigned int size = 0;
- for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
- size += (*it)->mNumProperties;
- }
-
- out->Clear();
- delete[] out->mProperties;
-
- out->mNumAllocated = size;
- out->mNumProperties = 0;
- out->mProperties = new aiMaterialProperty*[out->mNumAllocated];
-
- for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
- for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) {
- aiMaterialProperty* sprop = (*it)->mProperties[i];
-
- // Test if we already have a matching property
- const aiMaterialProperty* prop_exist;
- if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->mType, sprop->mIndex, &prop_exist) != AI_SUCCESS) {
- // If not, we add it to the new material
- aiMaterialProperty* prop = out->mProperties[out->mNumProperties] = new aiMaterialProperty();
-
- prop->mDataLength = sprop->mDataLength;
- prop->mData = new char[prop->mDataLength];
- ::memcpy(prop->mData, sprop->mData, prop->mDataLength);
-
- prop->mIndex = sprop->mIndex;
- prop->mSemantic = sprop->mSemantic;
- prop->mKey = sprop->mKey;
- prop->mType = sprop->mType;
-
- out->mNumProperties++;
- }
- }
- }
+ ai_assert(NULL != dest);
+
+ if (begin == end) {
+ *dest = NULL; // no materials ...
+ return;
+ }
+
+ // Allocate the output material
+ aiMaterial* out = *dest = new aiMaterial();
+
+ // Get the maximal number of properties
+ unsigned int size = 0;
+ for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
+ size += (*it)->mNumProperties;
+ }
+
+ out->Clear();
+ delete[] out->mProperties;
+
+ out->mNumAllocated = size;
+ out->mNumProperties = 0;
+ out->mProperties = new aiMaterialProperty*[out->mNumAllocated];
+
+ for (std::vector<aiMaterial*>::const_iterator it = begin; it != end; ++it) {
+ for(unsigned int i = 0; i < (*it)->mNumProperties; ++i) {
+ aiMaterialProperty* sprop = (*it)->mProperties[i];
+
+ // Test if we already have a matching property
+ const aiMaterialProperty* prop_exist;
+ if(aiGetMaterialProperty(out, sprop->mKey.C_Str(), sprop->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, unsigned int num)
{
- if (!num)
- {
- dest = NULL;
- return;
- }
- dest = new Type*[num];
- for (unsigned int i = 0; i < num;++i) {
- SceneCombiner::Copy(&dest[i],src[i]);
- }
+ if (!num)
+ {
+ dest = NULL;
+ return;
+ }
+ dest = new Type*[num];
+ for (unsigned int i = 0; i < num;++i) {
+ SceneCombiner::Copy(&dest[i],src[i]);
+ }
}
// ------------------------------------------------------------------------------------------------
template <typename Type>
inline void GetArrayCopy (Type*& dest, unsigned int num )
{
- if (!dest)return;
- Type* old = dest;
+ if (!dest)return;
+ Type* old = dest;
- dest = new Type[num];
- ::memcpy(dest, old, sizeof(Type) * num);
+ dest = new Type[num];
+ ::memcpy(dest, old, sizeof(Type) * num);
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src)
{
- // reuse the old scene or allocate a new?
- if (*_dest) {
- (*_dest)->~aiScene();
- new (*_dest) aiScene();
- }
- else *_dest = new aiScene();
-
- ::memcpy(*_dest,src,sizeof(aiScene));
+ // 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)
{
- ai_assert(NULL != _dest && NULL != src);
-
- if (allocate) {
- *_dest = new aiScene();
- }
- aiScene* dest = *_dest;
- ai_assert(dest);
-
- // 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)
- ScenePriv(dest)->mPPStepsApplied = ScenePriv(src) ? ScenePriv(src)->mPPStepsApplied : 0;
+ ai_assert(NULL != _dest && NULL != src);
+
+ if (allocate) {
+ *_dest = new aiScene();
+ }
+ aiScene* dest = *_dest;
+ ai_assert(dest);
+
+ // 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)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiMesh* dest = *_dest = new aiMesh();
+ aiMesh* dest = *_dest = new aiMesh();
- // get a flat copy
- ::memcpy(dest,src,sizeof(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 );
+ // 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 );
+ 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 );
+ 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 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 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);
+ }
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() );
+ aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() );
- dest->Clear();
- delete[] dest->mProperties;
+ dest->Clear();
+ delete[] dest->mProperties;
- dest->mNumAllocated = src->mNumAllocated;
- dest->mNumProperties = src->mNumProperties;
- dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated];
+ 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];
+ 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->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;
- }
+ prop->mIndex = sprop->mIndex;
+ prop->mSemantic = sprop->mSemantic;
+ prop->mKey = sprop->mKey;
+ prop->mType = sprop->mType;
+ }
}
-
+
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src)
{
- ai_assert(NULL != _dest && NULL != src);
-
- 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);
- }
+ ai_assert(NULL != _dest && NULL != src);
+
+ 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)
+void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src )
{
- ai_assert(NULL != _dest && NULL != src);
-
- aiAnimation* dest = *_dest = new aiAnimation();
+ ai_assert( NULL != _dest );
+ ai_assert( NULL != src );
+
+ aiAnimation* dest = *_dest = new aiAnimation();
- // get a flat copy
- ::memcpy(dest,src,sizeof(aiAnimation));
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiAnimation));
- // and reallocate all arrays
- CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
+ // and reallocate all arrays
+ CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiNodeAnim* dest = *_dest = new aiNodeAnim();
+ aiNodeAnim* dest = *_dest = new aiNodeAnim();
- // get a flat copy
- ::memcpy(dest,src,sizeof(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 );
+ // and reallocate all arrays
+ GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
+ GetArrayCopy( dest->mScalingKeys, dest->mNumScalingKeys );
+ GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiCamera* dest = *_dest = new aiCamera();
+ aiCamera* dest = *_dest = new aiCamera();
- // get a flat copy, that's already OK
- ::memcpy(dest,src,sizeof(aiCamera));
+ // get a flat copy, that's already OK
+ ::memcpy(dest,src,sizeof(aiCamera));
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiLight** _dest, const aiLight* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiLight* dest = *_dest = new aiLight();
+ aiLight* dest = *_dest = new aiLight();
- // get a flat copy, that's already OK
- ::memcpy(dest,src,sizeof(aiLight));
+ // get a flat copy, that's already OK
+ ::memcpy(dest,src,sizeof(aiLight));
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiBone** _dest, const aiBone* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
- aiBone* dest = *_dest = new aiBone();
+ aiBone* dest = *_dest = new aiBone();
- // get a flat copy
- ::memcpy(dest,src,sizeof(aiBone));
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(aiBone));
- // and reallocate all arrays
- GetArrayCopy( dest->mWeights, dest->mNumWeights );
+ // and reallocate all arrays
+ GetArrayCopy( dest->mWeights, dest->mNumWeights );
}
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
{
- ai_assert(NULL != _dest && NULL != src);
+ ai_assert(NULL != _dest && NULL != src);
+
+ aiNode* dest = *_dest = new aiNode();
- aiNode* dest = *_dest = new aiNode();
+ // get a flat copy
+ ::memcpy(dest,src,sizeof(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);
+ // 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)
+{
+ ai_assert(NULL != _dest && NULL != src);
+
+ aiMetadata* dest = *_dest = new aiMetadata();
+ dest->mNumProperties = src->mNumProperties;
+ dest->mKeys = new aiString[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_INT:
+ out.mData = new int(*static_cast<int*>(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_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);
+ }
+ }
+}
}
diff --git a/src/3rdparty/assimp/code/SceneCombiner.h b/src/3rdparty/assimp/code/SceneCombiner.h
index 3bcc478e4..81e58aaf3 100644
--- a/src/3rdparty/assimp/code/SceneCombiner.h
+++ b/src/3rdparty/assimp/code/SceneCombiner.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,9 +44,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_SCENE_COMBINER_H_INC
#define AI_SCENE_COMBINER_H_INC
-#include "../include/assimp/ai_assert.h"
-
-namespace Assimp {
+#include <assimp/ai_assert.h>
+#include <assimp/types.h>
+#include "Defines.h"
+#include <stddef.h>
+#include <set>
+#include <list>
+#include <stdint.h>
+
+#include <vector>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiTexture;
+struct aiCamera;
+struct aiLight;
+struct aiMetadata;
+struct aiBone;
+struct aiMesh;
+struct aiAnimation;
+struct aiNodeAnim;
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** \brief Helper data structure for SceneCombiner.
@@ -55,41 +75,41 @@ namespace Assimp {
*/
struct AttachmentInfo
{
- AttachmentInfo()
- : scene (NULL)
- , attachToNode (NULL)
- {}
-
- AttachmentInfo(aiScene* _scene, aiNode* _attachToNode)
- : scene (_scene)
- , attachToNode (_attachToNode)
- {}
-
- aiScene* scene;
- aiNode* attachToNode;
+ AttachmentInfo()
+ : scene (NULL)
+ , attachToNode (NULL)
+ {}
+
+ AttachmentInfo(aiScene* _scene, aiNode* _attachToNode)
+ : scene (_scene)
+ , attachToNode (_attachToNode)
+ {}
+
+ aiScene* scene;
+ aiNode* attachToNode;
};
// ---------------------------------------------------------------------------
struct NodeAttachmentInfo
{
- NodeAttachmentInfo()
- : node (NULL)
- , attachToNode (NULL)
- , resolved (false)
- , src_idx (SIZE_MAX)
- {}
-
- NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx)
- : node (_scene)
- , attachToNode (_attachToNode)
- , resolved (false)
- , src_idx (idx)
- {}
-
- aiNode* node;
- aiNode* attachToNode;
- bool resolved;
- size_t src_idx;
+ NodeAttachmentInfo()
+ : node (NULL)
+ , attachToNode (NULL)
+ , resolved (false)
+ , src_idx (SIZE_MAX)
+ {}
+
+ NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx)
+ : node (_scene)
+ , attachToNode (_attachToNode)
+ , resolved (false)
+ , src_idx (idx)
+ {}
+
+ aiNode* node;
+ aiNode* attachToNode;
+ bool resolved;
+ size_t src_idx;
};
// ---------------------------------------------------------------------------
@@ -99,7 +119,7 @@ struct NodeAttachmentInfo
#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1
/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES
- * Generate unique names for materials, too.
+ * Generate unique names for materials, too.
* This is not absolutely required to pass the validation.
*/
#define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2
@@ -128,8 +148,8 @@ typedef std::pair<aiBone*,unsigned int> BoneSrcIndex;
// ---------------------------------------------------------------------------
/** @brief Helper data structure for SceneCombiner::MergeBones.
*/
-struct BoneWithHash : public std::pair<uint32_t,aiString*> {
- std::vector<BoneSrcIndex> pSrcBones;
+struct BoneWithHash : public std::pair<uint32_t,aiString*> {
+ std::vector<BoneSrcIndex> pSrcBones;
};
@@ -138,240 +158,241 @@ struct BoneWithHash : public std::pair<uint32_t,aiString*> {
*/
struct SceneHelper
{
- SceneHelper ()
- : scene (NULL)
- , idlen (0)
- {
- id[0] = 0;
- }
-
- SceneHelper (aiScene* _scene)
- : scene (_scene)
- , idlen (0)
- {
- id[0] = 0;
- }
-
- AI_FORCE_INLINE aiScene* operator-> () const
- {
- return scene;
- }
-
- // scene we're working on
- aiScene* scene;
-
- // prefix to be added to all identifiers in the scene ...
- char id [32];
-
- // and its strlen()
- unsigned int idlen;
-
- // hash table to quickly check whether a name is contained in the scene
- std::set<unsigned int> hashes;
+ SceneHelper ()
+ : scene (NULL)
+ , idlen (0)
+ {
+ id[0] = 0;
+ }
+
+ explicit SceneHelper (aiScene* _scene)
+ : scene (_scene)
+ , idlen (0)
+ {
+ id[0] = 0;
+ }
+
+ AI_FORCE_INLINE aiScene* operator-> () const
+ {
+ return scene;
+ }
+
+ // scene we're working on
+ aiScene* scene;
+
+ // prefix to be added to all identifiers in the scene ...
+ char id [32];
+
+ // and its strlen()
+ unsigned int idlen;
+
+ // hash table to quickly check whether a name is contained in the scene
+ std::set<unsigned int> hashes;
};
// ---------------------------------------------------------------------------
/** \brief Static helper class providing various utilities to merge two
- * scenes. It is intended as internal utility and NOT for use by
+ * scenes. It is intended as internal utility and NOT for use by
* applications.
- *
+ *
* The class is currently being used by various postprocessing steps
* and loaders (ie. LWS).
*/
class SceneCombiner
{
- // class cannot be instanced
- SceneCombiner() {}
+ // class cannot be instanced
+ SceneCombiner() {}
public:
- // -------------------------------------------------------------------
- /** Merges two or more scenes.
- *
- * @param dest Receives a pointer to the destination scene. If the
- * pointer doesn't point to NULL when the function is called, the
- * existing scene is cleared and refilled.
- * @param src Non-empty list of scenes to be merged. The function
- * deletes the input scenes afterwards. There may be duplicate scenes.
- * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
- */
- static void MergeScenes(aiScene** dest,std::vector<aiScene*>& src,
- unsigned int flags = 0);
-
-
- // -------------------------------------------------------------------
- /** Merges two or more scenes and attaches all sceenes to a specific
- * position in the node graph of the masteer scene.
- *
- * @param dest Receives a pointer to the destination scene. If the
- * pointer doesn't point to NULL when the function is called, the
- * existing scene is cleared and refilled.
- * @param master Master scene. It will be deleted afterwards. All
- * other scenes will be inserted in its node graph.
- * @param src Non-empty list of scenes to be merged along with their
- * corresponding attachment points in the master scene. The function
- * deletes the input scenes afterwards. There may be duplicate scenes.
- * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
- */
- static void MergeScenes(aiScene** dest, aiScene* master,
- std::vector<AttachmentInfo>& src,
- unsigned int flags = 0);
-
-
- // -------------------------------------------------------------------
- /** Merges two or more meshes
- *
- * The meshes should have equal vertex formats. Only components
- * that are provided by ALL meshes will be present in the output mesh.
- * An exception is made for VColors - they are set to black. The
- * meshes should have the same material indices, too. The output
- * material index is always the material index of the first mesh.
- *
- * @param dest Destination mesh. Must be empty.
- * @param flags Currently no parameters
- * @param begin First mesh to be processed
- * @param end Points to the mesh after the last mesh to be processed
- */
- static void MergeMeshes(aiMesh** dest,unsigned int flags,
- std::vector<aiMesh*>::const_iterator begin,
- std::vector<aiMesh*>::const_iterator end);
-
-
- // -------------------------------------------------------------------
- /** Merges two or more bones
- *
- * @param out Mesh to receive the output bone list
- * @param flags Currently no parameters
- * @param begin First mesh to be processed
- * @param end Points to the mesh after the last mesh to be processed
- */
- static void MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
- std::vector<aiMesh*>::const_iterator end);
-
- // -------------------------------------------------------------------
- /** Merges two or more materials
- *
- * The materials should be complementary as much as possible. In case
- * of a property present in different materials, the first occurence
- * is used.
- *
- * @param dest Destination material. Must be empty.
- * @param begin First material to be processed
- * @param end Points to the material after the last material to be processed
- */
- static void MergeMaterials(aiMaterial** dest,
- std::vector<aiMaterial*>::const_iterator begin,
- std::vector<aiMaterial*>::const_iterator end);
-
- // -------------------------------------------------------------------
- /** Builds a list of uniquely named bones in a mesh list
- *
- * @param asBones Receives the output list
- * @param it First mesh to be processed
- * @param end Last mesh to be processed
- */
- static void BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
- std::vector<aiMesh*>::const_iterator it,
- std::vector<aiMesh*>::const_iterator end);
-
- // -------------------------------------------------------------------
- /** Add a name prefix to all nodes in a scene.
- *
- * @param Current node. This function is called recursively.
- * @param prefix Prefix to be added to all nodes
- * @param len STring length
- */
- static void AddNodePrefixes(aiNode* node, const char* prefix,
- unsigned int len);
-
- // -------------------------------------------------------------------
- /** Add an offset to all mesh indices in a node graph
- *
- * @param Current node. This function is called recursively.
- * @param offset Offset to be added to all mesh indices
- */
- static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset);
-
- // -------------------------------------------------------------------
- /** Attach a list of node graphs to well-defined nodes in a master
- * graph. This is a helper for MergeScenes()
- *
- * @param master Master scene
- * @param srcList List of source scenes along with their attachment
- * points. If an attachment point is NULL (or does not exist in
- * the master graph), a scene is attached to the root of the master
- * graph (as an additional child node)
- * @duplicates List of duplicates. If elem[n] == n the scene is not
- * a duplicate. Otherwise elem[n] links scene n to its first occurence.
- */
- static void AttachToGraph ( aiScene* master,
- std::vector<NodeAttachmentInfo>& srcList);
-
- static void AttachToGraph (aiNode* attach,
- std::vector<NodeAttachmentInfo>& srcList);
-
-
- // -------------------------------------------------------------------
- /** Get a deep copy of a scene
- *
- * @param dest Receives a pointer to the destination scene
- * @param src Source scene - remains unmodified.
- */
- static void CopyScene(aiScene** dest,const aiScene* source,bool allocate = true);
-
-
- // -------------------------------------------------------------------
- /** Get a flat copy of a scene
- *
- * Only the first hierarchy layer is copied. All pointer members of
- * aiScene are shared by source and destination scene. If the
- * pointer doesn't point to NULL when the function is called, the
- * existing scene is cleared and refilled.
- * @param dest Receives a pointer to the destination scene
- * @param src Source scene - remains unmodified.
- */
- static void CopySceneFlat(aiScene** dest,const aiScene* source);
-
-
- // -------------------------------------------------------------------
- /** Get a deep copy of a mesh
- *
- * @param dest Receives a pointer to the destination mesh
- * @param src Source mesh - remains unmodified.
- */
- static void Copy (aiMesh** dest, const aiMesh* src);
-
- // similar to Copy():
- static void Copy (aiMaterial** dest, const aiMaterial* src);
- static void Copy (aiTexture** dest, const aiTexture* src);
- static void Copy (aiAnimation** dest, const aiAnimation* src);
- static void Copy (aiCamera** dest, const aiCamera* src);
- static void Copy (aiBone** dest, const aiBone* src);
- static void Copy (aiLight** dest, const aiLight* src);
- static void Copy (aiNodeAnim** dest, const aiNodeAnim* src);
-
- // recursive, of course
- static void Copy (aiNode** dest, const aiNode* src);
+ // -------------------------------------------------------------------
+ /** Merges two or more scenes.
+ *
+ * @param dest Receives a pointer to the destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param src Non-empty list of scenes to be merged. The function
+ * deletes the input scenes afterwards. There may be duplicate scenes.
+ * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
+ */
+ static void MergeScenes(aiScene** dest,std::vector<aiScene*>& src,
+ unsigned int flags = 0);
+
+
+ // -------------------------------------------------------------------
+ /** Merges two or more scenes and attaches all sceenes to a specific
+ * position in the node graph of the masteer scene.
+ *
+ * @param dest Receives a pointer to the destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param master Master scene. It will be deleted afterwards. All
+ * other scenes will be inserted in its node graph.
+ * @param src Non-empty list of scenes to be merged along with their
+ * corresponding attachment points in the master scene. The function
+ * deletes the input scenes afterwards. There may be duplicate scenes.
+ * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above
+ */
+ static void MergeScenes(aiScene** dest, aiScene* master,
+ std::vector<AttachmentInfo>& src,
+ unsigned int flags = 0);
+
+
+ // -------------------------------------------------------------------
+ /** Merges two or more meshes
+ *
+ * The meshes should have equal vertex formats. Only components
+ * that are provided by ALL meshes will be present in the output mesh.
+ * An exception is made for VColors - they are set to black. The
+ * meshes should have the same material indices, too. The output
+ * material index is always the material index of the first mesh.
+ *
+ * @param dest Destination mesh. Must be empty.
+ * @param flags Currently no parameters
+ * @param begin First mesh to be processed
+ * @param end Points to the mesh after the last mesh to be processed
+ */
+ static void MergeMeshes(aiMesh** dest,unsigned int flags,
+ std::vector<aiMesh*>::const_iterator begin,
+ std::vector<aiMesh*>::const_iterator end);
+
+
+ // -------------------------------------------------------------------
+ /** Merges two or more bones
+ *
+ * @param out Mesh to receive the output bone list
+ * @param flags Currently no parameters
+ * @param begin First mesh to be processed
+ * @param end Points to the mesh after the last mesh to be processed
+ */
+ static void MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Merges two or more materials
+ *
+ * The materials should be complementary as much as possible. In case
+ * of a property present in different materials, the first occurrence
+ * is used.
+ *
+ * @param dest Destination material. Must be empty.
+ * @param begin First material to be processed
+ * @param end Points to the material after the last material to be processed
+ */
+ static void MergeMaterials(aiMaterial** dest,
+ std::vector<aiMaterial*>::const_iterator begin,
+ std::vector<aiMaterial*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Builds a list of uniquely named bones in a mesh list
+ *
+ * @param asBones Receives the output list
+ * @param it First mesh to be processed
+ * @param end Last mesh to be processed
+ */
+ static void BuildUniqueBoneList(std::list<BoneWithHash>& asBones,
+ std::vector<aiMesh*>::const_iterator it,
+ std::vector<aiMesh*>::const_iterator end);
+
+ // -------------------------------------------------------------------
+ /** Add a name prefix to all nodes in a scene.
+ *
+ * @param Current node. This function is called recursively.
+ * @param prefix Prefix to be added to all nodes
+ * @param len STring length
+ */
+ static void AddNodePrefixes(aiNode* node, const char* prefix,
+ unsigned int len);
+
+ // -------------------------------------------------------------------
+ /** Add an offset to all mesh indices in a node graph
+ *
+ * @param Current node. This function is called recursively.
+ * @param offset Offset to be added to all mesh indices
+ */
+ static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset);
+
+ // -------------------------------------------------------------------
+ /** Attach a list of node graphs to well-defined nodes in a master
+ * graph. This is a helper for MergeScenes()
+ *
+ * @param master Master scene
+ * @param srcList List of source scenes along with their attachment
+ * points. If an attachment point is NULL (or does not exist in
+ * the master graph), a scene is attached to the root of the master
+ * graph (as an additional child node)
+ * @duplicates List of duplicates. If elem[n] == n the scene is not
+ * a duplicate. Otherwise elem[n] links scene n to its first occurrence.
+ */
+ static void AttachToGraph ( aiScene* master,
+ std::vector<NodeAttachmentInfo>& srcList);
+
+ static void AttachToGraph (aiNode* attach,
+ std::vector<NodeAttachmentInfo>& srcList);
+
+
+ // -------------------------------------------------------------------
+ /** Get a deep copy of a scene
+ *
+ * @param dest Receives a pointer to the destination scene
+ * @param src Source scene - remains unmodified.
+ */
+ static void CopyScene(aiScene** dest,const aiScene* source,bool allocate = true);
+
+
+ // -------------------------------------------------------------------
+ /** Get a flat copy of a scene
+ *
+ * Only the first hierarchy layer is copied. All pointer members of
+ * aiScene are shared by source and destination scene. If the
+ * pointer doesn't point to NULL when the function is called, the
+ * existing scene is cleared and refilled.
+ * @param dest Receives a pointer to the destination scene
+ * @param src Source scene - remains unmodified.
+ */
+ static void CopySceneFlat(aiScene** dest,const aiScene* source);
+
+
+ // -------------------------------------------------------------------
+ /** Get a deep copy of a mesh
+ *
+ * @param dest Receives a pointer to the destination mesh
+ * @param src Source mesh - remains unmodified.
+ */
+ static void Copy (aiMesh** dest, const aiMesh* src);
+
+ // similar to Copy():
+ static void Copy (aiMaterial** dest, const aiMaterial* src);
+ static void Copy (aiTexture** dest, const aiTexture* src);
+ static void Copy (aiAnimation** dest, const aiAnimation* src);
+ static void Copy (aiCamera** dest, const aiCamera* src);
+ static void Copy (aiBone** dest, const aiBone* src);
+ static void Copy (aiLight** dest, const aiLight* src);
+ static void Copy (aiNodeAnim** dest, const aiNodeAnim* src);
+ static void Copy (aiMetadata** dest, const aiMetadata* src);
+
+ // recursive, of course
+ static void Copy (aiNode** dest, const aiNode* src);
private:
- // -------------------------------------------------------------------
- // Same as AddNodePrefixes, but with an additional check
- static void AddNodePrefixesChecked(aiNode* node, const char* prefix,
- unsigned int len,
- std::vector<SceneHelper>& input,
- unsigned int cur);
+ // -------------------------------------------------------------------
+ // Same as AddNodePrefixes, but with an additional check
+ static void AddNodePrefixesChecked(aiNode* node, const char* prefix,
+ unsigned int len,
+ std::vector<SceneHelper>& input,
+ unsigned int cur);
- // -------------------------------------------------------------------
- // Add node identifiers to a hashing set
- static void AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes);
+ // -------------------------------------------------------------------
+ // Add node identifiers to a hashing set
+ static void AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes);
- // -------------------------------------------------------------------
- // Search for duplicate names
- static bool FindNameMatch(const aiString& name,
- std::vector<SceneHelper>& input, unsigned int cur);
+ // -------------------------------------------------------------------
+ // Search for duplicate names
+ static bool FindNameMatch(const aiString& name,
+ std::vector<SceneHelper>& input, unsigned int cur);
};
}
diff --git a/src/3rdparty/assimp/code/ScenePreprocessor.cpp b/src/3rdparty/assimp/code/ScenePreprocessor.cpp
index 4e3ff973c..a38a9430e 100644
--- a/src/3rdparty/assimp/code/ScenePreprocessor.cpp
+++ b/src/3rdparty/assimp/code/ScenePreprocessor.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,236 +23,237 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
#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);
+ ai_assert(scene != NULL);
- // Process all meshes
- for (unsigned int i = 0; i < scene->mNumMeshes;++i)
- ProcessMesh(scene->mMeshes[i]);
+ // 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
+ // - 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]);
+ // 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;
+ // Generate a default material if none was specified
+ if (!scene->mNumMaterials && scene->mNumMeshes) {
+ scene->mMaterials = new aiMaterial*[2];
+ aiMaterial* helper;
- aiString name;
+ 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);
+ 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);
+ // setup the default name to make this material identifiable
+ name.Set(AI_DEFAULT_MATERIAL_NAME);
+ helper->AddProperty(&name,AI_MATKEY_NAME);
- DefaultLogger::get()->debug("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
+ DefaultLogger::get()->debug("ScenePreprocessor: Adding default material \'" AI_DEFAULT_MATERIAL_NAME "\'");
- for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
- scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
- }
+ for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+ scene->mMeshes[i]->mMaterialIndex = scene->mNumMaterials;
+ }
- 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 unsued 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) {
- DefaultLogger::get()->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];
- }
- }
+ // 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 unsued 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) {
+ DefaultLogger::get()->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 i = 0; i < channel->mNumPositionKeys;++i) {
- aiVectorKey& key = channel->mPositionKeys[i];
- first = std::min (first, key.mTime);
- last = std::max (last, key.mTime);
- }
-
- // Scaling keys
- for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) {
- aiVectorKey& key = channel->mScalingKeys[i];
- first = std::min (first, key.mTime);
- last = std::max (last, key.mTime);
- }
-
- // Rotation keys
- for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) {
- aiQuatKey& key = channel->mRotationKeys[i];
- 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;
-
- DefaultLogger::get()->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;
-
- DefaultLogger::get()->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;
-
- DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated");
- }
- }
- }
- }
-
- if (anim->mDuration == -1.) {
- DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration");
- anim->mDuration = last - std::min( first, 0. );
- }
+ 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 i = 0; i < channel->mNumPositionKeys;++i) {
+ aiVectorKey& key = channel->mPositionKeys[i];
+ first = std::min (first, key.mTime);
+ last = std::max (last, key.mTime);
+ }
+
+ // Scaling keys
+ for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) {
+ aiVectorKey& key = channel->mScalingKeys[i];
+ first = std::min (first, key.mTime);
+ last = std::max (last, key.mTime);
+ }
+
+ // Rotation keys
+ for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) {
+ aiQuatKey& key = channel->mRotationKeys[i];
+ 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;
+
+ DefaultLogger::get()->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;
+
+ DefaultLogger::get()->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;
+
+ DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated");
+ }
+ }
+ }
+ }
+
+ if (anim->mDuration == -1.) {
+ DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration");
+ anim->mDuration = last - std::min( first, 0. );
+ }
}
diff --git a/src/3rdparty/assimp/code/ScenePreprocessor.h b/src/3rdparty/assimp/code/ScenePreprocessor.h
index cfa0892be..9c4b422a2 100644
--- a/src/3rdparty/assimp/code/ScenePreprocessor.h
+++ b/src/3rdparty/assimp/code/ScenePreprocessor.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,8 +43,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 {
+namespace Assimp {
// ----------------------------------------------------------------------------------
/** ScenePreprocessor: Preprocess a scene before any post-processing
@@ -56,58 +63,58 @@ namespace Assimp {
// ----------------------------------------------------------------------------------
class ASSIMP_API ScenePreprocessor
{
- // Make ourselves a friend of the corresponding test unit.
- friend class ::ScenePreprocessorTest;
+ // 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 ();
+ // ----------------------------------------------------------------
+ /** 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);
+ // ----------------------------------------------------------------
+ /** 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;
+ //! Scene we're currently working on
+ aiScene* scene;
};
diff --git a/src/3rdparty/assimp/code/ScenePrivate.h b/src/3rdparty/assimp/code/ScenePrivate.h
index af1966457..dd4d0a5e1 100644
--- a/src/3rdparty/assimp/code/ScenePrivate.h
+++ b/src/3rdparty/assimp/code/ScenePrivate.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,41 +43,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_SCENEPRIVATE_H_INCLUDED
#define AI_SCENEPRIVATE_H_INCLUDED
+#include <assimp/scene.h>
-namespace Assimp {
+namespace Assimp {
- class Importer;
+class Importer;
struct ScenePrivateData {
-
- ScenePrivateData()
- : mOrigImporter()
- , mPPStepsApplied()
- , mIsCopy()
- {}
-
- // 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 postprocessing 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;
+
+ ScenePrivateData()
+ : mOrigImporter()
+ , mPPStepsApplied()
+ , mIsCopy()
+ {}
+
+ // 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;
};
// Access private data stored in the scene
inline ScenePrivateData* ScenePriv(aiScene* in) {
- return static_cast<ScenePrivateData*>(in->mPrivate);
+ return static_cast<ScenePrivateData*>(in->mPrivate);
}
inline const ScenePrivateData* ScenePriv(const aiScene* in) {
- return static_cast<const ScenePrivateData*>(in->mPrivate);
+ return static_cast<const ScenePrivateData*>(in->mPrivate);
}
}
diff --git a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
index 7e0d68a9f..ec7aa8985 100644
--- a/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
+++ b/src/3rdparty/assimp/code/SkeletonMeshBuilder.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,245 +23,246 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file SkeletonMeshBuilder.cpp
- * @brief Implementation of a little class to construct a dummy mesh for a skeleton
+ * @brief Implementation of a little class to construct a dummy mesh for a skeleton
*/
-#include "AssimpPCH.h"
-#include "../include/assimp/scene.h"
+#include <assimp/scene.h>
#include "SkeletonMeshBuilder.h"
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
-// The constructor processes the given scene and adds a mesh there.
+// 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
- pScene->mNumMaterials = 1;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = CreateMaterial();
+ // 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
+// 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 = 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);
- float distanceToChild = childpos.Length();
- if( distanceToChild < 0.0001f)
- continue;
- aiVector3D up = aiVector3D( childpos).Normalize();
-
- aiVector3D orth( 1.0f, 0.0f, 0.0f);
- if( std::fabs( orth * up) > 0.99f)
- orth.Set( 0.0f, 1.0f, 0.0f);
-
- aiVector3D front = (up ^ orth).Normalize();
- aiVector3D side = (front ^ up).Normalize();
-
- unsigned int localVertexStart = mVertices.size();
- mVertices.push_back( -front * distanceToChild * 0.1f);
- mVertices.push_back( childpos);
- mVertices.push_back( -side * distanceToChild * 0.1f);
- mVertices.push_back( -side * distanceToChild * 0.1f);
- mVertices.push_back( childpos);
- mVertices.push_back( front * distanceToChild * 0.1f);
- mVertices.push_back( front * distanceToChild * 0.1f);
- mVertices.push_back( childpos);
- mVertices.push_back( side * distanceToChild * 0.1f);
- mVertices.push_back( side * distanceToChild * 0.1f);
- mVertices.push_back( childpos);
- mVertices.push_back( -front * distanceToChild * 0.1f);
-
- 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);
- float sizeEstimate = ownpos.Length() * 0.18f;
-
- mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
- mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
- mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
- mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
-
- mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
- mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
- mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
- mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
- mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
- mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
-
- 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 = 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.0f);
-
- // 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]);
+ // add a joint entry for the node.
+ const unsigned int vertexStartIndex = 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);
+ float distanceToChild = childpos.Length();
+ if( distanceToChild < 0.0001f)
+ continue;
+ aiVector3D up = aiVector3D( childpos).Normalize();
+
+ aiVector3D orth( 1.0f, 0.0f, 0.0f);
+ if( std::fabs( orth * up) > 0.99f)
+ orth.Set( 0.0f, 1.0f, 0.0f);
+
+ aiVector3D front = (up ^ orth).Normalize();
+ aiVector3D side = (front ^ up).Normalize();
+
+ unsigned int localVertexStart = mVertices.size();
+ mVertices.push_back( -front * distanceToChild * 0.1f);
+ mVertices.push_back( childpos);
+ mVertices.push_back( -side * distanceToChild * 0.1f);
+ mVertices.push_back( -side * distanceToChild * 0.1f);
+ mVertices.push_back( childpos);
+ mVertices.push_back( front * distanceToChild * 0.1f);
+ mVertices.push_back( front * distanceToChild * 0.1f);
+ mVertices.push_back( childpos);
+ mVertices.push_back( side * distanceToChild * 0.1f);
+ mVertices.push_back( side * distanceToChild * 0.1f);
+ mVertices.push_back( childpos);
+ mVertices.push_back( -front * distanceToChild * 0.1f);
+
+ 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);
+ float sizeEstimate = ownpos.Length() * 0.18f;
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
+
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
+ mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
+ mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
+ mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
+
+ 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 = 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.0f);
+
+ // 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 = 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 = 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-5f) /* ensure that FindInvalidData won't remove us ...*/
- nor = aiVector3D(1.f,0.f,0.f);
-
- for (unsigned int n = 0; n < 3; ++n)
- mesh->mNormals[inface.mIndices[n]] = nor;
- }
-
- // add the bones
- mesh->mNumBones = mBones.size();
- mesh->mBones = new aiBone*[mesh->mNumBones];
- std::copy( mBones.begin(), mBones.end(), mesh->mBones);
-
- // default
- mesh->mMaterialIndex = 0;
-
- return mesh;
+ aiMesh* mesh = new aiMesh();
+
+ // add points
+ mesh->mNumVertices = 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 = 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-5f) /* ensure that FindInvalidData won't remove us ...*/
+ nor = aiVector3D(1.f,0.f,0.f);
+
+ for (unsigned int n = 0; n < 3; ++n)
+ mesh->mNormals[inface.mIndices[n]] = nor;
+ }
+
+ // add the bones
+ mesh->mNumBones = 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;
+ aiMaterial* matHelper = new aiMaterial;
- // Name
- aiString matName( std::string( "SkeletonMaterial"));
- matHelper->AddProperty( &matName, AI_MATKEY_NAME);
+ // 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);
+ // Prevent backface culling
+ const int no_cull = 1;
+ matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
- return matHelper;
+ return matHelper;
}
diff --git a/src/3rdparty/assimp/code/SkeletonMeshBuilder.h b/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
index aa0fbc054..3c518e8cd 100644
--- a/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
+++ b/src/3rdparty/assimp/code/SkeletonMeshBuilder.h
@@ -4,11 +4,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,15 +49,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_SKELETONMESHBUILDER_H_INC
#include <vector>
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
+struct aiMaterial;
struct aiScene;
struct aiNode;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
-/**
+/**
* This little helper class constructs a dummy mesh for a given scene
* the resembles the node hierarchy. This is useful for file formats
* that don't carry any mesh data but only animation data.
@@ -66,55 +67,55 @@ class SkeletonMeshBuilder
{
public:
- // -------------------------------------------------------------------
- /** The constructor processes the given scene and adds a mesh there.
- *
- * Does nothing if the scene already has mesh data.
- * @param pScene The scene for which a skeleton mesh should be constructed.
- * @param root The node to start with. NULL is the scene root
- * @param bKnobsOnly Set this to true if you don't want the connectors
- * between the knobs representing the nodes.
- */
- SkeletonMeshBuilder( aiScene* pScene, aiNode* root = NULL,
- bool bKnobsOnly = false);
+ // -------------------------------------------------------------------
+ /** The constructor processes the given scene and adds a mesh there.
+ *
+ * Does nothing if the scene already has mesh data.
+ * @param pScene The scene for which a skeleton mesh should be constructed.
+ * @param root The node to start with. NULL is the scene root
+ * @param bKnobsOnly Set this to true if you don't want the connectors
+ * between the knobs representing the nodes.
+ */
+ SkeletonMeshBuilder( aiScene* pScene, aiNode* root = NULL,
+ bool bKnobsOnly = false);
protected:
- // -------------------------------------------------------------------
- /** Recursively builds a simple mesh representation for the given node
- * and also creates a joint for the node that affects this part of
- * the mesh.
- * @param pNode The node to build geometry for.
- */
- void CreateGeometry( const aiNode* pNode);
+ // -------------------------------------------------------------------
+ /** Recursively builds a simple mesh representation for the given node
+ * and also creates a joint for the node that affects this part of
+ * the mesh.
+ * @param pNode The node to build geometry for.
+ */
+ void CreateGeometry( const aiNode* pNode);
- // -------------------------------------------------------------------
- /** Creates the mesh from the internally accumulated stuff and returns it.
- */
- aiMesh* CreateMesh();
+ // -------------------------------------------------------------------
+ /** Creates the mesh from the internally accumulated stuff and returns it.
+ */
+ aiMesh* CreateMesh();
- // -------------------------------------------------------------------
- /** Creates a dummy material and returns it. */
- aiMaterial* CreateMaterial();
+ // -------------------------------------------------------------------
+ /** Creates a dummy material and returns it. */
+ aiMaterial* CreateMaterial();
protected:
- /** space to assemble the mesh data: points */
- std::vector<aiVector3D> mVertices;
-
- /** faces */
- struct Face
- {
- unsigned int mIndices[3];
- Face();
- Face( unsigned int p0, unsigned int p1, unsigned int p2)
- { mIndices[0] = p0; mIndices[1] = p1; mIndices[2] = p2; }
- };
- std::vector<Face> mFaces;
-
- /** bones */
- std::vector<aiBone*> mBones;
-
- bool mKnobsOnly;
+ /** space to assemble the mesh data: points */
+ std::vector<aiVector3D> mVertices;
+
+ /** faces */
+ struct Face
+ {
+ unsigned int mIndices[3];
+ Face();
+ Face( unsigned int p0, unsigned int p1, unsigned int p2)
+ { mIndices[0] = p0; mIndices[1] = p1; mIndices[2] = p2; }
+ };
+ std::vector<Face> mFaces;
+
+ /** bones */
+ std::vector<aiBone*> mBones;
+
+ bool mKnobsOnly;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/SmoothingGroups.h b/src/3rdparty/assimp/code/SmoothingGroups.h
index 19ecee6df..75c59d1cb 100644
--- a/src/3rdparty/assimp/code/SmoothingGroups.h
+++ b/src/3rdparty/assimp/code/SmoothingGroups.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,50 +44,55 @@ http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
#ifndef AI_SMOOTHINGGROUPS_H_INC
#define AI_SMOOTHINGGROUPS_H_INC
+#include <assimp/vector3.h>
+#include <stdint.h>
+#include <vector>
+
// ---------------------------------------------------------------------------
/** Helper structure representing a face with smoothing groups assigned */
struct FaceWithSmoothingGroup
{
- FaceWithSmoothingGroup() : iSmoothGroup(0)
- {
- // let the rest uninitialized for performance - in release builds.
- // in debug builds set all indices to a common magic value
+ FaceWithSmoothingGroup()
+ : mIndices(),
+ iSmoothGroup(0)
+ {
+ // in debug builds set all indices to a common magic value
#ifdef ASSIMP_BUILD_DEBUG
- this->mIndices[0] = 0xffffffff;
- this->mIndices[1] = 0xffffffff;
- this->mIndices[2] = 0xffffffff;
+ this->mIndices[0] = 0xffffffff;
+ this->mIndices[1] = 0xffffffff;
+ this->mIndices[2] = 0xffffffff;
#endif
- }
+ }
+
-
- //! Indices. .3ds is using uint16. However, after
- //! an unique vrtex set has been generated,
- //! individual index values might exceed 2^16
- uint32_t mIndices[3];
+ //! Indices. .3ds is using uint16. However, after
+ //! an unique vertex set has been generated,
+ //! individual index values might exceed 2^16
+ uint32_t mIndices[3];
- //! specifies to which smoothing group the face belongs to
- uint32_t iSmoothGroup;
+ //! specifies to which smoothing group the face belongs to
+ uint32_t iSmoothGroup;
};
// ---------------------------------------------------------------------------
/** Helper structure representing a mesh whose faces have smoothing
- groups assigned. This allows us to reuse the code for normal computations
- from smoothings groups for several loaders (3DS, ASE). All of them
- use face structures which inherit from #FaceWithSmoothingGroup,
- but as they add extra members and need to be copied by value we
- need to use a template here.
- */
+ groups assigned. This allows us to reuse the code for normal computations
+ from smoothings groups for several loaders (3DS, ASE). All of them
+ use face structures which inherit from #FaceWithSmoothingGroup,
+ but as they add extra members and need to be copied by value we
+ need to use a template here.
+ */
template <class T>
struct MeshWithSmoothingGroups
{
- //! Vertex positions
- std::vector<aiVector3D> mPositions;
+ //! Vertex positions
+ std::vector<aiVector3D> mPositions;
- //! Face lists
- std::vector<T> mFaces;
+ //! Face lists
+ std::vector<T> mFaces;
- //! List of normal vectors
- std::vector<aiVector3D> mNormals;
+ //! List of normal vectors
+ std::vector<aiVector3D> mNormals;
};
// ---------------------------------------------------------------------------
diff --git a/src/3rdparty/assimp/code/SmoothingGroups.inl b/src/3rdparty/assimp/code/SmoothingGroups.inl
index 156ebf72d..42c500070 100644
--- a/src/3rdparty/assimp/code/SmoothingGroups.inl
+++ b/src/3rdparty/assimp/code/SmoothingGroups.inl
@@ -56,83 +56,83 @@ using namespace Assimp;
template <class T>
void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
{
- // First generate face normals
- sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D());
- for( unsigned int a = 0; a < sMesh.mFaces.size(); a++)
- {
- T& face = sMesh.mFaces[a];
-
- aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]];
- aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]];
- aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]];
-
- aiVector3D pDelta1 = *pV2 - *pV1;
- aiVector3D pDelta2 = *pV3 - *pV1;
- aiVector3D vNor = pDelta1 ^ pDelta2;
-
- for (unsigned int c = 0; c < 3;++c)
- sMesh.mNormals[face.mIndices[c]] = vNor;
- }
-
- // calculate the position bounds so we have a reliable epsilon to check position differences against
- aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
- for( unsigned int a = 0; a < sMesh.mPositions.size(); a++)
- {
- minVec.x = std::min( minVec.x, sMesh.mPositions[a].x);
- minVec.y = std::min( minVec.y, sMesh.mPositions[a].y);
- minVec.z = std::min( minVec.z, sMesh.mPositions[a].z);
- maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x);
- maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y);
- maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z);
- }
- const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
- std::vector<aiVector3D> avNormals;
- avNormals.resize(sMesh.mNormals.size());
-
- // now generate the spatial sort tree
- SGSpatialSort sSort;
- for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
- i != sMesh.mFaces.end();++i)
- {
- for (unsigned int c = 0; c < 3;++c)
- sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup);
- }
- sSort.Prepare();
-
- std::vector<bool> vertexDone(sMesh.mPositions.size(),false);
- for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
- i != sMesh.mFaces.end();++i)
- {
- std::vector<unsigned int> poResult;
- for (unsigned int c = 0; c < 3;++c)
- {
- unsigned int idx = (*i).mIndices[c];
- if (vertexDone[idx])continue;
-
- sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup,
- posEpsilon,poResult);
-
- aiVector3D vNormals;
- for (std::vector<unsigned int>::const_iterator
- a = poResult.begin();
- a != poResult.end();++a)
- {
- vNormals += sMesh.mNormals[(*a)];
- }
- vNormals.Normalize();
-
- // write back into all affected normals
- for (std::vector<unsigned int>::const_iterator
- a = poResult.begin();
- a != poResult.end();++a)
- {
- idx = *a;
- avNormals [idx] = vNormals;
- vertexDone[idx] = true;
- }
- }
- }
- sMesh.mNormals = avNormals;
+ // First generate face normals
+ sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D());
+ for( unsigned int a = 0; a < sMesh.mFaces.size(); a++)
+ {
+ T& face = sMesh.mFaces[a];
+
+ aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]];
+ aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]];
+ aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]];
+
+ aiVector3D pDelta1 = *pV2 - *pV1;
+ aiVector3D pDelta2 = *pV3 - *pV1;
+ aiVector3D vNor = pDelta1 ^ pDelta2;
+
+ for (unsigned int c = 0; c < 3;++c)
+ sMesh.mNormals[face.mIndices[c]] = vNor;
+ }
+
+ // calculate the position bounds so we have a reliable epsilon to check position differences against
+ aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
+ for( unsigned int a = 0; a < sMesh.mPositions.size(); a++)
+ {
+ minVec.x = std::min( minVec.x, sMesh.mPositions[a].x);
+ minVec.y = std::min( minVec.y, sMesh.mPositions[a].y);
+ minVec.z = std::min( minVec.z, sMesh.mPositions[a].z);
+ maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x);
+ maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y);
+ maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z);
+ }
+ const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
+ std::vector<aiVector3D> avNormals;
+ avNormals.resize(sMesh.mNormals.size());
+
+ // now generate the spatial sort tree
+ SGSpatialSort sSort;
+ for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
+ i != sMesh.mFaces.end();++i)
+ {
+ for (unsigned int c = 0; c < 3;++c)
+ sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup);
+ }
+ sSort.Prepare();
+
+ std::vector<bool> vertexDone(sMesh.mPositions.size(),false);
+ for( typename std::vector<T>::iterator i = sMesh.mFaces.begin();
+ i != sMesh.mFaces.end();++i)
+ {
+ std::vector<unsigned int> poResult;
+ for (unsigned int c = 0; c < 3;++c)
+ {
+ unsigned int idx = (*i).mIndices[c];
+ if (vertexDone[idx])continue;
+
+ sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup,
+ posEpsilon,poResult);
+
+ aiVector3D vNormals;
+ for (std::vector<unsigned int>::const_iterator
+ a = poResult.begin();
+ a != poResult.end();++a)
+ {
+ vNormals += sMesh.mNormals[(*a)];
+ }
+ vNormals.NormalizeSafe();
+
+ // write back into all affected normals
+ for (std::vector<unsigned int>::const_iterator
+ a = poResult.begin();
+ a != poResult.end();++a)
+ {
+ idx = *a;
+ avNormals [idx] = vNormals;
+ vertexDone[idx] = true;
+ }
+ }
+ }
+ sMesh.mNormals = avNormals;
}
#endif // !! AI_SMOOTHINGGROUPS_INL_INCLUDED
diff --git a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
index 7165f4469..74867184a 100644
--- a/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
+++ b/src/3rdparty/assimp/code/SortByPTypeProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -43,11 +43,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* SortByPTypeProcess post-process steps.
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "ProcessHelper.h"
#include "SortByPTypeProcess.h"
+#include "Exceptional.h"
using namespace Assimp;
@@ -55,354 +56,354 @@ using namespace Assimp;
// Constructor to be privately used by Importer
SortByPTypeProcess::SortByPTypeProcess()
{
- configRemoveMeshes = 0;
+ configRemoveMeshes = 0;
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
SortByPTypeProcess::~SortByPTypeProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_SortByPType) != 0;
+ return (pFlags & aiProcess_SortByPType) != 0;
}
// ------------------------------------------------------------------------------------------------
void SortByPTypeProcess::SetupProperties(const Importer* pImp)
{
- configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
+ configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
}
// ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
{
-// std::vector<unsigned int>::const_iterator it;
-
- if (node->mNumMeshes)
- {
- unsigned int newSize = 0;
- for (unsigned int m = 0; m< node->mNumMeshes; ++m)
- {
- unsigned int add = node->mMeshes[m]<<2;
- for (unsigned int i = 0; i < 4;++i)
- {
- if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
- }
- }
- if (!newSize)
- {
- delete[] node->mMeshes;
- node->mNumMeshes = 0;
- node->mMeshes = NULL;
- }
- else
- {
- // Try to reuse the old array if possible
- unsigned int* newMeshes = (newSize > node->mNumMeshes
- ? new unsigned int[newSize] : node->mMeshes);
-
- for (unsigned int m = 0; m< node->mNumMeshes; ++m)
- {
- unsigned int add = node->mMeshes[m]<<2;
- for (unsigned int i = 0; i < 4;++i)
- {
- if (UINT_MAX != replaceMeshIndex[add+i])
- *newMeshes++ = replaceMeshIndex[add+i];
- }
- }
- if (newSize > node->mNumMeshes)
- delete[] node->mMeshes;
-
- node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
- }
- }
-
- // call all subnodes recursively
- for (unsigned int m = 0; m < node->mNumChildren; ++m)
- UpdateNodes(replaceMeshIndex,node->mChildren[m]);
+// std::vector<unsigned int>::const_iterator it;
+
+ if (node->mNumMeshes)
+ {
+ unsigned int newSize = 0;
+ for (unsigned int m = 0; m< node->mNumMeshes; ++m)
+ {
+ unsigned int add = node->mMeshes[m]<<2;
+ for (unsigned int i = 0; i < 4;++i)
+ {
+ if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
+ }
+ }
+ if (!newSize)
+ {
+ delete[] node->mMeshes;
+ node->mNumMeshes = 0;
+ node->mMeshes = NULL;
+ }
+ else
+ {
+ // Try to reuse the old array if possible
+ unsigned int* newMeshes = (newSize > node->mNumMeshes
+ ? new unsigned int[newSize] : node->mMeshes);
+
+ for (unsigned int m = 0; m< node->mNumMeshes; ++m)
+ {
+ unsigned int add = node->mMeshes[m]<<2;
+ for (unsigned int i = 0; i < 4;++i)
+ {
+ if (UINT_MAX != replaceMeshIndex[add+i])
+ *newMeshes++ = replaceMeshIndex[add+i];
+ }
+ }
+ if (newSize > node->mNumMeshes)
+ delete[] node->mMeshes;
+
+ node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
+ }
+ }
+
+ // call all subnodes recursively
+ for (unsigned int m = 0; m < node->mNumChildren; ++m)
+ UpdateNodes(replaceMeshIndex,node->mChildren[m]);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SortByPTypeProcess::Execute( aiScene* pScene)
{
- if (!pScene->mNumMeshes)
- {
- DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes");
- return;
- }
-
- DefaultLogger::get()->debug("SortByPTypeProcess begin");
-
- unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
-
- std::vector<aiMesh*> outMeshes;
- outMeshes.reserve(pScene->mNumMeshes<<1u);
-
- bool bAnyChanges = false;
-
- std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
- std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- {
- aiMesh* const mesh = pScene->mMeshes[i];
- ai_assert(0 != mesh->mPrimitiveTypes);
-
- // if there's just one primitive type in the mesh there's nothing to do for us
- unsigned int num = 0;
- if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
- {
- ++aiNumMeshesPerPType[0];
- ++num;
- }
- if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
- {
- ++aiNumMeshesPerPType[1];
- ++num;
- }
- if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
- {
- ++aiNumMeshesPerPType[2];
- ++num;
- }
- if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
- {
- ++aiNumMeshesPerPType[3];
- ++num;
- }
-
- if (1 == num)
- {
- if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
- {
- *meshIdx = (unsigned int) outMeshes.size();
- outMeshes.push_back(mesh);
- }
- else bAnyChanges = true;
-
- meshIdx += 4;
- continue;
- }
- bAnyChanges = true;
-
- // reuse our current mesh arrays for the submesh
- // with the largest numer of primitives
- unsigned int aiNumPerPType[4] = {0,0,0,0};
- aiFace* pFirstFace = mesh->mFaces;
- aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
-
- unsigned int numPolyVerts = 0;
- for (;pFirstFace != pLastFace; ++pFirstFace)
- {
- if (pFirstFace->mNumIndices <= 3)
- ++aiNumPerPType[pFirstFace->mNumIndices-1];
- else
- {
- ++aiNumPerPType[3];
- numPolyVerts += pFirstFace-> mNumIndices;
- }
- }
-
- VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
- for (unsigned int real = 0; real < 4; ++real,++meshIdx)
- {
- if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
- {
- continue;
- }
-
- *meshIdx = (unsigned int) outMeshes.size();
- outMeshes.push_back(new aiMesh());
- aiMesh* out = outMeshes.back();
-
- // the name carries the adjacency information between the meshes
- out->mName = mesh->mName;
-
- // copy data members
- out->mPrimitiveTypes = 1u << real;
- out->mMaterialIndex = mesh->mMaterialIndex;
-
- // allocate output storage
- out->mNumFaces = aiNumPerPType[real];
- aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
-
- out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
-
- aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL);
- aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
- aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
-
- if (mesh->mVertices)
- vert = out->mVertices = new aiVector3D[out->mNumVertices];
-
- if (mesh->mNormals)
- nor = out->mNormals = new aiVector3D[out->mNumVertices];
-
- if (mesh->mTangents)
- {
- tan = out->mTangents = new aiVector3D[out->mNumVertices];
- bit = out->mBitangents = new aiVector3D[out->mNumVertices];
- }
-
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
- {
- if (mesh->mTextureCoords[i])
- uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices];
- else uv[i] = NULL;
-
- out->mNumUVComponents[i] = mesh->mNumUVComponents[i];
- }
-
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
- {
- if (mesh->mColors[i])
- cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices];
- else cols[i] = NULL;
- }
-
- typedef std::vector< aiVertexWeight > TempBoneInfo;
- std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
-
- // try to guess how much storage we'll need
- for (unsigned int q = 0; q < mesh->mNumBones;++q)
- {
- tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
- }
-
- unsigned int outIdx = 0;
- for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
- {
- aiFace& in = mesh->mFaces[m];
- if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
- {
- continue;
- }
-
- outFaces->mNumIndices = in.mNumIndices;
- outFaces->mIndices = in.mIndices;
-
- for (unsigned int q = 0; q < in.mNumIndices; ++q)
- {
- unsigned int idx = in.mIndices[q];
-
- // process all bones of this index
- if (avw)
- {
- VertexWeightTable& tbl = avw[idx];
- for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
- it != end; ++it)
- {
- tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
- }
- }
-
- if (vert)
- {
- *vert++ = mesh->mVertices[idx];
- //mesh->mVertices[idx].x = get_qnan();
- }
- if (nor )*nor++ = mesh->mNormals[idx];
- if (tan )
- {
- *tan++ = mesh->mTangents[idx];
- *bit++ = mesh->mBitangents[idx];
- }
-
- for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
- {
- if (!uv[pp])break;
- *uv[pp]++ = mesh->mTextureCoords[pp][idx];
- }
-
- for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
- {
- if (!cols[pp])break;
- *cols[pp]++ = mesh->mColors[pp][idx];
- }
-
- in.mIndices[q] = outIdx++;
- }
-
- in.mIndices = NULL;
- ++outFaces;
- }
- ai_assert(outFaces == out->mFaces + out->mNumFaces);
-
- // now generate output bones
- for (unsigned int q = 0; q < mesh->mNumBones;++q)
- if (!tempBones[q].empty())++out->mNumBones;
-
- if (out->mNumBones)
- {
- out->mBones = new aiBone*[out->mNumBones];
- for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q)
- {
- TempBoneInfo& in = tempBones[q];
- if (in.empty())continue;
-
- aiBone* srcBone = mesh->mBones[q];
- aiBone* bone = out->mBones[real] = new aiBone();
-
- bone->mName = srcBone->mName;
- bone->mOffsetMatrix = srcBone->mOffsetMatrix;
-
- bone->mNumWeights = (unsigned int)in.size();
- bone->mWeights = new aiVertexWeight[bone->mNumWeights];
-
- ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
-
- ++real;
- }
- }
- }
-
- // delete the per-vertex bone weights table
- delete[] avw;
-
- // delete the input mesh
- delete mesh;
+ if (!pScene->mNumMeshes)
+ {
+ DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes");
+ return;
+ }
+
+ DefaultLogger::get()->debug("SortByPTypeProcess begin");
+
+ unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
+
+ std::vector<aiMesh*> outMeshes;
+ outMeshes.reserve(pScene->mNumMeshes<<1u);
+
+ bool bAnyChanges = false;
+
+ std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
+ std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+ {
+ aiMesh* const mesh = pScene->mMeshes[i];
+ ai_assert(0 != mesh->mPrimitiveTypes);
+
+ // if there's just one primitive type in the mesh there's nothing to do for us
+ unsigned int num = 0;
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
+ {
+ ++aiNumMeshesPerPType[0];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
+ {
+ ++aiNumMeshesPerPType[1];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
+ {
+ ++aiNumMeshesPerPType[2];
+ ++num;
+ }
+ if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
+ {
+ ++aiNumMeshesPerPType[3];
+ ++num;
+ }
+
+ if (1 == num)
+ {
+ if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
+ {
+ *meshIdx = (unsigned int) outMeshes.size();
+ outMeshes.push_back(mesh);
+ }
+ else bAnyChanges = true;
+
+ meshIdx += 4;
+ continue;
+ }
+ bAnyChanges = true;
+
+ // reuse our current mesh arrays for the submesh
+ // with the largest numer of primitives
+ unsigned int aiNumPerPType[4] = {0,0,0,0};
+ aiFace* pFirstFace = mesh->mFaces;
+ aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
+
+ unsigned int numPolyVerts = 0;
+ for (;pFirstFace != pLastFace; ++pFirstFace)
+ {
+ if (pFirstFace->mNumIndices <= 3)
+ ++aiNumPerPType[pFirstFace->mNumIndices-1];
+ else
+ {
+ ++aiNumPerPType[3];
+ numPolyVerts += pFirstFace-> mNumIndices;
+ }
+ }
+
+ VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
+ for (unsigned int real = 0; real < 4; ++real,++meshIdx)
+ {
+ if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
+ {
+ continue;
+ }
+
+ *meshIdx = (unsigned int) outMeshes.size();
+ outMeshes.push_back(new aiMesh());
+ aiMesh* out = outMeshes.back();
+
+ // the name carries the adjacency information between the meshes
+ out->mName = mesh->mName;
+
+ // copy data members
+ out->mPrimitiveTypes = 1u << real;
+ out->mMaterialIndex = mesh->mMaterialIndex;
+
+ // allocate output storage
+ out->mNumFaces = aiNumPerPType[real];
+ aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
+
+ out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
+
+ aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL);
+ aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ if (mesh->mVertices)
+ vert = out->mVertices = new aiVector3D[out->mNumVertices];
+
+ if (mesh->mNormals)
+ nor = out->mNormals = new aiVector3D[out->mNumVertices];
+
+ if (mesh->mTangents)
+ {
+ tan = out->mTangents = new aiVector3D[out->mNumVertices];
+ bit = out->mBitangents = new aiVector3D[out->mNumVertices];
+ }
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ {
+ if (mesh->mTextureCoords[i])
+ uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices];
+ else uv[i] = NULL;
+
+ out->mNumUVComponents[i] = mesh->mNumUVComponents[i];
+ }
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
+ {
+ if (mesh->mColors[i])
+ cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices];
+ else cols[i] = NULL;
+ }
+
+ typedef std::vector< aiVertexWeight > TempBoneInfo;
+ std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
+
+ // try to guess how much storage we'll need
+ for (unsigned int q = 0; q < mesh->mNumBones;++q)
+ {
+ tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
+ }
+
+ unsigned int outIdx = 0;
+ for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
+ {
+ aiFace& in = mesh->mFaces[m];
+ if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
+ {
+ continue;
+ }
+
+ outFaces->mNumIndices = in.mNumIndices;
+ outFaces->mIndices = in.mIndices;
+
+ for (unsigned int q = 0; q < in.mNumIndices; ++q)
+ {
+ unsigned int idx = in.mIndices[q];
+
+ // process all bones of this index
+ if (avw)
+ {
+ VertexWeightTable& tbl = avw[idx];
+ for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
+ it != end; ++it)
+ {
+ tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
+ }
+ }
+
+ if (vert)
+ {
+ *vert++ = mesh->mVertices[idx];
+ //mesh->mVertices[idx].x = get_qnan();
+ }
+ if (nor )*nor++ = mesh->mNormals[idx];
+ if (tan )
+ {
+ *tan++ = mesh->mTangents[idx];
+ *bit++ = mesh->mBitangents[idx];
+ }
+
+ for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
+ {
+ if (!uv[pp])break;
+ *uv[pp]++ = mesh->mTextureCoords[pp][idx];
+ }
+
+ for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
+ {
+ if (!cols[pp])break;
+ *cols[pp]++ = mesh->mColors[pp][idx];
+ }
+
+ in.mIndices[q] = outIdx++;
+ }
+
+ in.mIndices = NULL;
+ ++outFaces;
+ }
+ ai_assert(outFaces == out->mFaces + out->mNumFaces);
+
+ // now generate output bones
+ for (unsigned int q = 0; q < mesh->mNumBones;++q)
+ if (!tempBones[q].empty())++out->mNumBones;
+
+ if (out->mNumBones)
+ {
+ out->mBones = new aiBone*[out->mNumBones];
+ for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q)
+ {
+ TempBoneInfo& in = tempBones[q];
+ if (in.empty())continue;
+
+ aiBone* srcBone = mesh->mBones[q];
+ aiBone* bone = out->mBones[real] = new aiBone();
+
+ bone->mName = srcBone->mName;
+ bone->mOffsetMatrix = srcBone->mOffsetMatrix;
+
+ bone->mNumWeights = (unsigned int)in.size();
+ bone->mWeights = new aiVertexWeight[bone->mNumWeights];
+
+ ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
+
+ ++real;
+ }
+ }
+ }
+
+ // delete the per-vertex bone weights table
+ delete[] avw;
+
+ // delete the input mesh
+ delete mesh;
// avoid invalid pointer
pScene->mMeshes[i] = NULL;
- }
-
- if (outMeshes.empty())
- {
- // This should not occur
- throw DeadlyImportError("No meshes remaining");
- }
-
- // If we added at least one mesh process all nodes in the node
- // graph and update their respective mesh indices.
- if (bAnyChanges)
- {
- UpdateNodes(replaceMeshIndex,pScene->mRootNode);
- }
-
- if (outMeshes.size() != pScene->mNumMeshes)
- {
- delete[] pScene->mMeshes;
- pScene->mNumMeshes = (unsigned int)outMeshes.size();
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- }
- ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
-
- if (!DefaultLogger::isNullLogger())
- {
- char buffer[1024];
- ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)",
- aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""),
- aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""),
- aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""),
- aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : ""));
- DefaultLogger::get()->info(buffer);
- DefaultLogger::get()->debug("SortByPTypeProcess finished");
- }
+ }
+
+ if (outMeshes.empty())
+ {
+ // This should not occur
+ throw DeadlyImportError("No meshes remaining");
+ }
+
+ // If we added at least one mesh process all nodes in the node
+ // graph and update their respective mesh indices.
+ if (bAnyChanges)
+ {
+ UpdateNodes(replaceMeshIndex,pScene->mRootNode);
+ }
+
+ if (outMeshes.size() != pScene->mNumMeshes)
+ {
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)outMeshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ }
+ ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
+
+ if (!DefaultLogger::isNullLogger())
+ {
+ char buffer[1024];
+ ::ai_snprintf(buffer,1024,"Points: %u%s, Lines: %u%s, Triangles: %u%s, Polygons: %u%s (Meshes, X = removed)",
+ aiNumMeshesPerPType[0], ((configRemoveMeshes & aiPrimitiveType_POINT) ? "X" : ""),
+ aiNumMeshesPerPType[1], ((configRemoveMeshes & aiPrimitiveType_LINE) ? "X" : ""),
+ aiNumMeshesPerPType[2], ((configRemoveMeshes & aiPrimitiveType_TRIANGLE) ? "X" : ""),
+ aiNumMeshesPerPType[3], ((configRemoveMeshes & aiPrimitiveType_POLYGON) ? "X" : ""));
+ DefaultLogger::get()->info(buffer);
+ DefaultLogger::get()->debug("SortByPTypeProcess finished");
+ }
}
diff --git a/src/3rdparty/assimp/code/SortByPTypeProcess.h b/src/3rdparty/assimp/code/SortByPTypeProcess.h
index 455215f03..f96985cb3 100644
--- a/src/3rdparty/assimp/code/SortByPTypeProcess.h
+++ b/src/3rdparty/assimp/code/SortByPTypeProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,58 +23,58 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to sort meshes by the types
+/** @file Defines a post processing step to sort meshes by the types
of primitives they contain */
#ifndef AI_SORTBYPTYPEPROCESS_H_INC
#define AI_SORTBYPTYPEPROCESS_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
+#include <assimp/mesh.h>
class SortByPTypeProcessTest;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** SortByPTypeProcess: Sorts meshes by the types of primitives they contain.
- * A mesh with 5 lines, 3 points and 145 triangles would be split in 3
+ * A mesh with 5 lines, 3 points and 145 triangles would be split in 3
* submeshes.
*/
class ASSIMP_API SortByPTypeProcess : public BaseProcess
{
public:
- SortByPTypeProcess();
- ~SortByPTypeProcess();
+ SortByPTypeProcess();
+ ~SortByPTypeProcess();
public:
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
private:
- int configRemoveMeshes;
+ int configRemoveMeshes;
};
diff --git a/src/3rdparty/assimp/code/SpatialSort.cpp b/src/3rdparty/assimp/code/SpatialSort.cpp
index e54665609..c4e4ef2d5 100644
--- a/src/3rdparty/assimp/code/SpatialSort.cpp
+++ b/src/3rdparty/assimp/code/SpatialSort.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,318 +25,318 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the helper class to quickly find vertices close to a given position */
-#include "AssimpPCH.h"
#include "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
+# 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)
+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)
+ // 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);
+ mPlaneNormal.Normalize();
+ Fill(pPositions,pNumPositions,pElementOffset);
}
// ------------------------------------------------------------------------------------------------
SpatialSort :: SpatialSort()
: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
{
- mPlaneNormal.Normalize();
+ mPlaneNormal.Normalize();
}
// ------------------------------------------------------------------------------------------------
// Destructor
SpatialSort::~SpatialSort()
{
- // nothing to do here, everything destructs automatically
+ // nothing to do here, everything destructs automatically
}
// ------------------------------------------------------------------------------------------------
-void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
- unsigned int pElementOffset,
- bool pFinalize /*= true */)
+void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize /*= true */)
{
- mPositions.clear();
- Append(pPositions,pNumPositions,pElementOffset,pFinalize);
+ mPositions.clear();
+ Append(pPositions,pNumPositions,pElementOffset,pFinalize);
}
// ------------------------------------------------------------------------------------------------
void SpatialSort :: Finalize()
{
- std::sort( mPositions.begin(), mPositions.end());
+ std::sort( mPositions.begin(), mPositions.end());
}
// ------------------------------------------------------------------------------------------------
-void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
- unsigned int pElementOffset,
- bool pFinalize /*= true */)
+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
- float distance = *vec * mPlaneNormal;
- mPositions.push_back( Entry( a+initial, *vec, distance));
- }
-
- if (pFinalize) {
- // now sort the array ascending by distance.
- Finalize();
- }
+ // 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
+ float distance = *vec * mPlaneNormal;
+ mPositions.push_back( Entry( 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,
- float pRadius, std::vector<unsigned int>& poResults) const
+void SpatialSort::FindPositions( const aiVector3D& pPosition,
+ float pRadius, std::vector<unsigned int>& poResults) const
{
- const float dist = pPosition * mPlaneNormal;
- const float minDist = dist - pRadius, maxDist = dist + pRadius;
+ const float dist = pPosition * mPlaneNormal;
+ const float minDist = dist - pRadius, maxDist = dist + pRadius;
- // clear the array in this strange fashion because a simple clear() would also deallocate
+ // clear the array in this strange fashion because a simple clear() would also deallocate
// the array which we want to avoid
- poResults.erase( poResults.begin(), poResults.end());
-
- // 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 float 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
+ poResults.erase( poResults.begin(), poResults.end());
+
+ // 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 float 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 signed int BinFloat;
-
- // --------------------------------------------------------------------------------------------
- // Converts the bit pattern of a floating-point number to its signed integer representation.
- BinFloat ToBinary( const float & 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!
- BOOST_STATIC_ASSERT( sizeof(BinFloat) >= sizeof(float));
-
- #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).
- BOOST_STATIC_ASSERT( sizeof(BinFloat) == sizeof(float));
-
- // 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 {
- float 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;
- }
+ // 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 signed int BinFloat;
+
+ // --------------------------------------------------------------------------------------------
+ // Converts the bit pattern of a floating-point number to its signed integer representation.
+ BinFloat ToBinary( const float & 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(float), "sizeof(BinFloat) >= sizeof(float)");
+
+ #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(float), "sizeof(BinFloat) == sizeof(float)");
+
+ // 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 {
+ float 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 indentical to the given position. In opposite to
+// 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
+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
+ // 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.erase( poResults.begin(), poResults.end());
-
- // 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 aray
- 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
+ poResults.erase( poResults.begin(), poResults.end());
+
+ // 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 aray
+ 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,float pRadius) const
{
- fill.resize(mPositions.size(),UINT_MAX);
- float dist, maxDist;
-
- unsigned int t=0;
- const float 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;
- }
+ fill.resize(mPositions.size(),UINT_MAX);
+ float dist, maxDist;
+
+ unsigned int t=0;
+ const float 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());
- }
+ // 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;
+ return t;
}
diff --git a/src/3rdparty/assimp/code/SpatialSort.h b/src/3rdparty/assimp/code/SpatialSort.h
index 04a1a69ba..b594fc6d1 100644
--- a/src/3rdparty/assimp/code/SpatialSort.h
+++ b/src/3rdparty/assimp/code/SpatialSort.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_SPATIALSORT_H_INC
#include <vector>
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
namespace Assimp
{
@@ -52,7 +52,7 @@ namespace Assimp
/** A little helper class to quickly find all vertices in the epsilon environment of a given
* position. Construct an instance with an array of positions. The class stores the given positions
* by their indices and sorts them by their distance to an arbitrary chosen plane.
- * You can then query the instance for all vertices close to a given position in an average O(log n)
+ * You can then query the instance for all vertices close to a given position in an average O(log n)
* time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen
* so that it avoids common planes in usual data sets. */
// ------------------------------------------------------------------------------------------------
@@ -60,109 +60,109 @@ class SpatialSort
{
public:
- SpatialSort();
+ SpatialSort();
- // ------------------------------------------------------------------------------------
- /** Constructs a spatially sorted representation from the given position array.
- * Supply the positions in its layout in memory, the class will only refer to them
- * by index.
- * @param pPositions Pointer to the first position vector of the array.
- * @param pNumPositions Number of vectors to expect in that array.
- * @param pElementOffset Offset in bytes from the beginning of one vector in memory
- * to the beginning of the next vector. */
- SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
- unsigned int pElementOffset);
+ // ------------------------------------------------------------------------------------
+ /** Constructs a spatially sorted representation from the given position array.
+ * Supply the positions in its layout in memory, the class will only refer to them
+ * by index.
+ * @param pPositions Pointer to the first position vector of the array.
+ * @param pNumPositions Number of vectors to expect in that array.
+ * @param pElementOffset Offset in bytes from the beginning of one vector in memory
+ * to the beginning of the next vector. */
+ SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset);
- /** Destructor */
- ~SpatialSort();
+ /** Destructor */
+ ~SpatialSort();
public:
- // ------------------------------------------------------------------------------------
- /** Sets the input data for the SpatialSort. This replaces existing data, if any.
- * The new data receives new indices in ascending order.
- *
- * @param pPositions Pointer to the first position vector of the array.
- * @param pNumPositions Number of vectors to expect in that array.
- * @param pElementOffset Offset in bytes from the beginning of one vector in memory
- * to the beginning of the next vector.
- * @param pFinalize Specifies whether the SpatialSort's internal representation
- * is finalized after the new data has been added. Finalization is
- * required in order to use #FindPosition() or #GenerateMappingTable().
- * If you don't finalize yet, you can use #Append() to add data from
- * other sources.*/
- void Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
- unsigned int pElementOffset,
- bool pFinalize = true);
-
-
- // ------------------------------------------------------------------------------------
- /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
- void Append( const aiVector3D* pPositions, unsigned int pNumPositions,
- unsigned int pElementOffset,
- bool pFinalize = true);
-
-
- // ------------------------------------------------------------------------------------
- /** Finalize the spatial hash data structure. This can be useful after
- * multiple calls to #Append() with the pFinalize parameter set to false.
- * This is finally required before one of #FindPositions() and #GenerateMappingTable()
- * can be called to query the spatial sort.*/
- void Finalize();
-
- // ------------------------------------------------------------------------------------
- /** Returns an iterator for all positions close to the given position.
- * @param pPosition The position to look for vertices.
- * @param pRadius Maximal distance from the position a vertex may have to be counted in.
- * @param poResults The container to store the indices of the found positions.
- * Will be emptied by the call so it may contain anything.
- * @return An iterator to iterate over all vertices in the given area.*/
- void FindPositions( const aiVector3D& pPosition, float pRadius,
- std::vector<unsigned int>& poResults) const;
-
- // ------------------------------------------------------------------------------------
- /** Fills an array with indices of all positions indentical to the given position. In
- * opposite to FindPositions(), not an epsilon is used but a (very low) tolerance of
- * four floating-point units.
- * @param pPosition The position to look for vertices.
- * @param poResults The container to store the indices of the found positions.
- * Will be emptied by the call so it may contain anything.*/
- void FindIdenticalPositions( const aiVector3D& pPosition,
- std::vector<unsigned int>& poResults) const;
-
- // ------------------------------------------------------------------------------------
- /** Compute a table that maps each vertex ID referring to a spatially close
- * enough position to the same output ID. Output IDs are assigned in ascending order
- * from 0...n.
- * @param fill Will be filled with numPositions entries.
- * @param pRadius Maximal distance from the position a vertex may have to
- * be counted in.
- * @return Number of unique vertices (n). */
- unsigned int GenerateMappingTable(std::vector<unsigned int>& fill,
- float pRadius) const;
+ // ------------------------------------------------------------------------------------
+ /** Sets the input data for the SpatialSort. This replaces existing data, if any.
+ * The new data receives new indices in ascending order.
+ *
+ * @param pPositions Pointer to the first position vector of the array.
+ * @param pNumPositions Number of vectors to expect in that array.
+ * @param pElementOffset Offset in bytes from the beginning of one vector in memory
+ * to the beginning of the next vector.
+ * @param pFinalize Specifies whether the SpatialSort's internal representation
+ * is finalized after the new data has been added. Finalization is
+ * required in order to use #FindPosition() or #GenerateMappingTable().
+ * If you don't finalize yet, you can use #Append() to add data from
+ * other sources.*/
+ void Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize = true);
+
+
+ // ------------------------------------------------------------------------------------
+ /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
+ void Append( const aiVector3D* pPositions, unsigned int pNumPositions,
+ unsigned int pElementOffset,
+ bool pFinalize = true);
+
+
+ // ------------------------------------------------------------------------------------
+ /** Finalize the spatial hash data structure. This can be useful after
+ * multiple calls to #Append() with the pFinalize parameter set to false.
+ * This is finally required before one of #FindPositions() and #GenerateMappingTable()
+ * can be called to query the spatial sort.*/
+ void Finalize();
+
+ // ------------------------------------------------------------------------------------
+ /** Returns an iterator for all positions close to the given position.
+ * @param pPosition The position to look for vertices.
+ * @param pRadius Maximal distance from the position a vertex may have to be counted in.
+ * @param poResults The container to store the indices of the found positions.
+ * Will be emptied by the call so it may contain anything.
+ * @return An iterator to iterate over all vertices in the given area.*/
+ void FindPositions( const aiVector3D& pPosition, float pRadius,
+ std::vector<unsigned int>& poResults) const;
+
+ // ------------------------------------------------------------------------------------
+ /** 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.
+ * @param pPosition The position to look for vertices.
+ * @param poResults The container to store the indices of the found positions.
+ * Will be emptied by the call so it may contain anything.*/
+ void FindIdenticalPositions( const aiVector3D& pPosition,
+ std::vector<unsigned int>& poResults) const;
+
+ // ------------------------------------------------------------------------------------
+ /** Compute a table that maps each vertex ID referring to a spatially close
+ * enough position to the same output ID. Output IDs are assigned in ascending order
+ * from 0...n.
+ * @param fill Will be filled with numPositions entries.
+ * @param pRadius Maximal distance from the position a vertex may have to
+ * be counted in.
+ * @return Number of unique vertices (n). */
+ unsigned int GenerateMappingTable(std::vector<unsigned int>& fill,
+ float pRadius) const;
protected:
- /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
- aiVector3D mPlaneNormal;
-
- /** An entry in a spatially sorted position array. Consists of a vertex index,
- * its position and its precalculated distance from the reference plane */
- struct Entry
- {
- unsigned int mIndex; ///< The vertex referred by this entry
- aiVector3D mPosition; ///< Position
- float mDistance; ///< Distance of this vertex to the sorting plane
-
- Entry() { /** intentionally not initialized.*/ }
- Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance)
- : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance)
- { }
-
- bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
- };
-
- // all positions, sorted by distance to the sorting plane
- std::vector<Entry> mPositions;
+ /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
+ aiVector3D mPlaneNormal;
+
+ /** An entry in a spatially sorted position array. Consists of a vertex index,
+ * its position and its precalculated distance from the reference plane */
+ struct Entry
+ {
+ unsigned int mIndex; ///< The vertex referred by this entry
+ aiVector3D mPosition; ///< Position
+ float mDistance; ///< Distance of this vertex to the sorting plane
+
+ Entry() { /** intentionally not initialized.*/ }
+ Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance)
+ : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance)
+ { }
+
+ bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
+ };
+
+ // all positions, sorted by distance to the sorting plane
+ std::vector<Entry> mPositions;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp b/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
index 1b033451c..58b14ff49 100644
--- a/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
+++ b/src/3rdparty/assimp/code/SplitByBoneCountProcess.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,381 +23,383 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/// @file SplitByBoneCountProcess.cpp
+/// @file SplitByBoneCountProcess.cpp
/// Implementation of the SplitByBoneCount postprocessing step
-#include "AssimpPCH.h"
-
// internal headers of the post-processing framework
#include "SplitByBoneCountProcess.h"
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
#include <limits>
+#include "TinyFormatter.h"
using namespace Assimp;
+using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------
// Constructor
SplitByBoneCountProcess::SplitByBoneCountProcess()
{
- // set default, might be overriden by importer config
- mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
+ // set default, might be overriden by importer config
+ mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
}
// ------------------------------------------------------------------------------------------------
// Destructor
SplitByBoneCountProcess::~SplitByBoneCountProcess()
{
- // nothing to do here
+ // 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);
+ 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);
+ 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)
{
- DefaultLogger::get()->debug("SplitByBoneCountProcess begin");
-
- // early out
- bool isNecessary = false;
- for( size_t a = 0; a < pScene->mNumMeshes; ++a)
- if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
- isNecessary = true;
-
- if( !isNecessary )
- {
- DefaultLogger::get()->debug( boost::str( boost::format( "SplitByBoneCountProcess early-out: no meshes with more than %d bones.") % mMaxBoneCount));
- 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( size_t 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( size_t b = 0; b < newMeshes.size(); ++b)
- {
- mSubMeshIndices[a].push_back( 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( meshes.size());
- meshes.push_back( srcMesh);
- }
- }
-
- // rebuild the scene's mesh array
- pScene->mNumMeshes = 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);
-
- DefaultLogger::get()->debug( boost::str( boost::format( "SplitByBoneCountProcess end: split %d meshes into %d submeshes.") % mSubMeshIndices.size() % meshes.size()));
+ DefaultLogger::get()->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 )
+ {
+ DefaultLogger::get()->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);
+
+ DefaultLogger::get()->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<size_t, float> BoneWeight;
- std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
- for( size_t a = 0; a < pMesh->mNumBones; ++a)
- {
- const aiBone* bone = pMesh->mBones[a];
- for( size_t b = 0; b < bone->mNumWeights; ++b)
- vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
- }
-
- size_t numFacesHandled = 0;
- std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
- while( numFacesHandled < pMesh->mNumFaces )
- {
- // which bones are used in the current submesh
- size_t numBones = 0;
- std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
- // indices of the faces which are going to go into this submesh
- std::vector<size_t> subMeshFaces;
- subMeshFaces.reserve( pMesh->mNumFaces);
- // accumulated vertex count of all the faces in this submesh
- size_t 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<size_t> newBonesAtCurrentFace;
-
- // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
- for( size_t 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( size_t b = 0; b < face.mNumIndices; ++b )
- {
- const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
- for( size_t c = 0; c < vb.size(); ++c)
- {
- size_t 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() )
- {
- size_t 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( boost::str( boost::format( "%s_sub%d") % pMesh->mName.data % 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 = 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( size_t 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( size_t 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()];
- size_t nvi = 0; // next vertex index
- std::vector<size_t> previousVertexIndices( numSubMeshVertices, std::numeric_limits<size_t>::max()); // per new vertex: its index in the source mesh
- for( size_t 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( size_t b = 0; b < dstFace.mNumIndices; ++b )
- {
- size_t 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( size_t c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
- {
- if( pMesh->HasTextureCoords( c) )
- newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
- }
- for( size_t 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<size_t> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<size_t>::max());
- for( size_t 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( size_t a = 0; a < numSubMeshVertices; ++a )
- {
- size_t oldIndex = previousVertexIndices[a];
- const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
-
- for( size_t b = 0; b < bonesOnThisVertex.size(); ++b )
- {
- size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
- if( newBoneIndex != std::numeric_limits<size_t>::max() )
- newMesh->mBones[newBoneIndex]->mNumWeights++;
- }
- }
-
- // allocate all bone weight arrays accordingly
- for( size_t 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( size_t a = 0; a < numSubMeshVertices; ++a)
- {
- // find the source vertex for it in the source mesh
- size_t 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( size_t b = 0; b < bonesOnThisVertex.size(); ++b)
- {
- size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
- ai_assert( newBoneIndex != std::numeric_limits<size_t>::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...
- }
+ // 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<size_t> newMeshList;
- for( size_t a = 0; a < pNode->mNumMeshes; ++a)
- {
- size_t srcIndex = pNode->mMeshes[a];
- const std::vector<size_t>& replaceMeshes = mSubMeshIndices[srcIndex];
- newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
- }
-
- delete pNode->mMeshes;
- pNode->mNumMeshes = 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( size_t a = 0; a < pNode->mNumChildren; ++a )
- {
- UpdateNode( pNode->mChildren[a]);
- }
+ // 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]);
+ }
}
diff --git a/src/3rdparty/assimp/code/SplitByBoneCountProcess.h b/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
index ddade0f9a..816d18357 100644
--- a/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
+++ b/src/3rdparty/assimp/code/SplitByBoneCountProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,22 +23,22 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/// @file SplitByBoneCountProcess.h
+/// @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
@@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/scene.h"
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
namespace Assimp
{
@@ -63,45 +63,45 @@ class SplitByBoneCountProcess : public BaseProcess
{
public:
- SplitByBoneCountProcess();
- ~SplitByBoneCountProcess();
+ 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);
+ /** 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);
+ /** 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;
+ /// 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;
+ /// 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;
+ /// 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<size_t> > mSubMeshIndices;
+ /// Per mesh index: Array of indices of the new submeshes.
+ std::vector< std::vector<unsigned int> > mSubMeshIndices;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
index 4be8fe104..5e21ec6b8 100644
--- a/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
+++ b/src/3rdparty/assimp/code/SplitLargeMeshes.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the SplitLargeMeshes postprocessing step
*/
-#include "AssimpPCH.h"
+
// internal headers of the post-processing framework
#include "SplitLargeMeshes.h"
@@ -54,50 +54,50 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle()
{
- LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
+ LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
}
// ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_SplitLargeMeshes) != 0;
+ return (pFlags & aiProcess_SplitLargeMeshes) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
{
- if (0xffffffff == this->LIMIT)return;
-
- DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
- std::vector<std::pair<aiMesh*, unsigned int> > avList;
-
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- this->SplitMesh(a, pScene->mMeshes[a],avList);
-
- if (avList.size() != pScene->mNumMeshes)
- {
- // it seems something has been split. rebuild the mesh list
- delete[] pScene->mMeshes;
- pScene->mNumMeshes = (unsigned int)avList.size();
- pScene->mMeshes = new aiMesh*[avList.size()];
-
- for (unsigned int i = 0; i < avList.size();++i)
- pScene->mMeshes[i] = avList[i].first;
-
- // now we need to update all nodes
- this->UpdateNode(pScene->mRootNode,avList);
- DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
- }
- else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
- return;
+ if (0xffffffff == this->LIMIT)return;
+
+ DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
+ std::vector<std::pair<aiMesh*, unsigned int> > avList;
+
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ this->SplitMesh(a, pScene->mMeshes[a],avList);
+
+ if (avList.size() != pScene->mNumMeshes)
+ {
+ // it seems something has been split. rebuild the mesh list
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)avList.size();
+ pScene->mMeshes = new aiMesh*[avList.size()];
+
+ for (unsigned int i = 0; i < avList.size();++i)
+ pScene->mMeshes[i] = avList[i].first;
+
+ // now we need to update all nodes
+ this->UpdateNode(pScene->mRootNode,avList);
+ DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
+ }
+ else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
+ return;
}
// ------------------------------------------------------------------------------------------------
@@ -105,573 +105,571 @@ void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp)
{
// get the current value of the split property
- this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
+ this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
}
// ------------------------------------------------------------------------------------------------
// Update a node after some meshes have been split
void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
- const std::vector<std::pair<aiMesh*, unsigned int> >& avList)
+ const std::vector<std::pair<aiMesh*, unsigned int> >& avList)
{
- // for every index in out list build a new entry
- std::vector<unsigned int> aiEntries;
- aiEntries.reserve(pcNode->mNumMeshes + 1);
- for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
- {
- for (unsigned int a = 0; a < avList.size();++a)
- {
- if (avList[a].second == pcNode->mMeshes[i])
- {
- aiEntries.push_back(a);
- }
- }
- }
-
- // now build the new list
- delete pcNode->mMeshes;
- pcNode->mNumMeshes = (unsigned int)aiEntries.size();
- pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
-
- for (unsigned int b = 0; b < pcNode->mNumMeshes;++b)
- pcNode->mMeshes[b] = aiEntries[b];
-
- // recusively update all other nodes
- for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
- {
- UpdateNode ( pcNode->mChildren[i], avList );
- }
- return;
+ // for every index in out list build a new entry
+ std::vector<unsigned int> aiEntries;
+ aiEntries.reserve(pcNode->mNumMeshes + 1);
+ for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
+ {
+ for (unsigned int a = 0; a < avList.size();++a)
+ {
+ if (avList[a].second == pcNode->mMeshes[i])
+ {
+ aiEntries.push_back(a);
+ }
+ }
+ }
+
+ // now build the new list
+ delete[] pcNode->mMeshes;
+ pcNode->mNumMeshes = (unsigned int)aiEntries.size();
+ pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
+
+ for (unsigned int b = 0; b < pcNode->mNumMeshes;++b)
+ pcNode->mMeshes[b] = aiEntries[b];
+
+ // recusively update all other nodes
+ for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
+ {
+ UpdateNode ( pcNode->mChildren[i], avList );
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Triangle::SplitMesh(
- unsigned int a,
- aiMesh* pMesh,
- std::vector<std::pair<aiMesh*, unsigned int> >& avList)
+ unsigned int a,
+ aiMesh* pMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList)
{
- if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
- {
- DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ...");
-
- // we need to split this mesh into sub meshes
- // determine the size of a submesh
- const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
-
- const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
- const unsigned int iOutVertexNum = iOutFaceNum * 3;
-
- // now generate all submeshes
- for (unsigned int i = 0; i < iSubMeshes;++i)
- {
- aiMesh* pcMesh = new aiMesh;
- pcMesh->mNumFaces = iOutFaceNum;
- pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
-
- // the name carries the adjacency information between the meshes
- pcMesh->mName = pMesh->mName;
-
- if (i == iSubMeshes-1)
- {
- pcMesh->mNumFaces = iOutFaceNum + (
- pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
- }
- // copy the list of faces
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
-
- const unsigned int iBase = iOutFaceNum * i;
-
- // get the total number of indices
- unsigned int iCnt = 0;
- for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p)
- {
- iCnt += pMesh->mFaces[p].mNumIndices;
- }
- pcMesh->mNumVertices = iCnt;
-
- // allocate storage
- if (pMesh->mVertices != NULL)
- pcMesh->mVertices = new aiVector3D[iCnt];
-
- if (pMesh->HasNormals())
- pcMesh->mNormals = new aiVector3D[iCnt];
-
- if (pMesh->HasTangentsAndBitangents())
- {
- pcMesh->mTangents = new aiVector3D[iCnt];
- pcMesh->mBitangents = new aiVector3D[iCnt];
- }
-
- // texture coordinates
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
- {
- pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
- if (pMesh->HasTextureCoords( c))
- {
- pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
- }
- }
-
- // vertex colors
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
- {
- if (pMesh->HasVertexColors( c))
- {
- pcMesh->mColors[c] = new aiColor4D[iCnt];
- }
- }
-
- if (pMesh->HasBones())
- {
- // assume the number of bones won't change in most cases
- pcMesh->mBones = new aiBone*[pMesh->mNumBones];
-
- // iterate through all bones of the mesh and find those which
- // need to be copied to the split mesh
- std::vector<aiVertexWeight> avTempWeights;
- for (unsigned int p = 0; p < pcMesh->mNumBones;++p)
- {
- aiBone* const bone = pcMesh->mBones[p];
- avTempWeights.clear();
- avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
-
- for (unsigned int q = 0; q < bone->mNumWeights;++q)
- {
- aiVertexWeight& weight = bone->mWeights[q];
- if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum)
- {
- avTempWeights.push_back(weight);
- weight = avTempWeights.back();
- weight.mVertexId -= iBase;
- }
- }
-
- if (!avTempWeights.empty())
- {
- // we'll need this bone. Copy it ...
- aiBone* pc = new aiBone();
- pcMesh->mBones[pcMesh->mNumBones++] = pc;
- pc->mName = aiString(bone->mName);
- pc->mNumWeights = (unsigned int)avTempWeights.size();
- pc->mOffsetMatrix = bone->mOffsetMatrix;
-
- // no need to reallocate the array for the last submesh.
- // Here we can reuse the (large) source array, although
- // we'll waste some memory
- if (iSubMeshes-1 == i)
- {
- pc->mWeights = bone->mWeights;
- bone->mWeights = NULL;
- }
- else pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-
- // copy the weights
- ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
- }
- }
- }
-
- // (we will also need to copy the array of indices)
- unsigned int iCurrent = 0;
- for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
- {
- pcMesh->mFaces[p].mNumIndices = 3;
- // allocate a new array
- const unsigned int iTemp = p + iBase;
- const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
-
- // setup face type and number of indices
- pcMesh->mFaces[p].mNumIndices = iNumIndices;
- unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
- unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
-
- // need to update the output primitive types
- switch (iNumIndices)
- {
- case 1:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
- break;
- case 2:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
- break;
- case 3:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- break;
- default:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- }
-
- // and copy the contents of the old array, offset by current base
- for (unsigned int v = 0; v < iNumIndices;++v)
- {
- unsigned int iIndex = pi[v];
- unsigned int iIndexOut = iCurrent++;
- piOut[v] = iIndexOut;
-
- // copy positions
- if (pMesh->mVertices != NULL)
- pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
-
- // copy normals
- if (pMesh->HasNormals())
- pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
-
- // copy tangents/bitangents
- if (pMesh->HasTangentsAndBitangents())
- {
- pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
- pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
- }
-
- // texture coordinates
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
- {
- if (pMesh->HasTextureCoords( c))
- pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
- }
- // vertex colors
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
- {
- if (pMesh->HasVertexColors( c))
- pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
- }
- }
- }
-
- // add the newly created mesh to the list
- avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
- }
-
- // now delete the old mesh data
- delete pMesh;
- }
- else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
- return;
+ if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
+ {
+ DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ...");
+
+ // we need to split this mesh into sub meshes
+ // determine the size of a submesh
+ const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
+
+ const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
+ const unsigned int iOutVertexNum = iOutFaceNum * 3;
+
+ // now generate all submeshes
+ for (unsigned int i = 0; i < iSubMeshes;++i)
+ {
+ aiMesh* pcMesh = new aiMesh;
+ pcMesh->mNumFaces = iOutFaceNum;
+ pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
+
+ // the name carries the adjacency information between the meshes
+ pcMesh->mName = pMesh->mName;
+
+ if (i == iSubMeshes-1)
+ {
+ pcMesh->mNumFaces = iOutFaceNum + (
+ pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
+ }
+ // copy the list of faces
+ pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
+
+ const unsigned int iBase = iOutFaceNum * i;
+
+ // get the total number of indices
+ unsigned int iCnt = 0;
+ for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p)
+ {
+ iCnt += pMesh->mFaces[p].mNumIndices;
+ }
+ pcMesh->mNumVertices = iCnt;
+
+ // allocate storage
+ if (pMesh->mVertices != NULL)
+ pcMesh->mVertices = new aiVector3D[iCnt];
+
+ if (pMesh->HasNormals())
+ pcMesh->mNormals = new aiVector3D[iCnt];
+
+ if (pMesh->HasTangentsAndBitangents())
+ {
+ pcMesh->mTangents = new aiVector3D[iCnt];
+ pcMesh->mBitangents = new aiVector3D[iCnt];
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+ {
+ pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
+ if (pMesh->HasTextureCoords( c))
+ {
+ pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
+ }
+ }
+
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
+ {
+ if (pMesh->HasVertexColors( c))
+ {
+ pcMesh->mColors[c] = new aiColor4D[iCnt];
+ }
+ }
+
+ if (pMesh->HasBones())
+ {
+ // assume the number of bones won't change in most cases
+ pcMesh->mBones = new aiBone*[pMesh->mNumBones];
+
+ // iterate through all bones of the mesh and find those which
+ // need to be copied to the split mesh
+ std::vector<aiVertexWeight> avTempWeights;
+ for (unsigned int p = 0; p < pcMesh->mNumBones;++p)
+ {
+ aiBone* const bone = pcMesh->mBones[p];
+ avTempWeights.clear();
+ avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
+
+ for (unsigned int q = 0; q < bone->mNumWeights;++q)
+ {
+ aiVertexWeight& weight = bone->mWeights[q];
+ if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum)
+ {
+ avTempWeights.push_back(weight);
+ weight = avTempWeights.back();
+ weight.mVertexId -= iBase;
+ }
+ }
+
+ if (!avTempWeights.empty())
+ {
+ // we'll need this bone. Copy it ...
+ aiBone* pc = new aiBone();
+ pcMesh->mBones[pcMesh->mNumBones++] = pc;
+ pc->mName = aiString(bone->mName);
+ pc->mNumWeights = (unsigned int)avTempWeights.size();
+ pc->mOffsetMatrix = bone->mOffsetMatrix;
+
+ // no need to reallocate the array for the last submesh.
+ // Here we can reuse the (large) source array, although
+ // we'll waste some memory
+ if (iSubMeshes-1 == i)
+ {
+ pc->mWeights = bone->mWeights;
+ bone->mWeights = NULL;
+ }
+ else pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+
+ // copy the weights
+ ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
+ }
+ }
+ }
+
+ // (we will also need to copy the array of indices)
+ unsigned int iCurrent = 0;
+ for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
+ {
+ pcMesh->mFaces[p].mNumIndices = 3;
+ // allocate a new array
+ const unsigned int iTemp = p + iBase;
+ const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
+
+ // setup face type and number of indices
+ pcMesh->mFaces[p].mNumIndices = iNumIndices;
+ unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
+ unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
+
+ // need to update the output primitive types
+ switch (iNumIndices)
+ {
+ case 1:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+
+ // and copy the contents of the old array, offset by current base
+ for (unsigned int v = 0; v < iNumIndices;++v)
+ {
+ unsigned int iIndex = pi[v];
+ unsigned int iIndexOut = iCurrent++;
+ piOut[v] = iIndexOut;
+
+ // copy positions
+ if (pMesh->mVertices != NULL)
+ pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
+
+ // copy normals
+ if (pMesh->HasNormals())
+ pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
+
+ // copy tangents/bitangents
+ if (pMesh->HasTangentsAndBitangents())
+ {
+ pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
+ pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+ {
+ if (pMesh->HasTextureCoords( c))
+ pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
+ }
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
+ {
+ if (pMesh->HasVertexColors( c))
+ pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
+ }
+ }
+ }
+
+ // add the newly created mesh to the list
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
+ }
+
+ // now delete the old mesh data
+ delete pMesh;
+ }
+ else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+ return;
}
// ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex()
{
- LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
+ LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
}
// ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_SplitLargeMeshes) != 0;
+ return (pFlags & aiProcess_SplitLargeMeshes) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
{
- std::vector<std::pair<aiMesh*, unsigned int> > avList;
-
- if (0xffffffff == this->LIMIT)return;
-
- DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin");
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- this->SplitMesh(a, pScene->mMeshes[a],avList);
-
- if (avList.size() != pScene->mNumMeshes)
- {
- // it seems something has been split. rebuild the mesh list
- delete[] pScene->mMeshes;
- pScene->mNumMeshes = (unsigned int)avList.size();
- pScene->mMeshes = new aiMesh*[avList.size()];
-
- for (unsigned int i = 0; i < avList.size();++i)
- pScene->mMeshes[i] = avList[i].first;
-
- // now we need to update all nodes
- SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
- DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
- }
- else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
- return;
+ std::vector<std::pair<aiMesh*, unsigned int> > avList;
+
+ if (0xffffffff == this->LIMIT)return;
+
+ DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin");
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ this->SplitMesh(a, pScene->mMeshes[a],avList);
+
+ if (avList.size() != pScene->mNumMeshes)
+ {
+ // it seems something has been split. rebuild the mesh list
+ delete[] pScene->mMeshes;
+ pScene->mNumMeshes = (unsigned int)avList.size();
+ pScene->mMeshes = new aiMesh*[avList.size()];
+
+ for (unsigned int i = 0; i < avList.size();++i)
+ pScene->mMeshes[i] = avList[i].first;
+
+ // now we need to update all nodes
+ SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
+ DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
+ }
+ else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
+ return;
}
// ------------------------------------------------------------------------------------------------
// Setup properties
void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp)
{
- this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
+ this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void SplitLargeMeshesProcess_Vertex::SplitMesh(
- unsigned int a,
- aiMesh* pMesh,
- std::vector<std::pair<aiMesh*, unsigned int> >& avList)
+ unsigned int a,
+ aiMesh* pMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList)
{
- if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT)
- {
- typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
-
- // build a per-vertex weight list if necessary
- VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
-
- // we need to split this mesh into sub meshes
- // determine the estimated size of a submesh
- // (this could be too large. Max waste is a single digit percentage)
- const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
- //const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes;
-
- // create a std::vector<unsigned int> to indicate which vertices
- // have already been copied
- std::vector<unsigned int> avWasCopied;
- avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
-
- // try to find a good estimate for the number of output faces
- // per mesh. Add 12.5% as buffer
- unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
- iEstimatedSize += iEstimatedSize >> 3;
-
- // now generate all submeshes
- unsigned int iBase = 0;
- while (true)
- {
- const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
-
- aiMesh* pcMesh = new aiMesh;
- pcMesh->mNumVertices = 0;
- pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
-
- // the name carries the adjacency information between the meshes
- pcMesh->mName = pMesh->mName;
-
- typedef std::vector<aiVertexWeight> BoneWeightList;
- if (pMesh->HasBones())
- {
- pcMesh->mBones = new aiBone*[pMesh->mNumBones];
- ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
- }
-
- // clear the temporary helper array
- if (iBase)
- {
- // we can't use memset here we unsigned int needn' be 32 bits
- for (std::vector<unsigned int>::iterator
- iter = avWasCopied.begin(),end = avWasCopied.end();
- iter != end;++iter)
- {
- (*iter) = 0xffffffff;
- }
- }
-
- // output vectors
- std::vector<aiFace> vFaces;
-
- // reserve enough storage for most cases
- if (pMesh->HasPositions())
- {
- pcMesh->mVertices = new aiVector3D[iOutVertexNum];
- }
- if (pMesh->HasNormals())
- {
- pcMesh->mNormals = new aiVector3D[iOutVertexNum];
- }
- if (pMesh->HasTangentsAndBitangents())
- {
- pcMesh->mTangents = new aiVector3D[iOutVertexNum];
- pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
- }
- for (unsigned int c = 0; pMesh->HasVertexColors(c);++c)
- {
- pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
- }
- for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c)
- {
- pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
- pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
- }
- vFaces.reserve(iEstimatedSize);
-
- // (we will also need to copy the array of indices)
- while (iBase < pMesh->mNumFaces)
- {
- // allocate a new array
- const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
-
- // doesn't catch degenerates but is quite fast
- unsigned int iNeed = 0;
- for (unsigned int v = 0; v < iNumIndices;++v)
- {
- unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
-
- // check whether we do already have this vertex
- if (0xFFFFFFFF == avWasCopied[iIndex])
- {
- iNeed++;
- }
- }
- if (pcMesh->mNumVertices + iNeed > iOutVertexNum)
- {
- // don't use this face
- break;
- }
-
- vFaces.push_back(aiFace());
- aiFace& rFace = vFaces.back();
-
- // setup face type and number of indices
- rFace.mNumIndices = iNumIndices;
- rFace.mIndices = new unsigned int[iNumIndices];
-
- // need to update the output primitive types
- switch (rFace.mNumIndices)
- {
- case 1:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
- break;
- case 2:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
- break;
- case 3:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- break;
- default:
- pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
- }
-
- // and copy the contents of the old array, offset by current base
- for (unsigned int v = 0; v < iNumIndices;++v)
- {
- unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
-
- // check whether we do already have this vertex
- if (0xFFFFFFFF != avWasCopied[iIndex])
- {
- rFace.mIndices[v] = avWasCopied[iIndex];
- continue;
- }
-
- // copy positions
- pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
-
- // copy normals
- if (pMesh->HasNormals())
- {
- pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
- }
-
- // copy tangents/bitangents
- if (pMesh->HasTangentsAndBitangents())
- {
- pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
- pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
- }
-
- // texture coordinates
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
- {
- if (pMesh->HasTextureCoords( c))
- {
- pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
- }
- }
- // vertex colors
- for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
- {
- if (pMesh->HasVertexColors( c))
- {
- pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
- }
- }
- // check whether we have bone weights assigned to this vertex
- rFace.mIndices[v] = pcMesh->mNumVertices;
- if (avPerVertexWeights)
- {
- VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
- if( !table.empty() )
- {
- for (VertexWeightTable::const_iterator
- iter = table.begin();
- iter != table.end();++iter)
- {
- // allocate the bone weight array if necessary
- BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
- if (!pcWeightList)
- {
- pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
- }
- pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
- }
- }
- }
-
- avWasCopied[iIndex] = pcMesh->mNumVertices;
- pcMesh->mNumVertices++;
- }
- iBase++;
- if(pcMesh->mNumVertices == iOutVertexNum)
- {
- // break here. The face is only added if it was complete
- break;
- }
- }
-
- // check which bones we'll need to create for this submesh
- if (pMesh->HasBones())
- {
- aiBone** ppCurrent = pcMesh->mBones;
- for (unsigned int k = 0; k < pMesh->mNumBones;++k)
- {
- // check whether the bone is existing
- BoneWeightList* pcWeightList;
- if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k]))
- {
- aiBone* pcOldBone = pMesh->mBones[k];
- aiBone* pcOut;
- *ppCurrent++ = pcOut = new aiBone();
- pcOut->mName = aiString(pcOldBone->mName);
- pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
- pcOut->mNumWeights = (unsigned int)pcWeightList->size();
- pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights];
-
- // copy the vertex weights
- ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
- pcOut->mNumWeights * sizeof(aiVertexWeight));
-
- // delete the temporary bone weight list
- delete pcWeightList;
- pcMesh->mNumBones++;
- }
- }
- }
-
- // copy the face list to the mesh
- pcMesh->mFaces = new aiFace[vFaces.size()];
- pcMesh->mNumFaces = (unsigned int)vFaces.size();
-
- for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
- pcMesh->mFaces[p] = vFaces[p];
-
- // add the newly created mesh to the list
- avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
-
- if (iBase == pMesh->mNumFaces)
- {
- // have all faces ... finish the outer loop, too
- break;
- }
- }
-
- // delete the per-vertex weight list again
- delete[] avPerVertexWeights;
-
- // now delete the old mesh data
- delete pMesh;
- return;
- }
- avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
- return;
+ if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT)
+ {
+ typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
+
+ // build a per-vertex weight list if necessary
+ VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
+
+ // we need to split this mesh into sub meshes
+ // determine the estimated size of a submesh
+ // (this could be too large. Max waste is a single digit percentage)
+ const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
+ //const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes;
+
+ // create a std::vector<unsigned int> to indicate which vertices
+ // have already been copied
+ std::vector<unsigned int> avWasCopied;
+ avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
+
+ // try to find a good estimate for the number of output faces
+ // per mesh. Add 12.5% as buffer
+ unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
+ iEstimatedSize += iEstimatedSize >> 3;
+
+ // now generate all submeshes
+ unsigned int iBase = 0;
+ while (true)
+ {
+ const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
+
+ aiMesh* pcMesh = new aiMesh;
+ pcMesh->mNumVertices = 0;
+ pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
+
+ // the name carries the adjacency information between the meshes
+ pcMesh->mName = pMesh->mName;
+
+ typedef std::vector<aiVertexWeight> BoneWeightList;
+ if (pMesh->HasBones())
+ {
+ pcMesh->mBones = new aiBone*[pMesh->mNumBones];
+ ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
+ }
+
+ // clear the temporary helper array
+ if (iBase)
+ {
+ // we can't use memset here we unsigned int needn' be 32 bits
+ for (auto &elem : avWasCopied)
+ {
+ elem = 0xffffffff;
+ }
+ }
+
+ // output vectors
+ std::vector<aiFace> vFaces;
+
+ // reserve enough storage for most cases
+ if (pMesh->HasPositions())
+ {
+ pcMesh->mVertices = new aiVector3D[iOutVertexNum];
+ }
+ if (pMesh->HasNormals())
+ {
+ pcMesh->mNormals = new aiVector3D[iOutVertexNum];
+ }
+ if (pMesh->HasTangentsAndBitangents())
+ {
+ pcMesh->mTangents = new aiVector3D[iOutVertexNum];
+ pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
+ }
+ for (unsigned int c = 0; pMesh->HasVertexColors(c);++c)
+ {
+ pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
+ }
+ for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c)
+ {
+ pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
+ pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
+ }
+ vFaces.reserve(iEstimatedSize);
+
+ // (we will also need to copy the array of indices)
+ while (iBase < pMesh->mNumFaces)
+ {
+ // allocate a new array
+ const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
+
+ // doesn't catch degenerates but is quite fast
+ unsigned int iNeed = 0;
+ for (unsigned int v = 0; v < iNumIndices;++v)
+ {
+ unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+ // check whether we do already have this vertex
+ if (0xFFFFFFFF == avWasCopied[iIndex])
+ {
+ iNeed++;
+ }
+ }
+ if (pcMesh->mNumVertices + iNeed > iOutVertexNum)
+ {
+ // don't use this face
+ break;
+ }
+
+ vFaces.push_back(aiFace());
+ aiFace& rFace = vFaces.back();
+
+ // setup face type and number of indices
+ rFace.mNumIndices = iNumIndices;
+ rFace.mIndices = new unsigned int[iNumIndices];
+
+ // need to update the output primitive types
+ switch (rFace.mNumIndices)
+ {
+ case 1:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+ case 2:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+ case 3:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ default:
+ pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+ }
+
+ // and copy the contents of the old array, offset by current base
+ for (unsigned int v = 0; v < iNumIndices;++v)
+ {
+ unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
+
+ // check whether we do already have this vertex
+ if (0xFFFFFFFF != avWasCopied[iIndex])
+ {
+ rFace.mIndices[v] = avWasCopied[iIndex];
+ continue;
+ }
+
+ // copy positions
+ pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
+
+ // copy normals
+ if (pMesh->HasNormals())
+ {
+ pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
+ }
+
+ // copy tangents/bitangents
+ if (pMesh->HasTangentsAndBitangents())
+ {
+ pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
+ pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
+ }
+
+ // texture coordinates
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+ {
+ if (pMesh->HasTextureCoords( c))
+ {
+ pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
+ }
+ }
+ // vertex colors
+ for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
+ {
+ if (pMesh->HasVertexColors( c))
+ {
+ pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
+ }
+ }
+ // check whether we have bone weights assigned to this vertex
+ rFace.mIndices[v] = pcMesh->mNumVertices;
+ if (avPerVertexWeights)
+ {
+ VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
+ if( !table.empty() )
+ {
+ for (VertexWeightTable::const_iterator
+ iter = table.begin();
+ iter != table.end();++iter)
+ {
+ // allocate the bone weight array if necessary
+ BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
+ if (!pcWeightList)
+ {
+ pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
+ }
+ pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
+ }
+ }
+ }
+
+ avWasCopied[iIndex] = pcMesh->mNumVertices;
+ pcMesh->mNumVertices++;
+ }
+ iBase++;
+ if(pcMesh->mNumVertices == iOutVertexNum)
+ {
+ // break here. The face is only added if it was complete
+ break;
+ }
+ }
+
+ // check which bones we'll need to create for this submesh
+ if (pMesh->HasBones())
+ {
+ aiBone** ppCurrent = pcMesh->mBones;
+ for (unsigned int k = 0; k < pMesh->mNumBones;++k)
+ {
+ // check whether the bone is existing
+ BoneWeightList* pcWeightList;
+ if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k]))
+ {
+ aiBone* pcOldBone = pMesh->mBones[k];
+ aiBone* pcOut;
+ *ppCurrent++ = pcOut = new aiBone();
+ pcOut->mName = aiString(pcOldBone->mName);
+ pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
+ pcOut->mNumWeights = (unsigned int)pcWeightList->size();
+ pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights];
+
+ // copy the vertex weights
+ ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
+ pcOut->mNumWeights * sizeof(aiVertexWeight));
+
+ // delete the temporary bone weight list
+ delete pcWeightList;
+ pcMesh->mNumBones++;
+ }
+ }
+ }
+
+ // copy the face list to the mesh
+ pcMesh->mFaces = new aiFace[vFaces.size()];
+ pcMesh->mNumFaces = (unsigned int)vFaces.size();
+
+ for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
+ pcMesh->mFaces[p] = vFaces[p];
+
+ // add the newly created mesh to the list
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
+
+ if (iBase == pMesh->mNumFaces)
+ {
+ // have all faces ... finish the outer loop, too
+ break;
+ }
+ }
+
+ // delete the per-vertex weight list again
+ delete[] avPerVertexWeights;
+
+ // now delete the old mesh data
+ delete pMesh;
+ return;
+ }
+ avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
+ return;
}
diff --git a/src/3rdparty/assimp/code/SplitLargeMeshes.h b/src/3rdparty/assimp/code/SplitLargeMeshes.h
index 68e4540a1..9be27a8f1 100644
--- a/src/3rdparty/assimp/code/SplitLargeMeshes.h
+++ b/src/3rdparty/assimp/code/SplitLargeMeshes.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -46,33 +46,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include "BaseProcess.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/scene.h"
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
class SplitLargeMeshesTest;
+
namespace Assimp
{
-class SplitLargeMeshesProcess_Triangle;
-class SplitLargeMeshesProcess_Vertex;
+class SplitLargeMeshesProcess_Triangle;
+class SplitLargeMeshesProcess_Vertex;
// NOTE: If you change these limits, don't forget to change the
// corresponding values in all Assimp ports
// **********************************************************
-// Java: ConfigProperty.java,
+// Java: ConfigProperty.java,
// ConfigProperty.DEFAULT_VERTEX_SPLIT_LIMIT
// ConfigProperty.DEFAULT_TRIANGLE_SPLIT_LIMIT
// **********************************************************
// default limit for vertices
#if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
-# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+# define AI_SLM_DEFAULT_MAX_VERTICES 1000000
#endif
// default limit for triangles
#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
-# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
#endif
// ---------------------------------------------------------------------------
@@ -83,63 +84,63 @@ class SplitLargeMeshesProcess_Vertex;
*/
class ASSIMP_API SplitLargeMeshesProcess_Triangle : public BaseProcess
{
- friend class SplitLargeMeshesProcess_Vertex;
+ friend class SplitLargeMeshesProcess_Vertex;
public:
- SplitLargeMeshesProcess_Triangle();
- ~SplitLargeMeshesProcess_Triangle();
+ SplitLargeMeshesProcess_Triangle();
+ ~SplitLargeMeshesProcess_Triangle();
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;
+ // -------------------------------------------------------------------
+ /** 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);
+ // -------------------------------------------------------------------
+ /** 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);
- //! Set the split limit - needed for unit testing
- inline void SetLimit(unsigned int l)
- {LIMIT = l;}
+ //! Set the split limit - needed for unit testing
+ inline void SetLimit(unsigned int l)
+ {LIMIT = l;}
- //! Get the split limit
- inline unsigned int GetLimit() const
- {return LIMIT;}
+ //! Get the split limit
+ inline unsigned int GetLimit() const
+ {return LIMIT;}
public:
- // -------------------------------------------------------------------
- /** 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);
+ // -------------------------------------------------------------------
+ /** 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);
- // -------------------------------------------------------------------
- //! Apply the algorithm to a given mesh
- void SplitMesh (unsigned int a, aiMesh* pcMesh,
- std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+ // -------------------------------------------------------------------
+ //! Apply the algorithm to a given mesh
+ void SplitMesh (unsigned int a, aiMesh* pcMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList);
- // -------------------------------------------------------------------
- //! Update a node in the asset after a few of its meshes
- //! have been split
- static void UpdateNode(aiNode* pcNode,
- const std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+ // -------------------------------------------------------------------
+ //! Update a node in the asset after a few of its meshes
+ //! have been split
+ static void UpdateNode(aiNode* pcNode,
+ const std::vector<std::pair<aiMesh*, unsigned int> >& avList);
public:
- //! Triangle limit
- unsigned int LIMIT;
+ //! Triangle limit
+ unsigned int LIMIT;
};
@@ -153,53 +154,53 @@ class ASSIMP_API SplitLargeMeshesProcess_Vertex : public BaseProcess
{
public:
- SplitLargeMeshesProcess_Vertex();
- ~SplitLargeMeshesProcess_Vertex();
+ SplitLargeMeshesProcess_Vertex();
+ ~SplitLargeMeshesProcess_Vertex();
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;
-
- // -------------------------------------------------------------------
- /** 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);
-
-
- //! Set the split limit - needed for unit testing
- inline void SetLimit(unsigned int l)
- {LIMIT = l;}
-
- //! Get the split limit
- inline unsigned int GetLimit() const
- {return LIMIT;}
+ // -------------------------------------------------------------------
+ /** 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;
+
+ // -------------------------------------------------------------------
+ /** 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);
+
+
+ //! Set the split limit - needed for unit testing
+ inline void SetLimit(unsigned int l)
+ {LIMIT = l;}
+
+ //! Get the split limit
+ inline unsigned int GetLimit() const
+ {return LIMIT;}
public:
- // -------------------------------------------------------------------
- /** 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);
+ // -------------------------------------------------------------------
+ /** 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);
- // -------------------------------------------------------------------
- //! Apply the algorithm to a given mesh
- void SplitMesh (unsigned int a, aiMesh* pcMesh,
- std::vector<std::pair<aiMesh*, unsigned int> >& avList);
+ // -------------------------------------------------------------------
+ //! Apply the algorithm to a given mesh
+ void SplitMesh (unsigned int a, aiMesh* pcMesh,
+ std::vector<std::pair<aiMesh*, unsigned int> >& avList);
- // NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode()
+ // NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode()
public:
- //! Triangle limit
- unsigned int LIMIT;
+ //! Triangle limit
+ unsigned int LIMIT;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/StandardShapes.cpp b/src/3rdparty/assimp/code/StandardShapes.cpp
index 5924a20e0..d547c04a7 100644
--- a/src/3rdparty/assimp/code/StandardShapes.cpp
+++ b/src/3rdparty/assimp/code/StandardShapes.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,317 +41,320 @@ 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
+ * The primitive geometry data comes from
* http://geometrictools.com/Documentation/PlatonicSolids.pdf.
*/
-#include "AssimpPCH.h"
#include "StandardShapes.h"
+#include "StringComparison.h"
+#include "Defines.h"
+#include <stddef.h>
+#include <assimp/mesh.h>
+
+namespace Assimp {
-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) \
- }
+ 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 float 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);
- }
+ // assume this to be constant - (fixme: must be 1.0? I think so)
+ const float 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)
+ unsigned int numIndices)
{
- if (positions.size() & numIndices || 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 i = 0; i < numIndices;++i,++a)
- f.mIndices[i] = a;
- }
- out->mNumVertices = (unsigned int)positions.size();
- out->mVertices = new aiVector3D[out->mNumVertices];
- ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
- return out;
+ if (positions.size() & numIndices || 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 i = 0; i < numIndices;++i,++a)
+ f.mIndices[i] = 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>&))
{
- std::vector<aiVector3D> temp;
- unsigned num = (*GenerateFunc)(temp);
- return MakeMesh(temp,num);
+ 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>&, bool))
{
- std::vector<aiVector3D> temp;
- unsigned num = (*GenerateFunc)(temp,true);
- return MakeMesh(temp,num);
+ 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>&))
+ unsigned int,std::vector<aiVector3D>&))
{
- std::vector<aiVector3D> temp;
- (*GenerateFunc)(num,temp);
- return MakeMesh(temp,3);
+ 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);
+ positions.reserve(positions.size()+60);
- const float t = (1.f + 2.236067977f)/2.f;
+ const float t = (1.f + 2.236067977f)/2.f;
const float s = std::sqrt(1.f + t*t);
-
- const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
- const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
- const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s;
- const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s;
- const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s;
- const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s;
- const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s;
- const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s;
- const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s;
- const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s;
- const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s;
- const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/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;
+
+ const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
+ const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
+ const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s;
+ const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s;
+ const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s;
+ const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s;
+ const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s;
+ const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s;
+ const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s;
+ const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s;
+ const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s;
+ const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/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*/)
+ bool polygons /*= false*/)
{
- positions.reserve(positions.size()+108);
+ positions.reserve(positions.size()+108);
- const float a = 1.f / 1.7320508f;
+ const float a = 1.f / 1.7320508f;
const float b = std::sqrt((3.f-2.23606797f)/6.f);
const float c = std::sqrt((3.f+2.23606797f)/6.f);
- 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.f);
- const aiVector3D v9 = aiVector3D(-b,c,0.f);
- const aiVector3D v10 = aiVector3D(b,-c,0.f);
- const aiVector3D v11 = aiVector3D(-b,-c,0.f);
- const aiVector3D v12 = aiVector3D(c, 0.f, b);
- const aiVector3D v13 = aiVector3D(c, 0.f, -b);
- const aiVector3D v14 = aiVector3D(-c, 0.f, b);
- const aiVector3D v15 = aiVector3D(-c, 0.f, -b);
- const aiVector3D v16 = aiVector3D(0.f, b, c);
- const aiVector3D v17 = aiVector3D(0.f, -b, c);
- const aiVector3D v18 = aiVector3D(0.f, b, -c);
- const aiVector3D v19 = aiVector3D(0.f, -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);
+ 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.f);
+ const aiVector3D v9 = aiVector3D(-b,c,0.f);
+ const aiVector3D v10 = aiVector3D(b,-c,0.f);
+ const aiVector3D v11 = aiVector3D(-b,-c,0.f);
+ const aiVector3D v12 = aiVector3D(c, 0.f, b);
+ const aiVector3D v13 = aiVector3D(c, 0.f, -b);
+ const aiVector3D v14 = aiVector3D(-c, 0.f, b);
+ const aiVector3D v15 = aiVector3D(-c, 0.f, -b);
+ const aiVector3D v16 = aiVector3D(0.f, b, c);
+ const aiVector3D v17 = aiVector3D(0.f, -b, c);
+ const aiVector3D v18 = aiVector3D(0.f, b, -c);
+ const aiVector3D v19 = aiVector3D(0.f, -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.0f, 0.f, 0.f) ;
- const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
- const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
- const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
- const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
- const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
-
- 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;
+ positions.reserve(positions.size()+24);
+
+ const aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ;
+ const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
+ const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
+ const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
+ const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
+ const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
+
+ 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);
+ positions.reserve(positions.size()+9);
- const float a = 1.41421f/3.f;
- const float b = 2.4494f/3.f;
+ const float a = 1.41421f/3.f;
+ const float b = 2.4494f/3.f;
- const aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
- const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
- const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
- const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
+ const aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
+ const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
+ const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
+ const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
- ADD_TRIANGLE(v0,v1,v2);
- ADD_TRIANGLE(v0,v2,v3);
- ADD_TRIANGLE(v0,v3,v1);
- ADD_TRIANGLE(v1,v3,v2);
- return 3;
+ 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*/)
+ bool polygons /*= false*/)
{
- positions.reserve(positions.size()+36);
- const float length = 1.f/1.73205080f;
-
- const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
- const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
- const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
- const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
- const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
- const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
- const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
- const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*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);
+ positions.reserve(positions.size()+36);
+ const float length = 1.f/1.73205080f;
+
+ const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
+ const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
+ const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
+ const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
+ const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
+ const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
+ const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
+ const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*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 ...
@@ -361,142 +364,142 @@ unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
// ------------------------------------------------------------------------------------------------
// Create a subdivision sphere
-void StandardShapes::MakeSphere(unsigned int tess,
- std::vector<aiVector3D>& positions)
+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));
+ // 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);
+ // Construct an icosahedron to start with
+ MakeIcosahedron(positions);
- // ... and subdivide it until the requested output
- // tesselation is reached
- for (unsigned int i = 0; i<tess;++i)
- Subdivide(positions);
+ // ... and subdivide it until the requested output
+ // tesselation is reached
+ for (unsigned int i = 0; i<tess;++i)
+ Subdivide(positions);
}
// ------------------------------------------------------------------------------------------------
// Build a cone
void StandardShapes::MakeCone(float height,float radius1,
- float radius2,unsigned int tess,
- std::vector<aiVector3D>& positions,bool bOpen /*= false */)
+ float 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;
+ // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
+ if (tess < 3 || !height)
+ return;
- size_t old = positions.size();
+ size_t old = positions.size();
- // No negative radii
+ // No negative radii
radius1 = std::fabs(radius1);
radius2 = std::fabs(radius2);
- float halfHeight = height / 2;
+ float halfHeight = height / 2;
- // radius1 is always the smaller one
- if (radius2 > radius1)
- {
- std::swap(radius2,radius1);
- halfHeight = -halfHeight;
- }
- else old = SIZE_MAX;
+ // 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-3f)radius1 = 0.f;
+ // Use a large epsilon to check whether the cone is pointy
+ if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f;
- // 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);
+ // 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 float angle_delta = (float)AI_MATH_TWO_PI / tess;
- const float angle_max = (float)AI_MATH_TWO_PI;
+ // Now construct all segments
+ const float angle_delta = (float)AI_MATH_TWO_PI / tess;
+ const float angle_max = (float)AI_MATH_TWO_PI;
- float s = 1.f; // cos(angle == 0);
- float t = 0.f; // sin(angle == 0);
+ float s = 1.f; // std::cos(angle == 0);
+ float t = 0.f; // std::sin(angle == 0);
- for (float angle = 0.f; angle < angle_max; )
- {
- const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
- const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
+ for (float angle = 0.f; angle < angle_max; )
+ {
+ const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
+ const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
- const float next = angle + angle_delta;
+ const float next = angle + angle_delta;
float s2 = std::cos(next);
float 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.f, halfHeight, 0.f));
-
-
- 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.f, -halfHeight, 0.f));
-
- }
- }
- s = s2;
- t = t2;
- angle = next;
- }
-
- // Need to flip face order?
- if ( SIZE_MAX != old ) {
- for (size_t s = old; s < positions.size();s += 3) {
- std::swap(positions[s],positions[s+1]);
- }
- }
+ 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.f, halfHeight, 0.f));
+
+
+ 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.f, -halfHeight, 0.f));
+
+ }
+ }
+ s = s2;
+ t = t2;
+ angle = next;
+ }
+
+ // Need to flip face order?
+ if ( SIZE_MAX != old ) {
+ for (size_t s = old; s < positions.size();s += 3) {
+ std::swap(positions[s],positions[s+1]);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Build a circle
void StandardShapes::MakeCircle(float radius, unsigned int tess,
- std::vector<aiVector3D>& positions)
+ std::vector<aiVector3D>& positions)
{
- // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
- if (tess < 3 || !radius)
- return;
+ // 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);
+ // We will need 3 vertices per segment
+ positions.reserve(positions.size()+tess*3);
- const float angle_delta = (float)AI_MATH_TWO_PI / tess;
- const float angle_max = (float)AI_MATH_TWO_PI;
+ const float angle_delta = (float)AI_MATH_TWO_PI / tess;
+ const float angle_max = (float)AI_MATH_TWO_PI;
- float s = 1.f; // cos(angle == 0);
- float t = 0.f; // sin(angle == 0);
+ float s = 1.f; // std::cos(angle == 0);
+ float t = 0.f; // std::sin(angle == 0);
- for (float angle = 0.f; angle < angle_max; )
- {
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
- angle += angle_delta;
+ for (float angle = 0.f; angle < angle_max; )
+ {
+ positions.push_back(aiVector3D(s * radius,0.f,t * radius));
+ angle += angle_delta;
s = std::cos(angle);
t = std::sin(angle);
- positions.push_back(aiVector3D(s * radius,0.f,t * radius));
+ positions.push_back(aiVector3D(s * radius,0.f,t * radius));
- positions.push_back(aiVector3D(0.f,0.f,0.f));
- }
+ positions.push_back(aiVector3D(0.f,0.f,0.f));
+ }
}
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/StandardShapes.h b/src/3rdparty/assimp/code/StandardShapes.h
index cadce2b96..ec53ca30d 100644
--- a/src/3rdparty/assimp/code/StandardShapes.h
+++ b/src/3rdparty/assimp/code/StandardShapes.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,10 +44,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_STANDARD_SHAPES_H_INC
#define AI_STANDARD_SHAPES_H_INC
+#include <assimp/vector3.h>
#include <vector>
+struct aiMesh;
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
/** \brief Helper class to generate vertex buffers for standard geometric
@@ -55,141 +57,141 @@ namespace Assimp {
*/
class StandardShapes
{
- // class cannot be instanced
- StandardShapes() {}
+ // class cannot be instanced
+ StandardShapes() {}
public:
- // ----------------------------------------------------------------
- /** Generates a mesh from an array of vertex positions.
- *
- * @param positions List of vertex positions
- * @param numIndices Number of indices per primitive
- * @return Output mesh
- */
- static aiMesh* MakeMesh(const std::vector<aiVector3D>& positions,
- unsigned int numIndices);
-
-
- static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
- (std::vector<aiVector3D>&));
-
- static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
- (std::vector<aiVector3D>&, bool));
-
- static aiMesh* MakeMesh ( unsigned int n, void (*GenerateFunc)
- (unsigned int,std::vector<aiVector3D>&));
-
- // ----------------------------------------------------------------
- /** @brief Generates a hexahedron (cube)
- *
- * Hexahedrons can be scaled on all axes.
- * @param positions Receives output triangles.
- * @param polygons If you pass true here quads will be returned
- * @return Number of vertices per face
- */
- static unsigned int MakeHexahedron(
- std::vector<aiVector3D>& positions,
- bool polygons = false);
-
- // ----------------------------------------------------------------
- /** @brief Generates an icosahedron
- *
- * @param positions Receives output triangles.
- * @return Number of vertices per face
- */
- static unsigned int MakeIcosahedron(
- std::vector<aiVector3D>& positions);
-
-
- // ----------------------------------------------------------------
- /** @brief Generates a dodecahedron
- *
- * @param positions Receives output triangles
- * @param polygons If you pass true here pentagons will be returned
- * @return Number of vertices per face
- */
- static unsigned int MakeDodecahedron(
- std::vector<aiVector3D>& positions,
- bool polygons = false);
-
-
- // ----------------------------------------------------------------
- /** @brief Generates an octahedron
- *
- * @param positions Receives output triangles.
- * @return Number of vertices per face
- */
- static unsigned int MakeOctahedron(
- std::vector<aiVector3D>& positions);
-
-
- // ----------------------------------------------------------------
- /** @brief Generates a tetrahedron
- *
- * @param positions Receives output triangles.
- * @return Number of vertices per face
- */
- static unsigned int MakeTetrahedron(
- std::vector<aiVector3D>& positions);
-
-
-
- // ----------------------------------------------------------------
- /** @brief Generates a sphere
- *
- * @param tess Number of subdivions - 0 generates a octahedron
- * @param positions Receives output triangles.
- */
- static void MakeSphere(unsigned int tess,
- std::vector<aiVector3D>& positions);
-
-
- // ----------------------------------------------------------------
- /** @brief Generates a cone or a cylinder, either open or closed.
- *
- * @code
- *
- * |-----| <- radius 1
- *
- * __x__ <- ] ^
- * / \ | height |
- * / \ | Y
- * / \ |
- * / \ |
- * /______x______\ <- ] <- end cap
- *
- * |-------------| <- radius 2
- *
- * @endcode
- *
- * @param height Height of the cone
- * @param radius1 First radius
- * @param radius2 Second radius
- * @param tess Number of triangles.
- * @param bOpened true for an open cone/cylinder. An open shape has
- * no 'end caps'
- * @param positions Receives output triangles
- */
- static void MakeCone(float height,float radius1,
- float radius2,unsigned int tess,
- std::vector<aiVector3D>& positions,bool bOpen= false);
-
-
- // ----------------------------------------------------------------
- /** @brief Generates a flat circle
- *
- * The circle is constructed in the planed formed by the x,z
- * axes of the cartesian coordinate system.
- *
- * @param radius Radius of the circle
- * @param tess Number of segments.
- * @param positions Receives output triangles.
- */
- static void MakeCircle(float radius, unsigned int tess,
- std::vector<aiVector3D>& positions);
-
+ // ----------------------------------------------------------------
+ /** Generates a mesh from an array of vertex positions.
+ *
+ * @param positions List of vertex positions
+ * @param numIndices Number of indices per primitive
+ * @return Output mesh
+ */
+ static aiMesh* MakeMesh(const std::vector<aiVector3D>& positions,
+ unsigned int numIndices);
+
+
+ static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
+ (std::vector<aiVector3D>&));
+
+ static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
+ (std::vector<aiVector3D>&, bool));
+
+ static aiMesh* MakeMesh ( unsigned int n, void (*GenerateFunc)
+ (unsigned int,std::vector<aiVector3D>&));
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a hexahedron (cube)
+ *
+ * Hexahedrons can be scaled on all axes.
+ * @param positions Receives output triangles.
+ * @param polygons If you pass true here quads will be returned
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeHexahedron(
+ std::vector<aiVector3D>& positions,
+ bool polygons = false);
+
+ // ----------------------------------------------------------------
+ /** @brief Generates an icosahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeIcosahedron(
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a dodecahedron
+ *
+ * @param positions Receives output triangles
+ * @param polygons If you pass true here pentagons will be returned
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeDodecahedron(
+ std::vector<aiVector3D>& positions,
+ bool polygons = false);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates an octahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeOctahedron(
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a tetrahedron
+ *
+ * @param positions Receives output triangles.
+ * @return Number of vertices per face
+ */
+ static unsigned int MakeTetrahedron(
+ std::vector<aiVector3D>& positions);
+
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a sphere
+ *
+ * @param tess Number of subdivions - 0 generates a octahedron
+ * @param positions Receives output triangles.
+ */
+ static void MakeSphere(unsigned int tess,
+ std::vector<aiVector3D>& positions);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a cone or a cylinder, either open or closed.
+ *
+ * @code
+ *
+ * |-----| <- radius 1
+ *
+ * __x__ <- ] ^
+ * / \ | height |
+ * / \ | Y
+ * / \ |
+ * / \ |
+ * /______x______\ <- ] <- end cap
+ *
+ * |-------------| <- radius 2
+ *
+ * @endcode
+ *
+ * @param height Height of the cone
+ * @param radius1 First radius
+ * @param radius2 Second radius
+ * @param tess Number of triangles.
+ * @param bOpened true for an open cone/cylinder. An open shape has
+ * no 'end caps'
+ * @param positions Receives output triangles
+ */
+ static void MakeCone(float height,float radius1,
+ float radius2,unsigned int tess,
+ std::vector<aiVector3D>& positions,bool bOpen= false);
+
+
+ // ----------------------------------------------------------------
+ /** @brief Generates a flat circle
+ *
+ * The circle is constructed in the planned formed by the x,z
+ * axes of the cartesian coordinate system.
+ *
+ * @param radius Radius of the circle
+ * @param tess Number of segments.
+ * @param positions Receives output triangles.
+ */
+ static void MakeCircle(float radius, unsigned int tess,
+ std::vector<aiVector3D>& positions);
+
};
} // ! Assimp
diff --git a/src/3rdparty/assimp/code/StdOStreamLogStream.h b/src/3rdparty/assimp/code/StdOStreamLogStream.h
index 37b6331f6..20482fef7 100644
--- a/src/3rdparty/assimp/code/StdOStreamLogStream.h
+++ b/src/3rdparty/assimp/code/StdOStreamLogStream.h
@@ -1,52 +1,92 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
#ifndef AI_STROSTREAMLOGSTREAM_H_INC
#define AI_STROSTREAMLOGSTREAM_H_INC
-#include "../include/assimp/LogStream.hpp"
+#include <assimp/LogStream.hpp>
#include <ostream>
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
-/** @class StdOStreamLogStream
- * @brief Logs into a std::ostream
+/** @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
- */
- StdOStreamLogStream(std::ostream& _ostream);
-
- /** @brief Destructor */
- ~StdOStreamLogStream();
-
- /** @brief Writer */
- void write(const char* message);
+ /** @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& ostream;
+ std::ostream& ostream;
};
// ---------------------------------------------------------------------------
-// Default constructor
+// Default constructor
inline StdOStreamLogStream::StdOStreamLogStream(std::ostream& _ostream)
- : ostream (_ostream)
+ : ostream (_ostream)
{}
// ---------------------------------------------------------------------------
-// Default constructor
+// Default constructor
inline StdOStreamLogStream::~StdOStreamLogStream()
{}
// ---------------------------------------------------------------------------
-// Write method
+// Write method
inline void StdOStreamLogStream::write(const char* message)
{
- ostream << message;
- ostream.flush();
+ ostream << message;
+ ostream.flush();
}
// ---------------------------------------------------------------------------
-} // Namespace Assimp
+} // Namespace Assimp
#endif // guard
diff --git a/src/3rdparty/assimp/code/StepExporter.cpp b/src/3rdparty/assimp/code/StepExporter.cpp
new file mode 100644
index 000000000..eb84ac594
--- /dev/null
+++ b/src/3rdparty/assimp/code/StepExporter.cpp
@@ -0,0 +1,370 @@
+/*
+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.
+
+@author: Richard Steffen, 2015
+----------------------------------------------------------------------
+*/
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+#include "StepExporter.h"
+#include "ConvertToLHProcess.h"
+#include "Bitmap.h"
+#include "BaseImporter.h"
+#include "fast_atof.h"
+#include "SceneCombiner.h"
+#include "DefaultIOSystem.h"
+#include <iostream>
+#include <ctime>
+#include <set>
+#include <map>
+#include <list>
+#include <memory>
+#include "Exceptional.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/light.h>
+
+//
+#if _MSC_VER > 1500 || (defined __GNUC___)
+# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
+# else
+# define step_unordered_map map
+# define step_unordered_multimap multimap
+#endif
+
+#ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP
+# include <unordered_map>
+# if _MSC_VER > 1600
+# define step_unordered_map unordered_map
+# define step_unordered_multimap unordered_multimap
+# else
+# define step_unordered_map tr1::unordered_map
+# define step_unordered_multimap tr1::unordered_multimap
+# endif
+#endif
+
+typedef std::step_unordered_map<aiVector3D*, int> VectorIndexUMap;
+
+/* Tested with Step viewer v4 from www.ida-step.net */
+
+using namespace Assimp;
+
+namespace Assimp
+{
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
+void ExportSceneStep(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+ std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
+
+ // create/copy Properties
+ ExportProperties props(*pProperties);
+
+ // invoke the exporter
+ StepExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
+
+ // we're still here - export successfully completed. Write result to the given IOSYstem
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .stp file: " + std::string(pFile));
+ }
+
+ // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
+ outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
+}
+
+} // end of namespace Assimp
+
+
+namespace {
+ // Collect world transformations for each node
+ void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
+ const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
+ trafos[node] = parent * node->mTransformation;
+ for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+ CollectTrafos(node->mChildren[i], trafos);
+ }
+ }
+
+ // Generate a flat list of the meshes (by index) assigned to each node
+ void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
+ for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+ meshes.insert(std::make_pair(node, node->mMeshes[i]));
+ }
+ for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+ CollectMeshes(node->mChildren[i], meshes);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Constructor for a specific scene to export
+StepExporter::StepExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path,
+ const std::string& file, const ExportProperties* pProperties):
+ mProperties(pProperties),mIOSystem(pIOSystem),mFile(file), mPath(path),
+ mScene(pScene), endstr(";\n") {
+ CollectTrafos(pScene->mRootNode, trafos);
+ CollectMeshes(pScene->mRootNode, meshes);
+
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ mOutput.imbue( std::locale("C") );
+ mOutput.precision(16);
+
+ // start writing
+ WriteFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Starts writing the contents
+void StepExporter::WriteFile()
+{
+ // see http://shodhganga.inflibnet.ac.in:8080/jspui/bitstream/10603/14116/11/11_chapter%203.pdf
+ // note, that all realnumber values must be comma separated in x files
+ mOutput.setf(std::ios::fixed);
+ // precission for double
+ // see http://stackoverflow.com/questions/554063/how-do-i-print-a-double-value-with-full-precision-using-cout
+ mOutput.precision(16);
+
+ // standard color
+ aiColor4D fColor;
+ fColor.r = 0.8f;
+ fColor.g = 0.8f;
+ fColor.b = 0.8f;
+
+ int ind = 100; // the start index to be used
+ int faceEntryLen = 30; // number of entries for a triangle/face
+ // prepare unique (count triangles and vertices)
+
+ VectorIndexUMap uniqueVerts; // use a map to reduce find complexity to log(n)
+ VectorIndexUMap::iterator it;
+ int countFace = 0;
+
+ for (unsigned int i=0; i<mScene->mNumMeshes; ++i)
+ {
+ aiMesh* mesh = mScene->mMeshes[i];
+ for (unsigned int j=0; j<mesh->mNumFaces; ++j)
+ {
+ aiFace* face = &(mesh->mFaces[j]);
+
+ if (face->mNumIndices == 3) countFace++;
+ }
+ for (unsigned int j=0; j<mesh->mNumVertices; ++j)
+ {
+ aiVector3D* v = &(mesh->mVertices[j]);
+ it =uniqueVerts.find(v);
+ if (it == uniqueVerts.end())
+ {
+ uniqueVerts[v] = -1; // first mark the vector as not transformed
+ }
+ }
+ }
+
+ static const unsigned int date_nb_chars = 20;
+ char date_str[date_nb_chars];
+ std::time_t date = std::time(NULL);
+ std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
+
+ // write the header
+ mOutput << "ISO-10303-21" << endstr;
+ mOutput << "HEADER" << endstr;
+ mOutput << "FILE_DESCRIPTION(('STEP AP214'),'1')" << endstr;
+ mOutput << "FILE_NAME('" << mFile << ".stp','" << date_str << "',(' '),(' '),'Spatial InterOp 3D',' ',' ')" << endstr;
+ mOutput << "FILE_SCHEMA(('automotive_design'))" << endstr;
+ mOutput << "ENDSEC" << endstr;
+
+ // write the top of data
+ mOutput << "DATA" << endstr;
+ mOutput << "#1=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION(' ',(";
+ for (int i=0; i<countFace; ++i)
+ {
+ mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size();
+ if (i!=countFace-1) mOutput << ",";
+ }
+ mOutput << "),#6)" << endstr;
+
+ mOutput << "#2=PRODUCT_DEFINITION_CONTEXT('',#7,'design')" << endstr;
+ mOutput << "#3=APPLICATION_PROTOCOL_DEFINITION('INTERNATIONAL STANDARD','automotive_design',1994,#7)" << endstr;
+ mOutput << "#4=PRODUCT_CATEGORY_RELATIONSHIP('NONE','NONE',#8,#9)" << endstr;
+ mOutput << "#5=SHAPE_DEFINITION_REPRESENTATION(#10,#11)" << endstr;
+ mOutput << "#6= (GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#12))GLOBAL_UNIT_ASSIGNED_CONTEXT((#13,#14,#15))REPRESENTATION_CONTEXT('NONE','WORKSPACE'))" << endstr;
+ mOutput << "#7=APPLICATION_CONTEXT(' ')" << endstr;
+ mOutput << "#8=PRODUCT_CATEGORY('part','NONE')" << endstr;
+ mOutput << "#9=PRODUCT_RELATED_PRODUCT_CATEGORY('detail',' ',(#17))" << endstr;
+ mOutput << "#10=PRODUCT_DEFINITION_SHAPE('NONE','NONE',#18)" << endstr;
+ mOutput << "#11=MANIFOLD_SURFACE_SHAPE_REPRESENTATION('Root',(#16,#19),#6)" << endstr;
+ mOutput << "#12=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.0E-006),#13,'','')" << endstr;
+ mOutput << "#13=(CONVERSION_BASED_UNIT('METRE',#20)LENGTH_UNIT()NAMED_UNIT(#21))" << endstr;
+ mOutput << "#14=(NAMED_UNIT(#22)PLANE_ANGLE_UNIT()SI_UNIT($,.RADIAN.))" << endstr;
+ mOutput << "#15=(NAMED_UNIT(#22)SOLID_ANGLE_UNIT()SI_UNIT($,.STERADIAN.))" << endstr;
+ mOutput << "#16=SHELL_BASED_SURFACE_MODEL('Root',(#29))" << endstr;
+ mOutput << "#17=PRODUCT('Root','Root','Root',(#23))" << endstr;
+ mOutput << "#18=PRODUCT_DEFINITION('NONE','NONE',#24,#2)" << endstr;
+ mOutput << "#19=AXIS2_PLACEMENT_3D('',#25,#26,#27)" << endstr;
+ mOutput << "#20=LENGTH_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.0),#28)" << endstr;
+ mOutput << "#21=DIMENSIONAL_EXPONENTS(1.0,0.0,0.0,0.0,0.0,0.0,0.0)" << endstr;
+ mOutput << "#22=DIMENSIONAL_EXPONENTS(0.0,0.0,0.0,0.0,0.0,0.0,0.0)" << endstr;
+ mOutput << "#23=PRODUCT_CONTEXT('',#7,'mechanical')" << endstr;
+ mOutput << "#24=PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE(' ','NONE',#17,.NOT_KNOWN.)" << endstr;
+ mOutput << "#25=CARTESIAN_POINT('',(0.0,0.0,0.0))" << endstr;
+ mOutput << "#26=DIRECTION('',(0.0,0.0,1.0))" << endstr;
+ mOutput << "#27=DIRECTION('',(1.0,0.0,0.0))" << endstr;
+ mOutput << "#28= (NAMED_UNIT(#21)LENGTH_UNIT()SI_UNIT(.MILLI.,.METRE.))" << endstr;
+ mOutput << "#29=CLOSED_SHELL('',(";
+ for (int i=0; i<countFace; ++i)
+ {
+ mOutput << "#" << i*faceEntryLen + ind + 2*uniqueVerts.size() + 8;
+ if (i!=countFace-1) mOutput << ",";
+ }
+ mOutput << "))" << endstr;
+
+ // write all the unique transformed CARTESIAN and VERTEX
+ for (MeshesByNodeMap::const_iterator it2 = meshes.begin(); it2 != meshes.end(); ++it2)
+ {
+ const aiNode& node = *(*it2).first;
+ unsigned int mesh_idx = (*it2).second;
+
+ const aiMesh* mesh = mScene->mMeshes[mesh_idx];
+ aiMatrix4x4& trafo = trafos[&node];
+ for (unsigned int i = 0; i < mesh->mNumVertices; ++i)
+ {
+ aiVector3D* v = &(mesh->mVertices[i]);
+ it = uniqueVerts.find(v);
+ if (it->second >=0 ) continue;
+ it->second = ind; // this one is new, so set the index (ind)
+ aiVector3D vt = trafo * (*v); // transform the coordinate
+ mOutput << "#" << it->second << "=CARTESIAN_POINT('',(" << vt.x << "," << vt.y << "," << vt.z << "))" << endstr;
+ mOutput << "#" << it->second+1 << "=VERTEX_POINT('',#" << it->second << ")" << endstr;
+ ind += 2;
+ }
+ }
+
+ // write the triangles
+ for (unsigned int i=0; i<mScene->mNumMeshes; ++i)
+ {
+ aiMesh* mesh = mScene->mMeshes[i];
+ for (unsigned int j=0; j<mesh->mNumFaces; ++j)
+ {
+ aiFace* face = &(mesh->mFaces[j]);
+
+ if (face->mNumIndices != 3) continue;
+
+ aiVector3D* v1 = &(mesh->mVertices[face->mIndices[0]]);
+ aiVector3D* v2 = &(mesh->mVertices[face->mIndices[1]]);
+ aiVector3D* v3 = &(mesh->mVertices[face->mIndices[2]]);
+ aiVector3D dv12 = *v2 - *v1;
+ aiVector3D dv23 = *v3 - *v2;
+ aiVector3D dv31 = *v1 - *v3;
+ aiVector3D dv13 = *v3 - *v1;
+ dv12.Normalize();
+ dv23.Normalize();
+ dv31.Normalize();
+ dv13.Normalize();
+
+ int pid1 = uniqueVerts.find(v1)->second;
+ int pid2 = uniqueVerts.find(v2)->second;
+ int pid3 = uniqueVerts.find(v3)->second;
+
+ // mean vertex color for the face if available
+ if (mesh->HasVertexColors(0))
+ {
+ fColor.r = 0.0;
+ fColor.g = 0.0;
+ fColor.b = 0.0;
+ fColor += mesh->mColors[0][face->mIndices[0]];
+ fColor += mesh->mColors[0][face->mIndices[1]];
+ fColor += mesh->mColors[0][face->mIndices[2]];
+ fColor /= 3.0f;
+ }
+
+ int sid = ind; // the sub index
+ mOutput << "#" << sid << "=STYLED_ITEM('',(#" << sid+1 << "),#" << sid+8 << ")" << endstr; /* the item that must be referenced in #1 */
+ /* This is the color information of the Triangle */
+ mOutput << "#" << sid+1 << "=PRESENTATION_STYLE_ASSIGNMENT((#" << sid+2 << "))" << endstr;
+ mOutput << "#" << sid+2 << "=SURFACE_STYLE_USAGE(.BOTH.,#" << sid+3 << ")" << endstr;
+ mOutput << "#" << sid+3 << "=SURFACE_SIDE_STYLE('',(#" << sid+4 << "))" << endstr;
+ mOutput << "#" << sid+4 << "=SURFACE_STYLE_FILL_AREA(#" << sid+5 << ")" << endstr;
+ mOutput << "#" << sid+5 << "=FILL_AREA_STYLE('',(#" << sid+6 << "))" << endstr;
+ mOutput << "#" << sid+6 << "=FILL_AREA_STYLE_COLOUR('',#" << sid+7 << ")" << endstr;
+ mOutput << "#" << sid+7 << "=COLOUR_RGB(''," << fColor.r << "," << fColor.g << "," << fColor.b << ")" << endstr;
+
+ /* this is the geometry */
+ mOutput << "#" << sid+8 << "=FACE_SURFACE('',(#" << sid+13 << "),#" << sid+9<< ",.T.)" << endstr; /* the face that must be referenced in 29 */
+
+ /* 2 directions of the plane */
+ mOutput << "#" << sid+9 << "=PLANE('',#" << sid+10 << ")" << endstr;
+ mOutput << "#" << sid+10 << "=AXIS2_PLACEMENT_3D('',#" << pid1 << ", #" << sid+11 << ",#" << sid+12 << ")" << endstr;
+
+ mOutput << "#" << sid+11 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
+ mOutput << "#" << sid+12 << "=DIRECTION('',(" << dv13.x << "," << dv13.y << "," << dv13.z << "))" << endstr;
+
+ mOutput << "#" << sid+13 << "=FACE_BOUND('',#" << sid+14 << ",.T.)" << endstr;
+ mOutput << "#" << sid+14 << "=EDGE_LOOP('',(#" << sid+15 << ",#" << sid+16 << ",#" << sid+17 << "))" << endstr;
+
+ /* edge loop */
+ mOutput << "#" << sid+15 << "=ORIENTED_EDGE('',*,*,#" << sid+18 << ",.T.)" << endstr;
+ mOutput << "#" << sid+16 << "=ORIENTED_EDGE('',*,*,#" << sid+19 << ",.T.)" << endstr;
+ mOutput << "#" << sid+17 << "=ORIENTED_EDGE('',*,*,#" << sid+20 << ",.T.)" << endstr;
+
+ /* oriented edges */
+ mOutput << "#" << sid+18 << "=EDGE_CURVE('',#" << pid1+1 << ",#" << pid2+1 << ",#" << sid+21 << ",.F.)" << endstr;
+ mOutput << "#" << sid+19 << "=EDGE_CURVE('',#" << pid2+1 << ",#" << pid3+1 << ",#" << sid+22 << ",.T.)" << endstr;
+ mOutput << "#" << sid+20 << "=EDGE_CURVE('',#" << pid3+1 << ",#" << pid1+1 << ",#" << sid+23 << ",.T.)" << endstr;
+
+ /* 3 lines and 3 vectors for the lines for the 3 edge curves */
+ mOutput << "#" << sid+21 << "=LINE('',#" << pid1 << ",#" << sid+24 << ")" << endstr;
+ mOutput << "#" << sid+22 << "=LINE('',#" << pid2 << ",#" << sid+25 << ")" << endstr;
+ mOutput << "#" << sid+23 << "=LINE('',#" << pid3 << ",#" << sid+26 << ")" << endstr;
+ mOutput << "#" << sid+24 << "=VECTOR('',#" << sid+27 << ",1.0)" << endstr;
+ mOutput << "#" << sid+25 << "=VECTOR('',#" << sid+28 << ",1.0)" << endstr;
+ mOutput << "#" << sid+26 << "=VECTOR('',#" << sid+29 << ",1.0)" << endstr;
+ mOutput << "#" << sid+27 << "=DIRECTION('',(" << dv12.x << "," << dv12.y << "," << dv12.z << "))" << endstr;
+ mOutput << "#" << sid+28 << "=DIRECTION('',(" << dv23.x << "," << dv23.y << "," << dv23.z << "))" << endstr;
+ mOutput << "#" << sid+29 << "=DIRECTION('',(" << dv31.x << "," << dv31.y << "," << dv31.z << "))" << endstr;
+ ind += faceEntryLen; // increase counter
+ }
+ }
+
+ mOutput << "ENDSEC" << endstr; // end of data section
+ mOutput << "END-ISO-10303-21" << endstr; // end of file
+}
+
+#endif
+#endif
diff --git a/src/3rdparty/assimp/code/StepExporter.h b/src/3rdparty/assimp/code/StepExporter.h
new file mode 100644
index 000000000..b51280c6c
--- /dev/null
+++ b/src/3rdparty/assimp/code/StepExporter.h
@@ -0,0 +1,109 @@
+/*
+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.
+
+@author: Richard Steffen, 2014
+
+----------------------------------------------------------------------
+*/
+
+/** @file StepExporter.h
+ * Declares the exporter class to write a scene to a Collada file
+ */
+#ifndef AI_STEPEXPORTER_H_INC
+#define AI_STEPEXPORTER_H_INC
+
+#include <assimp/ai_assert.h>
+#include <assimp/matrix4x4.h>
+#include <assimp/Exporter.hpp>
+#include <sstream>
+
+
+struct aiScene;
+struct aiNode;
+
+namespace Assimp
+{
+
+/// Helper class to export a given scene to a StepFile.
+/// Note: an StepFile uses a left hand system. Assimp used a right hand system (OpenGL), therefore we have to transform everything
+class StepExporter
+{
+public:
+ /// Constructor for a specific scene to export
+ StepExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties);
+
+protected:
+ /// Starts writing the contents
+ void WriteFile();
+
+public:
+
+ /// Stringstream to write all output into
+ std::stringstream mOutput;
+
+protected:
+
+ /// hold the properties pointer
+ const ExportProperties* mProperties;
+
+ /// The IOSystem for output
+ IOSystem* mIOSystem;
+
+ /// Name of the file (without extension) where the scene will be exported
+ std::string mFile;
+
+ /// Path of the directory where the scene will be exported
+ std::string mPath;
+
+ /// The scene to be written
+ const aiScene* mScene;
+
+ /// current line end string for simple stream insertion
+ std::string endstr;
+
+ /// accumultated transformations for nodes
+ std::map<const aiNode*, aiMatrix4x4> trafos;
+
+ /// map to all meshed of nodes
+ typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+ MeshesByNodeMap meshes;
+
+};
+
+}
+
+#endif // !! AI_STEPEXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/StreamReader.h b/src/3rdparty/assimp/code/StreamReader.h
index 73467943b..244ad9784 100644
--- a/src/3rdparty/assimp/code/StreamReader.h
+++ b/src/3rdparty/assimp/code/StreamReader.h
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,37 +25,41 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Defines the StreamReader class which reads data from
- * a binary stream with a well-defined endianess. */
+ * a binary stream with a well-defined endianness. */
#ifndef AI_STREAMREADER_H_INCLUDED
#define AI_STREAMREADER_H_INCLUDED
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
+#include "Exceptional.h"
+#include <memory>
+#include <assimp/IOStream.hpp>
+#include "Defines.h"
namespace Assimp {
// --------------------------------------------------------------------------------------------
-/** Wrapper class around IOStream to allow for consistent reading of binary data in both
- * little and big endian format. Don't attempt to instance the template directly. Use
- * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a
- * BE stream. The class expects that the endianess of any input data is known at
+/** Wrapper class around IOStream to allow for consistent reading of binary data in both
+ * little and big endian format. Don't attempt to instance the template directly. Use
+ * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a
+ * BE stream. The class expects that the endianness of any input data is known at
* compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements
- * runtime endianess conversions for text files).
+ * runtime endianness conversions for text files).
*
* XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/
// --------------------------------------------------------------------------------------------
@@ -65,288 +69,290 @@ class StreamReader
public:
- // FIXME: use these data types throughout the whole library,
- // then change them to 64 bit values :-)
-
- typedef int diff;
- typedef unsigned int pos;
+ // FIXME: use these data types throughout the whole library,
+ // then change them to 64 bit values :-)
+
+ typedef int diff;
+ typedef unsigned int pos;
public:
- // ---------------------------------------------------------------------
- /** Construction from a given stream with a well-defined endianess.
- *
- * The StreamReader holds a permanent strong reference to the
- * stream, which is released upon destruction.
- * @param stream Input stream. The stream is not restarted if
- * its file pointer is not at 0. Instead, the stream reader
- * reads from the current position to the end of the stream.
- * @param le If @c RuntimeSwitch is true: specifies whether the
- * stream is in little endian byte order. Otherwise the
- * endianess information is contained in the @c SwapEndianess
- * template parameter and this parameter is meaningless. */
- StreamReader(boost::shared_ptr<IOStream> stream, bool le = false)
- : stream(stream)
- , le(le)
- {
- ai_assert(stream);
- InternBegin();
- }
-
- // ---------------------------------------------------------------------
- StreamReader(IOStream* stream, bool le = false)
- : stream(boost::shared_ptr<IOStream>(stream))
- , le(le)
- {
- ai_assert(stream);
- InternBegin();
- }
-
- // ---------------------------------------------------------------------
- ~StreamReader() {
- delete[] buffer;
- }
+ // ---------------------------------------------------------------------
+ /** Construction from a given stream with a well-defined endianness.
+ *
+ * The StreamReader holds a permanent strong reference to the
+ * stream, which is released upon destruction.
+ * @param stream Input stream. The stream is not restarted if
+ * its file pointer is not at 0. Instead, the stream reader
+ * reads from the current position to the end of the stream.
+ * @param le If @c RuntimeSwitch is true: specifies whether the
+ * stream is in little endian byte order. Otherwise the
+ * endianness information is contained in the @c SwapEndianess
+ * template parameter and this parameter is meaningless. */
+ StreamReader(std::shared_ptr<IOStream> stream, bool le = false)
+ : stream(stream)
+ , le(le)
+ {
+ ai_assert(stream);
+ InternBegin();
+ }
+
+ // ---------------------------------------------------------------------
+ StreamReader(IOStream* stream, bool le = false)
+ : stream(std::shared_ptr<IOStream>(stream))
+ , le(le)
+ {
+ ai_assert(stream);
+ InternBegin();
+ }
+
+ // ---------------------------------------------------------------------
+ ~StreamReader() {
+ delete[] buffer;
+ }
public:
- // deprecated, use overloaded operator>> instead
-
- // ---------------------------------------------------------------------
- /** Read a float from the stream */
- float GetF4()
- {
- return Get<float>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a double from the stream */
- double GetF8() {
- return Get<double>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a signed 16 bit integer from the stream */
- int16_t GetI2() {
- return Get<int16_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a signed 8 bit integer from the stream */
- int8_t GetI1() {
- return Get<int8_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read an signed 32 bit integer from the stream */
- int32_t GetI4() {
- return Get<int32_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a signed 64 bit integer from the stream */
- int64_t GetI8() {
- return Get<int64_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a unsigned 16 bit integer from the stream */
- uint16_t GetU2() {
- return Get<uint16_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a unsigned 8 bit integer from the stream */
- uint8_t GetU1() {
- return Get<uint8_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read an unsigned 32 bit integer from the stream */
- uint32_t GetU4() {
- return Get<uint32_t>();
- }
-
- // ---------------------------------------------------------------------
- /** Read a unsigned 64 bit integer from the stream */
- uint64_t GetU8() {
- return Get<uint64_t>();
- }
+ // deprecated, use overloaded operator>> instead
+
+ // ---------------------------------------------------------------------
+ /** Read a float from the stream */
+ float GetF4()
+ {
+ return Get<float>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a double from the stream */
+ double GetF8() {
+ return Get<double>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 16 bit integer from the stream */
+ int16_t GetI2() {
+ return Get<int16_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 8 bit integer from the stream */
+ int8_t GetI1() {
+ return Get<int8_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read an signed 32 bit integer from the stream */
+ int32_t GetI4() {
+ return Get<int32_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a signed 64 bit integer from the stream */
+ int64_t GetI8() {
+ return Get<int64_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 16 bit integer from the stream */
+ uint16_t GetU2() {
+ return Get<uint16_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 8 bit integer from the stream */
+ uint8_t GetU1() {
+ return Get<uint8_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read an unsigned 32 bit integer from the stream */
+ uint32_t GetU4() {
+ return Get<uint32_t>();
+ }
+
+ // ---------------------------------------------------------------------
+ /** Read a unsigned 64 bit integer from the stream */
+ uint64_t GetU8() {
+ return Get<uint64_t>();
+ }
public:
- // ---------------------------------------------------------------------
- /** Get the remaining stream size (to the end of the srream) */
- unsigned int GetRemainingSize() const {
- return (unsigned int)(end - current);
- }
-
-
- // ---------------------------------------------------------------------
- /** Get the remaining stream size (to the current read limit). The
- * return value is the remaining size of the stream if no custom
- * read limit has been set. */
- unsigned int GetRemainingSizeToLimit() const {
- return (unsigned int)(limit - current);
- }
-
-
- // ---------------------------------------------------------------------
- /** Increase the file pointer (relative seeking) */
- void IncPtr(size_t plus) {
- current += plus;
- if (current > limit) {
- throw DeadlyImportError("End of file or read limit was reached");
- }
- }
-
- // ---------------------------------------------------------------------
- /** Get the current file pointer */
- int8_t* GetPtr() const {
- return current;
- }
-
-
- // ---------------------------------------------------------------------
- /** Set current file pointer (Get it from #GetPtr). This is if you
- * prefer to do pointer arithmetics on your own or want to copy
- * large chunks of data at once.
- * @param p The new pointer, which is validated against the size
- * limit and buffer boundaries. */
- void SetPtr(int8_t* p) {
-
- current = p;
- if (current > limit || current < buffer) {
- throw DeadlyImportError("End of file or read limit was reached");
- }
- }
-
- // ---------------------------------------------------------------------
- /** Copy n bytes to an external buffer
- * @param out Destination for copying
- * @param bytes Number of bytes to copy */
- void CopyAndAdvance(void* out, size_t bytes) {
-
- int8_t* ur = GetPtr();
- SetPtr(ur+bytes); // fire exception if eof
-
- memcpy(out,ur,bytes);
- }
-
-
- // ---------------------------------------------------------------------
- /** Get the current offset from the beginning of the file */
- int GetCurrentPos() const {
- return (unsigned int)(current - buffer);
- }
-
- void SetCurrentPos(size_t pos) {
- SetPtr(buffer + pos);
- }
-
- // ---------------------------------------------------------------------
- /** Setup a temporary read limit
- *
- * @param limit Maximum number of bytes to be read from
- * the beginning of the file. Specifying UINT_MAX
- * resets the limit to the original end of the stream. */
- void SetReadLimit(unsigned int _limit) {
-
- if (UINT_MAX == _limit) {
- limit = end;
- return;
- }
-
- limit = buffer + _limit;
- if (limit > end) {
- throw DeadlyImportError("StreamReader: Invalid read limit");
- }
- }
-
- // ---------------------------------------------------------------------
- /** Get the current read limit in bytes. Reading over this limit
- * accidentially raises an exception. */
- int GetReadLimit() const {
- return (unsigned int)(limit - buffer);
- }
-
- // ---------------------------------------------------------------------
- /** Skip to the read limit in bytes. Reading over this limit
- * accidentially raises an exception. */
- void SkipToReadLimit() {
- current = limit;
- }
-
- // ---------------------------------------------------------------------
- /** overload operator>> and allow chaining of >> ops. */
- template <typename T>
- StreamReader& operator >> (T& f) {
- f = Get<T>();
- return *this;
- }
+ // ---------------------------------------------------------------------
+ /** Get the remaining stream size (to the end of the srream) */
+ unsigned int GetRemainingSize() const {
+ return (unsigned int)(end - current);
+ }
+
+
+ // ---------------------------------------------------------------------
+ /** Get the remaining stream size (to the current read limit). The
+ * return value is the remaining size of the stream if no custom
+ * read limit has been set. */
+ unsigned int GetRemainingSizeToLimit() const {
+ return (unsigned int)(limit - current);
+ }
+
+
+ // ---------------------------------------------------------------------
+ /** Increase the file pointer (relative seeking) */
+ void IncPtr(size_t plus) {
+ current += plus;
+ if (current > limit) {
+ throw DeadlyImportError("End of file or read limit was reached");
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the current file pointer */
+ int8_t* GetPtr() const {
+ return current;
+ }
+
+
+ // ---------------------------------------------------------------------
+ /** Set current file pointer (Get it from #GetPtr). This is if you
+ * prefer to do pointer arithmetics on your own or want to copy
+ * large chunks of data at once.
+ * @param p The new pointer, which is validated against the size
+ * limit and buffer boundaries. */
+ void SetPtr(int8_t* p) {
+
+ current = p;
+ if (current > limit || current < buffer) {
+ throw DeadlyImportError("End of file or read limit was reached");
+ }
+ }
+
+ // ---------------------------------------------------------------------
+ /** Copy n bytes to an external buffer
+ * @param out Destination for copying
+ * @param bytes Number of bytes to copy */
+ void CopyAndAdvance(void* out, size_t bytes) {
+
+ int8_t* ur = GetPtr();
+ SetPtr(ur+bytes); // fire exception if eof
+
+ memcpy(out,ur,bytes);
+ }
+
+
+ // ---------------------------------------------------------------------
+ /** Get the current offset from the beginning of the file */
+ int GetCurrentPos() const {
+ return (unsigned int)(current - buffer);
+ }
+
+ void SetCurrentPos(size_t pos) {
+ SetPtr(buffer + pos);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Setup a temporary read limit
+ *
+ * @param limit Maximum number of bytes to be read from
+ * the beginning of the file. Specifying UINT_MAX
+ * resets the limit to the original end of the stream.
+ * Returns the previously set limit. */
+ unsigned int SetReadLimit(unsigned int _limit) {
+ unsigned int prev = GetReadLimit();
+ if (UINT_MAX == _limit) {
+ limit = end;
+ return prev;
+ }
+
+ limit = buffer + _limit;
+ if (limit > end) {
+ throw DeadlyImportError("StreamReader: Invalid read limit");
+ }
+ return prev;
+ }
+
+ // ---------------------------------------------------------------------
+ /** Get the current read limit in bytes. Reading over this limit
+ * accidentially raises an exception. */
+ unsigned int GetReadLimit() const {
+ return (unsigned int)(limit - buffer);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Skip to the read limit in bytes. Reading over this limit
+ * accidentially raises an exception. */
+ void SkipToReadLimit() {
+ current = limit;
+ }
+
+ // ---------------------------------------------------------------------
+ /** overload operator>> and allow chaining of >> ops. */
+ template <typename T>
+ StreamReader& operator >> (T& f) {
+ f = Get<T>();
+ return *this;
+ }
private:
- // ---------------------------------------------------------------------
- /** Generic read method. ByteSwap::Swap(T*) *must* be defined */
- template <typename T>
- T Get() {
- if (current + sizeof(T) > limit) {
- throw DeadlyImportError("End of file or stream limit was reached");
- }
+ // ---------------------------------------------------------------------
+ /** Generic read method. ByteSwap::Swap(T*) *must* be defined */
+ template <typename T>
+ T Get() {
+ if (current + sizeof(T) > limit) {
+ throw DeadlyImportError("End of file or stream limit was reached");
+ }
#ifdef __arm__
- T f;
- memcpy (&f, current, sizeof(T));
+ T f;
+ memcpy (&f, current, sizeof(T));
#else
- T f = *((const T*)current);
-#endif
- Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
-
- current += sizeof(T);
- return f;
- }
-
- // ---------------------------------------------------------------------
- void InternBegin() {
- if (!stream) {
- // incase someone wonders: StreamReader is frequently invoked with
- // no prior validation whether the input stream is valid. Since
- // no one bothers changing the error message, this message here
- // is passed down to the caller and 'unable to open file'
- // simply describes best what happened.
- throw DeadlyImportError("StreamReader: Unable to open file");
- }
-
- const size_t s = stream->FileSize() - stream->Tell();
- if (!s) {
- throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
- }
-
- current = buffer = new int8_t[s];
- const size_t read = stream->Read(current,1,s);
- // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
- ai_assert(read <= s);
- end = limit = &buffer[read];
- }
+ T f = *((const T*)current);
+#endif
+ Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
+
+ current += sizeof(T);
+ return f;
+ }
+
+ // ---------------------------------------------------------------------
+ void InternBegin() {
+ if (!stream) {
+ // incase someone wonders: StreamReader is frequently invoked with
+ // no prior validation whether the input stream is valid. Since
+ // no one bothers changing the error message, this message here
+ // is passed down to the caller and 'unable to open file'
+ // simply describes best what happened.
+ throw DeadlyImportError("StreamReader: Unable to open file");
+ }
+
+ const size_t s = stream->FileSize() - stream->Tell();
+ if (!s) {
+ throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
+ }
+
+ current = buffer = new int8_t[s];
+ const size_t read = stream->Read(current,1,s);
+ // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
+ ai_assert(read <= s);
+ end = limit = &buffer[read];
+ }
private:
- boost::shared_ptr<IOStream> stream;
- int8_t *buffer, *current, *end, *limit;
- bool le;
+ std::shared_ptr<IOStream> stream;
+ int8_t *buffer, *current, *end, *limit;
+ bool le;
};
// --------------------------------------------------------------------------------------------
// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
#ifdef AI_BUILD_BIG_ENDIAN
- typedef StreamReader<true> StreamReaderLE;
- typedef StreamReader<false> StreamReaderBE;
+ typedef StreamReader<true> StreamReaderLE;
+ typedef StreamReader<false> StreamReaderBE;
#else
- typedef StreamReader<true> StreamReaderBE;
- typedef StreamReader<false> StreamReaderLE;
+ typedef StreamReader<true> StreamReaderBE;
+ typedef StreamReader<false> StreamReaderLE;
#endif
// `dynamic` StreamReader. The byte order of the input data is specified in the
diff --git a/src/3rdparty/assimp/code/StreamWriter.h b/src/3rdparty/assimp/code/StreamWriter.h
new file mode 100644
index 000000000..12239bf7f
--- /dev/null
+++ b/src/3rdparty/assimp/code/StreamWriter.h
@@ -0,0 +1,239 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+/** @file Defines the StreamWriter class which writes data to
+ * a binary stream with a well-defined endianness. */
+
+#ifndef AI_STREAMWRITER_H_INCLUDED
+#define AI_STREAMWRITER_H_INCLUDED
+
+#include "ByteSwapper.h"
+#include <assimp/IOStream.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/** Wrapper class around IOStream to allow for consistent writing of binary data in both
+ * little and big endian format. Don't attempt to instance the template directly. Use
+ * StreamWriterLE to read from a little-endian stream and StreamWriterBE to read from a
+ * BE stream. Alternatively, there is StreamWriterAny if the endianness of the output
+ * stream is to be determined at runtime.
+ */
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess = false, bool RuntimeSwitch = false>
+class StreamWriter
+{
+ enum {
+ INITIAL_CAPACITY = 1024
+ };
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** Construction from a given stream with a well-defined endianness.
+ *
+ * The StreamReader holds a permanent strong reference to the
+ * stream, which is released upon destruction.
+ * @param stream Input stream. The stream is not re-seeked and writing
+ continues at the current position of the stream cursor.
+ * @param le If @c RuntimeSwitch is true: specifies whether the
+ * stream is in little endian byte order. Otherwise the
+ * endianness information is defined by the @c SwapEndianess
+ * template parameter and this parameter is meaningless. */
+ StreamWriter(std::shared_ptr<IOStream> stream, bool le = false)
+ : stream(stream)
+ , le(le)
+ , cursor()
+ {
+ ai_assert(stream);
+ buffer.reserve(INITIAL_CAPACITY);
+ }
+
+ // ---------------------------------------------------------------------
+ StreamWriter(IOStream* stream, bool le = false)
+ : stream(std::shared_ptr<IOStream>(stream))
+ , le(le)
+ , cursor()
+ {
+ ai_assert(stream);
+ buffer.reserve(INITIAL_CAPACITY);
+ }
+
+ // ---------------------------------------------------------------------
+ ~StreamWriter() {
+ stream->Write(&buffer[0], 1, buffer.size());
+ stream->Flush();
+ }
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** Write a float to the stream */
+ void PutF4(float f)
+ {
+ Put(f);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a double to the stream */
+ void PutF8(double d) {
+ Put(d);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 16 bit integer to the stream */
+ void PutI2(int16_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 8 bit integer to the stream */
+ void PutI1(int8_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write an signed 32 bit integer to the stream */
+ void PutI4(int32_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a signed 64 bit integer to the stream */
+ void PutI8(int64_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 16 bit integer to the stream */
+ void PutU2(uint16_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 8 bit integer to the stream */
+ void PutU1(uint8_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write an unsigned 32 bit integer to the stream */
+ void PutU4(uint32_t n) {
+ Put(n);
+ }
+
+ // ---------------------------------------------------------------------
+ /** Write a unsigned 64 bit integer to the stream */
+ void PutU8(uint64_t n) {
+ Put(n);
+ }
+
+public:
+
+ // ---------------------------------------------------------------------
+ /** overload operator<< and allow chaining of MM ops. */
+ template <typename T>
+ StreamWriter& operator << (T f) {
+ Put(f);
+ return *this;
+ }
+
+ // ---------------------------------------------------------------------
+ std::size_t GetCurrentPos() const {
+ return cursor;
+ }
+
+ // ---------------------------------------------------------------------
+ void SetCurrentPos(std::size_t new_cursor) {
+ cursor = new_cursor;
+ }
+
+private:
+
+ // ---------------------------------------------------------------------
+ /** Generic write method. ByteSwap::Swap(T*) *must* be defined */
+ template <typename T>
+ void Put(T f) {
+ Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f, le);
+
+ if (cursor + sizeof(T) >= buffer.size()) {
+ buffer.resize(cursor + sizeof(T));
+ }
+
+ void* dest = &buffer[cursor];
+
+ // reinterpret_cast + assignment breaks strict aliasing rules
+ // and generally causes trouble on platforms such as ARM that
+ // do not silently ignore alignment faults.
+ ::memcpy(dest, &f, sizeof(T));
+ cursor += sizeof(T);
+ }
+
+private:
+
+ std::shared_ptr<IOStream> stream;
+ bool le;
+
+ std::vector<uint8_t> buffer;
+ std::size_t cursor;
+};
+
+
+// --------------------------------------------------------------------------------------------
+// `static` StreamWriter. Their byte order is fixed and they might be a little bit faster.
+#ifdef AI_BUILD_BIG_ENDIAN
+ typedef StreamWriter<true> StreamWriterLE;
+ typedef StreamWriter<false> StreamWriterBE;
+#else
+ typedef StreamWriter<true> StreamWriterBE;
+ typedef StreamWriter<false> StreamWriterLE;
+#endif
+
+// `dynamic` StreamWriter. The byte order of the input data is specified in the
+// c'tor. This involves runtime branching and might be a little bit slower.
+typedef StreamWriter<true,true> StreamWriterAny;
+
+} // end namespace Assimp
+
+#endif // !! AI_STREAMWriter_H_INCLUDED
diff --git a/src/3rdparty/assimp/code/StringComparison.h b/src/3rdparty/assimp/code/StringComparison.h
index d38fc86fe..0e1dbe4b8 100644
--- a/src/3rdparty/assimp/code/StringComparison.h
+++ b/src/3rdparty/assimp/code/StringComparison.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -50,9 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_STRING_WORKERS_H
#define INCLUDED_AI_STRING_WORKERS_H
-#include "../include/assimp/ai_assert.h"
+#include <assimp/ai_assert.h>
+#include "StringComparison.h"
-namespace Assimp {
+#include <string.h>
+#include <stdint.h>
+#include <string>
+#include <cctype>
+
+namespace Assimp {
// -------------------------------------------------------------------------------
/** @brief itoa with a fixed base 10
@@ -67,40 +73,40 @@ namespace Assimp {
*/
inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
{
- ai_assert(NULL != out);
-
- // write the unary minus to indicate we have a negative number
- unsigned int written = 1u;
- if (number < 0 && written < max) {
- *out++ = '-';
- ++written;
- number = -number;
- }
-
- // We begin with the largest number that is not zero.
- int32_t cur = 1000000000; // 2147483648
- bool mustPrint = false;
- while (written < max) {
-
- const unsigned int digit = number / cur;
- if (mustPrint || digit > 0 || 1 == cur) {
- // print all future zeroes from now
- mustPrint = true;
-
- *out++ = '0'+static_cast<char>(digit);
-
- ++written;
- number -= digit*cur;
- if (1 == cur) {
- break;
- }
- }
- cur /= 10;
- }
-
- // append a terminal zero
- *out++ = '\0';
- return written-1;
+ ai_assert(NULL != out);
+
+ // write the unary minus to indicate we have a negative number
+ unsigned int written = 1u;
+ if (number < 0 && written < max) {
+ *out++ = '-';
+ ++written;
+ number = -number;
+ }
+
+ // We begin with the largest number that is not zero.
+ int32_t cur = 1000000000; // 2147483648
+ bool mustPrint = false;
+ while (written < max) {
+
+ const unsigned int digit = number / cur;
+ if (mustPrint || digit > 0 || 1 == cur) {
+ // print all future zeroes from now
+ mustPrint = true;
+
+ *out++ = '0'+static_cast<char>(digit);
+
+ ++written;
+ number -= digit*cur;
+ if (1 == cur) {
+ break;
+ }
+ }
+ cur /= 10;
+ }
+
+ // append a terminal zero
+ *out++ = '\0';
+ return written-1;
}
// -------------------------------------------------------------------------------
@@ -111,7 +117,7 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number)
template <size_t length>
inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
{
- return ASSIMP_itoa10(out,length,number);
+ return ASSIMP_itoa10(out,length,number);
}
// -------------------------------------------------------------------------------
@@ -119,7 +125,7 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
*
* This is required since stricmp() is not consistently available on
* all platforms. Some platforms use the '_' prefix, others don't even
- * have such a function.
+ * have such a function.
*
* @param s1 First input string
* @param s2 Second input string
@@ -127,23 +133,23 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number)
*/
inline int ASSIMP_stricmp(const char *s1, const char *s2)
{
- ai_assert(NULL != s1 && NULL != s2);
+ ai_assert(NULL != s1 && NULL != s2);
#if (defined _MSC_VER)
- return ::_stricmp(s1,s2);
+ return ::_stricmp(s1,s2);
#elif defined( __GNUC__ )
-
- return ::strcasecmp(s1,s2);
+
+ return ::strcasecmp(s1,s2);
#else
-
+
char c1, c2;
- do {
- c1 = tolower(*s1++);
- c2 = tolower(*s2++);
- }
- while ( c1 && (c1 == c2) );
- return c1 - c2;
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ }
+ while ( c1 && (c1 == c2) );
+ return c1 - c2;
#endif
}
@@ -157,7 +163,7 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
{
int i = (int)b.length()-(int)a.length();
- return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
+ return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str()));
}
// -------------------------------------------------------------------------------
@@ -165,7 +171,7 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
*
* This is required since strincmp() is not consistently available on
* all platforms. Some platforms use the '_' prefix, others don't even
- * have such a function.
+ * have such a function.
*
* @param s1 First input string
* @param s2 Second input string
@@ -174,29 +180,29 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
*/
inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
{
- ai_assert(NULL != s1 && NULL != s2);
- if (!n)return 0;
+ ai_assert(NULL != s1 && NULL != s2);
+ if (!n)return 0;
#if (defined _MSC_VER)
- return ::_strnicmp(s1,s2,n);
+ return ::_strnicmp(s1,s2,n);
#elif defined( __GNUC__ )
- return ::strncasecmp(s1,s2, n);
+ return ::strncasecmp(s1,s2, n);
#else
char c1, c2;
- unsigned int p = 0;
- do
- {
- if (p++ >= n)return 0;
- c1 = tolower(*s1++);
- c2 = tolower(*s2++);
- }
- while ( c1 && (c1 == c2) );
-
- return c1 - c2;
+ unsigned int p = 0;
+ do
+ {
+ if (p++ >= n)return 0;
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ }
+ while ( c1 && (c1 == c2) );
+
+ return c1 - c2;
#endif
}
@@ -204,15 +210,15 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
// -------------------------------------------------------------------------------
/** @brief Evaluates an integer power
*
- * todo: move somewhere where it fits better in than here
+ * todo: move somewhere where it fits better in than here
*/
inline unsigned int integer_pow (unsigned int base, unsigned int power)
{
- unsigned int res = 1;
- for (unsigned int i = 0; i < power;++i)
- res *= base;
+ unsigned int res = 1;
+ for (unsigned int i = 0; i < power;++i)
+ res *= base;
- return res;
+ return res;
}
} // end of namespace
diff --git a/src/3rdparty/assimp/code/StringUtils.h b/src/3rdparty/assimp/code/StringUtils.h
new file mode 100644
index 000000000..99352ebfb
--- /dev/null
+++ b/src/3rdparty/assimp/code/StringUtils.h
@@ -0,0 +1,111 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef INCLUDED_AI_STRINGUTILS_H
+#define INCLUDED_AI_STRINGUTILS_H
+
+#include <cstdarg>
+#include <string.h>
+#include <stdio.h>
+#include <sstream>
+#include <string>
+
+/// @fn ai_snprintf
+/// @brief The portable version of the function snprintf ( C99 standard ), which works on visual studio compilers 2013 and earlier.
+/// @param outBuf The buffer to write in
+/// @param size The buffer size
+/// @param format The format string
+/// @param ap The additional arguments.
+/// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned.
+#if defined(_MSC_VER) && _MSC_VER < 1900
+
+ inline int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+ int count(-1);
+ if (0 != size) {
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ }
+ if (count == -1) {
+ count = _vscprintf(format, ap);
+ }
+
+ return count;
+ }
+
+ inline int ai_snprintf(char *outBuf, size_t size, const char *format, ...) {
+ int count;
+ va_list ap;
+
+ va_start(ap, format);
+ count = c99_ai_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+
+ return count;
+ }
+
+#else
+# define ai_snprintf snprintf
+#endif
+
+template <typename T>
+inline
+std::string to_string( T value ) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+}
+
+inline
+float ai_strtof( const char *begin, const char *end ) {
+ if ( nullptr == begin ) {
+ return 0.0f;
+ }
+ float val( 0.0f );
+ if ( nullptr == end ) {
+ val = static_cast< float >( ::atof( begin ) );
+ } else {
+ std::string::size_type len( end - begin );
+ std::string token( begin, len );
+ val = static_cast< float >( ::atof( token.c_str() ) );
+ }
+
+ return val;
+}
+
+#endif // INCLUDED_AI_STRINGUTILS_H
+
diff --git a/src/3rdparty/assimp/code/Subdivision.cpp b/src/3rdparty/assimp/code/Subdivision.cpp
index 483712c56..012c70047 100644
--- a/src/3rdparty/assimp/code/Subdivision.cpp
+++ b/src/3rdparty/assimp/code/Subdivision.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,34 +23,33 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
-
#include "Subdivision.h"
#include "SceneCombiner.h"
#include "SpatialSort.h"
#include "ProcessHelper.h"
#include "Vertex.h"
+#include <stdio.h>
using namespace Assimp;
void mydummy() {}
// ------------------------------------------------------------------------------------------------
-/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The
+/** 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. */
// ------------------------------------------------------------------------------------------------
@@ -59,50 +58,50 @@ 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.
- // ---------------------------------------------------------------------------
+ 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))
+ (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__;
+ unsigned int eh_tmp0__, eh_tmp1__;
private:
- void InternSubdivide (const aiMesh* const * smesh,
- size_t nmesh,aiMesh** out, unsigned int num);
+ void InternSubdivide (const aiMesh* const * smesh,
+ size_t nmesh,aiMesh** out, unsigned int num);
};
@@ -110,478 +109,485 @@ private:
// 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
+ 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
- )
+ aiMesh* mesh,
+ aiMesh*& out,
+ unsigned int num,
+ bool discard_input
+ )
{
- assert(mesh != out);
- Subdivide(&mesh,1,&out,num,discard_input);
+ 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
- )
+ aiMesh** smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num,
+ bool discard_input
+ )
{
- ai_assert(NULL != smesh && NULL != out);
-
- // course, both regions may not overlap
- 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) {
- DefaultLogger::get()->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(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()) {
- DefaultLogger::get()->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(outmeshes[i]);
- out[maptbl[i]] = outmeshes[i];
- }
-
- if (discard_input) {
- for (size_t s = 0; s < nmesh; ++s) {
- delete smesh[s];
- }
- }
+ ai_assert(NULL != smesh && NULL != out);
+
+ // course, both regions may not overlap
+ 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) {
+ DefaultLogger::get()->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(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()) {
+ DefaultLogger::get()->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(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
+// 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).
+// 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
- )
+ const aiMesh* const * smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num
+ )
{
- ai_assert(NULL != smesh && NULL != out);
- INIT_EDGE_HASH_TEMPORARIES();
+ ai_assert(NULL != smesh && NULL != out);
+ INIT_EDGE_HASH_TEMPORARIES();
- // no subdivision requested or end of recursive refinement
- if (!num) {
- return;
- }
+ // no subdivision requested or end of recursive refinement
+ if (!num) {
+ return;
+ }
- UIntVector maptbl;
- SpatialSort spatial;
+ 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];
+ // ---------------------------------------------------------------------
+ // 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);
+ spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false);
+ moffsets[t] = IntPair(totfaces,totvert);
- totfaces += mesh->mNumFaces;
- totvert += mesh->mNumVertices;
- }
+ totfaces += mesh->mNumFaces;
+ totvert += mesh->mNumVertices;
+ }
- spatial.Finalize();
- const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh));
+ 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;
- }
- }
-
- 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.
- char tmp[512];
- sprintf(tmp,"Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ",
- bad_cnt,static_cast<unsigned int>(edges.size()));
-
- DefaultLogger::get()->debug(tmp);
- }}
-
- // ---------------------------------------------------------------------
- // 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
+ // ---------------------------------------------------------------------
+ // 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.
+ char tmp[512];
+ ai_snprintf(tmp, 512, "Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ",
+ bad_cnt,static_cast<unsigned int>(edges.size()));
+
+ DefaultLogger::get()->debug(tmp);
+ }}
+
+ // ---------------------------------------------------------------------
+ // 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);
- break;
- }
- }
- }
- }
+ 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) {
+ DefaultLogger::get()->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];
-# ifdef ASSIMP_BUILD_DEBUG
- bool haveit = false;
-# endif
-
- // 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;
-
-# ifdef ASSIMP_BUILD_DEBUG
- haveit = true;
-# endif
- break;
- }
- }
-
- // this invariant *must* hold if the vertex-to-face adjacency table is valid
- ai_assert(haveit);
- }
-
- 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++);
- }
- }
- }
-
- // ---------------------------------------------------------------------
- // 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];
- }
- }
+ 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];
+# ifdef ASSIMP_BUILD_DEBUG
+ bool haveit = false;
+# endif
+
+ // 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;
+
+# ifdef ASSIMP_BUILD_DEBUG
+ haveit = true;
+# endif
+ break;
+ }
+ }
+
+ // this invariant *must* hold if the vertex-to-face adjacency table is valid
+ ai_assert(haveit);
+ }
+
+ 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];
+ }
+ }
}
diff --git a/src/3rdparty/assimp/code/Subdivision.h b/src/3rdparty/assimp/code/Subdivision.h
index 49e65297f..658640f55 100644
--- a/src/3rdparty/assimp/code/Subdivision.h
+++ b/src/3rdparty/assimp/code/Subdivision.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,7 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Defines a helper class to evaluate subdivision surfaces.*/
#ifndef AI_SUBDISIVION_H_INC
#define AI_SUBDISIVION_H_INC
-namespace Assimp {
+
+#include <cstddef>
+struct aiMesh;
+
+namespace Assimp {
// ------------------------------------------------------------------------------
/** Helper class to evaluate subdivision surfaces. Different algorithms
@@ -51,68 +55,68 @@ class Subdivider
{
public:
- /** Enumerates all supported subvidision algorithms */
- enum Algorithm {
- CATMULL_CLARKE = 0x1
- };
+ /** Enumerates all supported subvidision algorithms */
+ enum Algorithm {
+ CATMULL_CLARKE = 0x1
+ };
public:
- virtual ~Subdivider() {
- }
+ virtual ~Subdivider() {
+ }
public:
- // ---------------------------------------------------------------
- /** Create a subdivider of a specific type
- *
- * @param algo Algorithm to be used for subdivision
- * @return Subdivider instance. */
- static Subdivider* Create (Algorithm algo);
-
- // ---------------------------------------------------------------
- /** Subdivide a mesh using the selected algorithm
- *
- * @param mesh First mesh to be subdivided. Must be in verbose
- * format.
- * @param out Receives the output mesh, allocated by me.
- * @param num Number of subdivisions to perform.
- * @param discard_input If true is passed, the input mesh is
- * deleted after the subdivision is complete. This can
- * improve performance because it allows the optimization
- * to reuse the existing mesh for intermediate results.
- * @pre out!=mesh*/
- virtual void Subdivide ( aiMesh* mesh,
- aiMesh*& out, unsigned int num,
- bool discard_input = false) = 0;
-
- // ---------------------------------------------------------------
- /** Subdivide multiple meshes using the selected algorithm. This
- * avoids erroneous smoothing on objects consisting of multiple
- * per-material meshes. Usually, most 3d modellers smooth on a
- * per-object base, regardless the materials assigned to the
- * meshes.
- *
- * @param smesh Array of meshes to be subdivided. Must be in
- * verbose format.
- * @param nmesh Number of meshes in smesh.
- * @param out Receives the output meshes. The array must be
- * sufficiently large (at least @c nmesh elements) and may not
- * overlap the input array. Output meshes map one-to-one to
- * their corresponding input meshes. The meshes are allocated
- * by the function.
- * @param discard_input If true is passed, input meshes are
- * deleted after the subdivision is complete. This can
- * improve performance because it allows the optimization
- * of reusing existing meshes for intermediate results.
- * @param num Number of subdivisions to perform.
- * @pre nmesh != 0, smesh and out may not overlap*/
- virtual void Subdivide (
- aiMesh** smesh,
- size_t nmesh,
- aiMesh** out,
- unsigned int num,
- bool discard_input = false) = 0;
+ // ---------------------------------------------------------------
+ /** Create a subdivider of a specific type
+ *
+ * @param algo Algorithm to be used for subdivision
+ * @return Subdivider instance. */
+ static Subdivider* Create (Algorithm algo);
+
+ // ---------------------------------------------------------------
+ /** Subdivide a mesh using the selected algorithm
+ *
+ * @param mesh First mesh to be subdivided. Must be in verbose
+ * format.
+ * @param out Receives the output mesh, allocated by me.
+ * @param num Number of subdivisions to perform.
+ * @param discard_input If true is passed, the input mesh is
+ * deleted after the subdivision is complete. This can
+ * improve performance because it allows the optimization
+ * to reuse the existing mesh for intermediate results.
+ * @pre out!=mesh*/
+ virtual void Subdivide ( aiMesh* mesh,
+ aiMesh*& out, unsigned int num,
+ bool discard_input = false) = 0;
+
+ // ---------------------------------------------------------------
+ /** Subdivide multiple meshes using the selected algorithm. This
+ * avoids erroneous smoothing on objects consisting of multiple
+ * per-material meshes. Usually, most 3d modellers smooth on a
+ * per-object base, regardless the materials assigned to the
+ * meshes.
+ *
+ * @param smesh Array of meshes to be subdivided. Must be in
+ * verbose format.
+ * @param nmesh Number of meshes in smesh.
+ * @param out Receives the output meshes. The array must be
+ * sufficiently large (at least @c nmesh elements) and may not
+ * overlap the input array. Output meshes map one-to-one to
+ * their corresponding input meshes. The meshes are allocated
+ * by the function.
+ * @param discard_input If true is passed, input meshes are
+ * deleted after the subdivision is complete. This can
+ * improve performance because it allows the optimization
+ * of reusing existing meshes for intermediate results.
+ * @param num Number of subdivisions to perform.
+ * @pre nmesh != 0, smesh and out may not overlap*/
+ virtual void Subdivide (
+ aiMesh** smesh,
+ size_t nmesh,
+ aiMesh** out,
+ unsigned int num,
+ bool discard_input = false) = 0;
private:
};
diff --git a/src/3rdparty/assimp/code/TargetAnimation.cpp b/src/3rdparty/assimp/code/TargetAnimation.cpp
index 14ce0690a..a78f66bea 100644
--- a/src/3rdparty/assimp/code/TargetAnimation.cpp
+++ b/src/3rdparty/assimp/code/TargetAnimation.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,224 +23,224 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-#include "AssimpPCH.h"
#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)
+ 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;
- }
+ // 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, float val)
{
- return one + (two-one)*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<unsigned int> ( nextObjPos, objPos->size()-1) ).mTime;
- d1 = targetObjPos->at( std::min<unsigned int> ( nextTargetObjPos, 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, (float) (
- (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, (float) (
- (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;
- }
+ // 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<unsigned int> ( nextObjPos, objPos->size()-1) ).mTime;
+ d1 = targetObjPos->at( std::min<unsigned int> ( nextTargetObjPos, 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, (float) (
+ (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, (float) (
+ (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)
+ const std::vector<aiVectorKey>* _targetPositions)
{
- ai_assert(NULL != _targetPositions);
- targetPositions = _targetPositions;
+ ai_assert(NULL != _targetPositions);
+ targetPositions = _targetPositions;
}
// ------------------------------------------------------------------------------------------------
void TargetAnimationHelper::SetMainAnimationChannel (
- const std::vector<aiVectorKey>* _objectPositions)
+ const std::vector<aiVectorKey>* _objectPositions)
{
- ai_assert(NULL != _objectPositions);
- objectPositions = _objectPositions;
+ ai_assert(NULL != _objectPositions);
+ objectPositions = _objectPositions;
}
// ------------------------------------------------------------------------------------------------
void TargetAnimationHelper::SetFixedMainAnimationChannel(
- const aiVector3D& fixed)
+ const aiVector3D& fixed)
{
- objectPositions = NULL; // just to avoid confusion
- fixedMain = 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;
- float 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;
- }
+ 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;
+ float 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;
+ }
}
diff --git a/src/3rdparty/assimp/code/TargetAnimation.h b/src/3rdparty/assimp/code/TargetAnimation.h
index 9e517cd63..79cef599e 100644
--- a/src/3rdparty/assimp/code/TargetAnimation.h
+++ b/src/3rdparty/assimp/code/TargetAnimation.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,8 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_TARGET_ANIMATION_H_INC
#define AI_TARGET_ANIMATION_H_INC
+#include <assimp/anim.h>
+#include <vector>
-namespace Assimp {
+namespace Assimp {
@@ -58,64 +60,64 @@ 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;}
+
+ // ------------------------------------------------------------------
+ /** 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;
+ //! Did we reach the end?
+ bool reachedEnd;
- //! Represents the current position of the iterator
- aiVector3D curPosition, curTargetPosition;
+ //! Represents the current position of the iterator
+ aiVector3D curPosition, curTargetPosition;
- double curTime;
+ double curTime;
- //! Input tracks and the next key to process
- const std::vector<aiVectorKey>* objPos,*targetObjPos;
+ //! Input tracks and the next key to process
+ const std::vector<aiVectorKey>* objPos,*targetObjPos;
- unsigned int nextObjPos, nextTargetObjPos;
- std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos;
+ unsigned int nextObjPos, nextTargetObjPos;
+ std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos;
};
// ---------------------------------------------------------------------------
@@ -130,47 +132,47 @@ class TargetAnimationHelper
{
public:
- TargetAnimationHelper()
- : targetPositions (NULL)
- , objectPositions (NULL)
- {}
+ 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 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
+ *
+ * @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);
+ // ------------------------------------------------------------------
+ /** 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 );
+ // ------------------------------------------------------------------
+ /** 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;
+ const std::vector<aiVectorKey>* targetPositions,*objectPositions;
+ aiVector3D fixedMain;
};
diff --git a/src/3rdparty/assimp/code/TerragenLoader.cpp b/src/3rdparty/assimp/code/TerragenLoader.cpp
index 27775dd9e..854959f19 100644
--- a/src/3rdparty/assimp/code/TerragenLoader.cpp
+++ b/src/3rdparty/assimp/code/TerragenLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,40 +25,47 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the Terragen importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
+
#include "TerragenLoader.h"
+#include "StreamReader.h"
+#include <assimp/Importer.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Terragen Heightmap Importer",
- "",
- "",
- "http://www.planetside.co.uk/",
- aiImporterFlags_SupportBinaryFlavour,
- 0,
- 0,
- 0,
- 0,
- "ter"
+ "Terragen Heightmap Importer",
+ "",
+ "",
+ "http://www.planetside.co.uk/",
+ aiImporterFlags_SupportBinaryFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "ter"
};
// ------------------------------------------------------------------------------------------------
@@ -68,201 +75,201 @@ TerragenImporter::TerragenImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
TerragenImporter::~TerragenImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool TerragenImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- // check file extension
- std::string extension = GetExtension(pFile);
-
- if( extension == "ter")
- return true;
-
- if( !extension.length() || checkSig) {
- /* If CanRead() is called in order to check whether we
- * support a specific file extension in general pIOHandler
- * might be NULL and it's our duty to return true here.
- */
- if (!pIOHandler)return true;
- const char* tokens[] = {"terragen"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
- }
- return false;
+ // check file extension
+ std::string extension = GetExtension(pFile);
+
+ if( extension == "ter")
+ return true;
+
+ if( !extension.length() || checkSig) {
+ /* If CanRead() is called in order to check whether we
+ * support a specific file extension in general pIOHandler
+ * might be NULL and it's our duty to return true here.
+ */
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"terragen"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported
const aiImporterDesc* TerragenImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup import properties
void TerragenImporter::SetupProperties(const Importer* pImp)
{
- // AI_CONFIG_IMPORT_TER_MAKE_UVS
- configComputeUVs = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,0) );
+ // AI_CONFIG_IMPORT_TER_MAKE_UVS
+ configComputeUVs = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,0) );
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void TerragenImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void TerragenImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- IOStream* file = pIOHandler->Open( pFile, "rb");
-
- // Check whether we can read from the file
- if( file == NULL)
- throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + ".");
-
- // Construct a stream reader to read all data in the correct endianess
- StreamReaderLE reader(file);
- if(reader.GetRemainingSize() < 16)
- throw DeadlyImportError( "TER: file is too small" );
-
- // Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN '
- if (::strncmp((const char*)reader.GetPtr(),AI_TERR_BASE_STRING,8))
- throw DeadlyImportError( "TER: Magic string \'TERRAGEN\' not found" );
-
- if (::strncmp((const char*)reader.GetPtr()+8,AI_TERR_TERRAIN_STRING,8))
- throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" );
-
- unsigned int x = 0,y = 0,mode = 0;
- float rad = 6370.f;
- (void)rad;
-
-
- aiNode* root = pScene->mRootNode = new aiNode();
- root->mName.Set("<TERRAGEN.TERRAIN>");
-
- // Default scaling is 30
- root->mTransformation.a1 = root->mTransformation.b2 = root->mTransformation.c3 = 30.f;
-
- // Now read all chunks until we're finished or an EOF marker is encountered
- reader.IncPtr(16);
- while (reader.GetRemainingSize() >= 4)
- {
- const char* head = (const char*)reader.GetPtr();
- reader.IncPtr(4);
-
- // EOF, break in every case
- if (!::strncmp(head,AI_TERR_EOF_STRING,4))
- break;
-
- // Number of x-data points
- if (!::strncmp(head,AI_TERR_CHUNK_XPTS,4))
- {
- x = (uint16_t)reader.GetI2();
- }
- // Number of y-data points
- else if (!::strncmp(head,AI_TERR_CHUNK_YPTS,4))
- {
- y = (uint16_t)reader.GetI2();
- }
- // Squared terrains width-1.
- else if (!::strncmp(head,AI_TERR_CHUNK_SIZE,4))
- {
- x = y = (uint16_t)reader.GetI2()+1;
- }
- // terrain scaling
- else if (!::strncmp(head,AI_TERR_CHUNK_SCAL,4))
- {
- root->mTransformation.a1 = reader.GetF4();
- root->mTransformation.b2 = reader.GetF4();
- root->mTransformation.c3 = reader.GetF4();
- }
- // mapping == 1: earth radius
- else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
- {
- rad = reader.GetF4();
- }
- // mapping mode
- else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
- {
- mode = reader.GetI1();
- if (0 != mode)
- DefaultLogger::get()->error("TER: Unsupported mapping mode, a flat terrain is returned");
- }
- // actual terrain data
- else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4))
- {
- float hscale = (float)reader.GetI2() / 65536;
- float bheight = (float)reader.GetI2();
-
- if (!hscale)hscale = 1;
-
- // Ensure we have enough data
- if (reader.GetRemainingSize() < x*y*2)
- throw DeadlyImportError("TER: ALTW chunk is too small");
-
- if (x <= 1 || y <= 1)
- throw DeadlyImportError("TER: Invalid terrain size");
-
- // Allocate the output mesh
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = 1];
- aiMesh* m = pScene->mMeshes[0] = new aiMesh();
-
- // We return quads
- aiFace* f = m->mFaces = new aiFace[m->mNumFaces = (x-1)*(y-1)];
- aiVector3D* pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces*4];
-
- aiVector3D *uv( NULL );
- float step_y( 0.0f ), step_x( 0.0f );
- if (configComputeUVs) {
- uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
- step_y = 1.f/y;
- step_x = 1.f/x;
- }
- const int16_t* data = (const int16_t*)reader.GetPtr();
-
- for (unsigned int yy = 0, t = 0; yy < y-1;++yy) {
- for (unsigned int xx = 0; xx < x-1;++xx,++f) {
-
- // make verts
- const float fy = (float)yy, fx = (float)xx;
- unsigned tmp,tmp2;
- *pv++ = aiVector3D(fx,fy, (float)data[(tmp2=x*yy) + xx] * hscale + bheight);
- *pv++ = aiVector3D(fx,fy+1, (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight);
- *pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp + xx+1] * hscale + bheight);
- *pv++ = aiVector3D(fx+1,fy, (float)data[tmp2 + xx+1] * hscale + bheight);
-
- // also make texture coordinates, if necessary
- if (configComputeUVs) {
- *uv++ = aiVector3D( step_x*xx, step_y*yy, 0.f );
- *uv++ = aiVector3D( step_x*xx, step_y*(yy+1), 0.f );
- *uv++ = aiVector3D( step_x*(xx+1), step_y*(yy+1), 0.f );
- *uv++ = aiVector3D( step_x*(xx+1), step_y*yy, 0.f );
- }
-
- // make indices
- f->mIndices = new unsigned int[f->mNumIndices = 4];
- for (unsigned int i = 0; i < 4;++i)
- f->mIndices[i] = t++;
- }
- }
-
- // Add the mesh to the root node
- root->mMeshes = new unsigned int[root->mNumMeshes = 1];
- root->mMeshes[0] = 0;
- }
-
- // Get to the next chunk (4 byte aligned)
- unsigned dtt;
- if ((dtt = reader.GetCurrentPos() & 0x3))
- reader.IncPtr(4-dtt);
- }
-
- // Check whether we have a mesh now
- if (pScene->mNumMeshes != 1)
- throw DeadlyImportError("TER: Unable to load terrain");
-
- // Set the AI_SCENE_FLAGS_TERRAIN bit
- pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
+ IOStream* file = pIOHandler->Open( pFile, "rb");
+
+ // Check whether we can read from the file
+ if( file == NULL)
+ throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + ".");
+
+ // Construct a stream reader to read all data in the correct endianness
+ StreamReaderLE reader(file);
+ if(reader.GetRemainingSize() < 16)
+ throw DeadlyImportError( "TER: file is too small" );
+
+ // Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN '
+ if (::strncmp((const char*)reader.GetPtr(),AI_TERR_BASE_STRING,8))
+ throw DeadlyImportError( "TER: Magic string \'TERRAGEN\' not found" );
+
+ if (::strncmp((const char*)reader.GetPtr()+8,AI_TERR_TERRAIN_STRING,8))
+ throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" );
+
+ unsigned int x = 0,y = 0,mode = 0;
+ float rad = 6370.f;
+ (void)rad;
+
+
+ aiNode* root = pScene->mRootNode = new aiNode();
+ root->mName.Set("<TERRAGEN.TERRAIN>");
+
+ // Default scaling is 30
+ root->mTransformation.a1 = root->mTransformation.b2 = root->mTransformation.c3 = 30.f;
+
+ // Now read all chunks until we're finished or an EOF marker is encountered
+ reader.IncPtr(16);
+ while (reader.GetRemainingSize() >= 4)
+ {
+ const char* head = (const char*)reader.GetPtr();
+ reader.IncPtr(4);
+
+ // EOF, break in every case
+ if (!::strncmp(head,AI_TERR_EOF_STRING,4))
+ break;
+
+ // Number of x-data points
+ if (!::strncmp(head,AI_TERR_CHUNK_XPTS,4))
+ {
+ x = (uint16_t)reader.GetI2();
+ }
+ // Number of y-data points
+ else if (!::strncmp(head,AI_TERR_CHUNK_YPTS,4))
+ {
+ y = (uint16_t)reader.GetI2();
+ }
+ // Squared terrains width-1.
+ else if (!::strncmp(head,AI_TERR_CHUNK_SIZE,4))
+ {
+ x = y = (uint16_t)reader.GetI2()+1;
+ }
+ // terrain scaling
+ else if (!::strncmp(head,AI_TERR_CHUNK_SCAL,4))
+ {
+ root->mTransformation.a1 = reader.GetF4();
+ root->mTransformation.b2 = reader.GetF4();
+ root->mTransformation.c3 = reader.GetF4();
+ }
+ // mapping == 1: earth radius
+ else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
+ {
+ rad = reader.GetF4();
+ }
+ // mapping mode
+ else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
+ {
+ mode = reader.GetI1();
+ if (0 != mode)
+ DefaultLogger::get()->error("TER: Unsupported mapping mode, a flat terrain is returned");
+ }
+ // actual terrain data
+ else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4))
+ {
+ float hscale = (float)reader.GetI2() / 65536;
+ float bheight = (float)reader.GetI2();
+
+ if (!hscale)hscale = 1;
+
+ // Ensure we have enough data
+ if (reader.GetRemainingSize() < x*y*2)
+ throw DeadlyImportError("TER: ALTW chunk is too small");
+
+ if (x <= 1 || y <= 1)
+ throw DeadlyImportError("TER: Invalid terrain size");
+
+ // Allocate the output mesh
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = 1];
+ aiMesh* m = pScene->mMeshes[0] = new aiMesh();
+
+ // We return quads
+ aiFace* f = m->mFaces = new aiFace[m->mNumFaces = (x-1)*(y-1)];
+ aiVector3D* pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces*4];
+
+ aiVector3D *uv( NULL );
+ float step_y( 0.0f ), step_x( 0.0f );
+ if (configComputeUVs) {
+ uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
+ step_y = 1.f/y;
+ step_x = 1.f/x;
+ }
+ const int16_t* data = (const int16_t*)reader.GetPtr();
+
+ for (unsigned int yy = 0, t = 0; yy < y-1;++yy) {
+ for (unsigned int xx = 0; xx < x-1;++xx,++f) {
+
+ // make verts
+ const float fy = (float)yy, fx = (float)xx;
+ unsigned tmp,tmp2;
+ *pv++ = aiVector3D(fx,fy, (float)data[(tmp2=x*yy) + xx] * hscale + bheight);
+ *pv++ = aiVector3D(fx,fy+1, (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight);
+ *pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp + xx+1] * hscale + bheight);
+ *pv++ = aiVector3D(fx+1,fy, (float)data[tmp2 + xx+1] * hscale + bheight);
+
+ // also make texture coordinates, if necessary
+ if (configComputeUVs) {
+ *uv++ = aiVector3D( step_x*xx, step_y*yy, 0.f );
+ *uv++ = aiVector3D( step_x*xx, step_y*(yy+1), 0.f );
+ *uv++ = aiVector3D( step_x*(xx+1), step_y*(yy+1), 0.f );
+ *uv++ = aiVector3D( step_x*(xx+1), step_y*yy, 0.f );
+ }
+
+ // make indices
+ f->mIndices = new unsigned int[f->mNumIndices = 4];
+ for (unsigned int i = 0; i < 4;++i)
+ f->mIndices[i] = t++;
+ }
+ }
+
+ // Add the mesh to the root node
+ root->mMeshes = new unsigned int[root->mNumMeshes = 1];
+ root->mMeshes[0] = 0;
+ }
+
+ // Get to the next chunk (4 byte aligned)
+ unsigned dtt;
+ if ((dtt = reader.GetCurrentPos() & 0x3))
+ reader.IncPtr(4-dtt);
+ }
+
+ // Check whether we have a mesh now
+ if (pScene->mNumMeshes != 1)
+ throw DeadlyImportError("TER: Unable to load terrain");
+
+ // Set the AI_SCENE_FLAGS_TERRAIN bit
+ pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
}
#endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
diff --git a/src/3rdparty/assimp/code/TerragenLoader.h b/src/3rdparty/assimp/code/TerragenLoader.h
index 02112c843..c216a2186 100644
--- a/src/3rdparty/assimp/code/TerragenLoader.h
+++ b/src/3rdparty/assimp/code/TerragenLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,29 +23,29 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file TerragenLoader.h
- * @brief Declaration of the .ter importer class.
+ * @brief Declaration of the .ter importer class.
*/
#ifndef INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H
#define INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H
#include "BaseImporter.h"
-namespace Assimp {
+namespace Assimp {
// Magic strings
#define AI_TERR_BASE_STRING "TERRAGEN"
@@ -70,31 +70,31 @@ namespace Assimp {
class TerragenImporter : public BaseImporter
{
public:
- TerragenImporter();
- ~TerragenImporter();
+ TerragenImporter();
+ ~TerragenImporter();
public:
- // -------------------------------------------------------------------
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
private:
- bool configComputeUVs;
+ bool configComputeUVs;
}; //! class TerragenImporter
diff --git a/src/3rdparty/assimp/code/TextureTransform.cpp b/src/3rdparty/assimp/code/TextureTransform.cpp
index 365550cfd..948ec013b 100644
--- a/src/3rdparty/assimp/code/TextureTransform.cpp
+++ b/src/3rdparty/assimp/code/TextureTransform.cpp
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -41,524 +41,530 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file A helper class that processes texture transformations */
-#include "AssimpPCH.h"
+
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
+
#include "TextureTransform.h"
+#include "StringUtils.h"
using namespace Assimp;
-
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
-TextureTransformStep::TextureTransformStep()
+TextureTransformStep::TextureTransformStep() :
+ configFlags()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
TextureTransformStep::~TextureTransformStep()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool TextureTransformStep::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_TransformUVCoords) != 0;
+ return (pFlags & aiProcess_TransformUVCoords) != 0;
}
// ------------------------------------------------------------------------------------------------
// Setup properties
void TextureTransformStep::SetupProperties(const Importer* pImp)
{
- configFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_TUV_EVALUATE,AI_UVTRAFO_ALL);
+ configFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_TUV_EVALUATE,AI_UVTRAFO_ALL);
}
// ------------------------------------------------------------------------------------------------
void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
{
- /* This function tries to simplify the input UV transformation.
- * That's very important as it allows us to reduce the number
- * of output UV channels. The oder in which the transformations
- * are applied is - as always - scaling, rotation, translation.
- */
-
- char szTemp[512];
- int rounded = 0;
-
-
- /* Optimize the rotation angle. That's slightly difficult as
- * we have an inprecise floating-point number (when comparing
- * UV transformations we'll take that into account by using
- * an epsilon of 5 degrees). If there is a rotation value, we can't
- * perform any further optimizations.
- */
- if (info.mRotation)
- {
- float out = info.mRotation;
- if ((rounded = (int)(info.mRotation / (float)AI_MATH_TWO_PI)))
- {
- out -= rounded*(float)AI_MATH_PI;
-
- sprintf(szTemp,"Texture coordinate rotation %f can be simplified to %f",info.mRotation,out);
- DefaultLogger::get()->info(szTemp);
- }
-
- // Next step - convert negative rotation angles to positives
- if (out < 0.f)
- out = (float)AI_MATH_TWO_PI * 2 + out;
-
- info.mRotation = out;
- return;
- }
-
-
- /* Optimize UV translation in the U direction. To determine whether
- * or not we can optimize we need to look at the requested mapping
- * type (e.g. if mirroring is active there IS a difference between
- * offset 2 and 3)
- */
- if ((rounded = (int)info.mTranslation.x)) {
- float out;
- szTemp[0] = 0;
- if (aiTextureMapMode_Wrap == info.mapU) {
- // Wrap - simple take the fraction of the field
- out = info.mTranslation.x-(float)rounded;
- sprintf(szTemp,"[w] UV U offset %f can be simplified to %f",info.mTranslation.x,out);
- }
- else if (aiTextureMapMode_Mirror == info.mapU && 1 != rounded) {
- // Mirror
- if (rounded % 2)
- rounded--;
- out = info.mTranslation.x-(float)rounded;
-
- sprintf(szTemp,"[m/d] UV U offset %f can be simplified to %f",info.mTranslation.x,out);
- }
- else if (aiTextureMapMode_Clamp == info.mapU || aiTextureMapMode_Decal == info.mapU) {
- // Clamp - translations beyond 1,1 are senseless
- sprintf(szTemp,"[c] UV U offset %f can be clamped to 1.0f",info.mTranslation.x);
-
- out = 1.f;
- }
- if (szTemp[0]) {
- DefaultLogger::get()->info(szTemp);
- info.mTranslation.x = out;
- }
- }
-
- /* Optimize UV translation in the V direction. To determine whether
- * or not we can optimize we need to look at the requested mapping
- * type (e.g. if mirroring is active there IS a difference between
- * offset 2 and 3)
- */
- if ((rounded = (int)info.mTranslation.y)) {
- float out;
- szTemp[0] = 0;
- if (aiTextureMapMode_Wrap == info.mapV) {
- // Wrap - simple take the fraction of the field
- out = info.mTranslation.y-(float)rounded;
- sprintf(szTemp,"[w] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
- }
- else if (aiTextureMapMode_Mirror == info.mapV && 1 != rounded) {
- // Mirror
- if (rounded % 2)
- rounded--;
- out = info.mTranslation.x-(float)rounded;
-
- sprintf(szTemp,"[m/d] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
- }
- else if (aiTextureMapMode_Clamp == info.mapV || aiTextureMapMode_Decal == info.mapV) {
- // Clamp - translations beyond 1,1 are senseless
- sprintf(szTemp,"[c] UV V offset %f canbe clamped to 1.0f",info.mTranslation.y);
-
- out = 1.f;
- }
- if (szTemp[0]) {
- DefaultLogger::get()->info(szTemp);
- info.mTranslation.y = out;
- }
- }
- return;
+ /* This function tries to simplify the input UV transformation.
+ * That's very important as it allows us to reduce the number
+ * of output UV channels. The oder in which the transformations
+ * are applied is - as always - scaling, rotation, translation.
+ */
+
+ char szTemp[512];
+ int rounded = 0;
+
+
+ /* Optimize the rotation angle. That's slightly difficult as
+ * we have an inprecise floating-point number (when comparing
+ * UV transformations we'll take that into account by using
+ * an epsilon of 5 degrees). If there is a rotation value, we can't
+ * perform any further optimizations.
+ */
+ if (info.mRotation)
+ {
+ float out = info.mRotation;
+ if ((rounded = (int)(info.mRotation / (float)AI_MATH_TWO_PI)))
+ {
+ out -= rounded*(float)AI_MATH_PI;
+
+ ai_snprintf(szTemp, 512, "Texture coordinate rotation %f can be simplified to %f",info.mRotation,out);
+ DefaultLogger::get()->info(szTemp);
+ }
+
+ // Next step - convert negative rotation angles to positives
+ if (out < 0.f)
+ out = (float)AI_MATH_TWO_PI * 2 + out;
+
+ info.mRotation = out;
+ return;
+ }
+
+
+ /* Optimize UV translation in the U direction. To determine whether
+ * or not we can optimize we need to look at the requested mapping
+ * type (e.g. if mirroring is active there IS a difference between
+ * offset 2 and 3)
+ */
+ if ((rounded = (int)info.mTranslation.x)) {
+ float out = 0.0f;
+ szTemp[0] = 0;
+ if (aiTextureMapMode_Wrap == info.mapU) {
+ // Wrap - simple take the fraction of the field
+ out = info.mTranslation.x-(float)rounded;
+ ai_snprintf(szTemp, 512, "[w] UV U offset %f can be simplified to %f", info.mTranslation.x, out);
+ }
+ else if (aiTextureMapMode_Mirror == info.mapU && 1 != rounded) {
+ // Mirror
+ if (rounded % 2)
+ rounded--;
+ out = info.mTranslation.x-(float)rounded;
+
+ ai_snprintf(szTemp,512,"[m/d] UV U offset %f can be simplified to %f",info.mTranslation.x,out);
+ }
+ else if (aiTextureMapMode_Clamp == info.mapU || aiTextureMapMode_Decal == info.mapU) {
+ // Clamp - translations beyond 1,1 are senseless
+ ai_snprintf(szTemp,512,"[c] UV U offset %f can be clamped to 1.0f",info.mTranslation.x);
+
+ out = 1.f;
+ }
+ if (szTemp[0]) {
+ DefaultLogger::get()->info(szTemp);
+ info.mTranslation.x = out;
+ }
+ }
+
+ /* Optimize UV translation in the V direction. To determine whether
+ * or not we can optimize we need to look at the requested mapping
+ * type (e.g. if mirroring is active there IS a difference between
+ * offset 2 and 3)
+ */
+ if ((rounded = (int)info.mTranslation.y)) {
+ float out = 0.0f;
+ szTemp[0] = 0;
+ if (aiTextureMapMode_Wrap == info.mapV) {
+ // Wrap - simple take the fraction of the field
+ out = info.mTranslation.y-(float)rounded;
+ ::ai_snprintf(szTemp,512,"[w] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
+ }
+ else if (aiTextureMapMode_Mirror == info.mapV && 1 != rounded) {
+ // Mirror
+ if (rounded % 2)
+ rounded--;
+ out = info.mTranslation.x-(float)rounded;
+
+ ::ai_snprintf(szTemp,512,"[m/d] UV V offset %f can be simplified to %f",info.mTranslation.y,out);
+ }
+ else if (aiTextureMapMode_Clamp == info.mapV || aiTextureMapMode_Decal == info.mapV) {
+ // Clamp - translations beyond 1,1 are senseless
+ ::ai_snprintf(szTemp,512,"[c] UV V offset %f canbe clamped to 1.0f",info.mTranslation.y);
+
+ out = 1.f;
+ }
+ if (szTemp[0]) {
+ DefaultLogger::get()->info(szTemp);
+ info.mTranslation.y = out;
+ }
+ }
+ return;
}
// ------------------------------------------------------------------------------------------------
void UpdateUVIndex(const std::list<TTUpdateInfo>& l, unsigned int n)
{
- // Don't set if == 0 && wasn't set before
- for (std::list<TTUpdateInfo>::const_iterator it = l.begin();it != l.end(); ++it) {
- const TTUpdateInfo& info = *it;
-
- if (info.directShortcut)
- *info.directShortcut = n;
- else if (!n)
- {
- info.mat->AddProperty<int>((int*)&n,1,AI_MATKEY_UVWSRC(info.semantic,info.index));
- }
- }
+ // Don't set if == 0 && wasn't set before
+ for (std::list<TTUpdateInfo>::const_iterator it = l.begin();it != l.end(); ++it) {
+ const TTUpdateInfo& info = *it;
+
+ if (info.directShortcut)
+ *info.directShortcut = n;
+ else if (!n)
+ {
+ info.mat->AddProperty<int>((int*)&n,1,AI_MATKEY_UVWSRC(info.semantic,info.index));
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
inline const char* MappingModeToChar(aiTextureMapMode map)
{
- if (aiTextureMapMode_Wrap == map)
- return "-w";
+ if (aiTextureMapMode_Wrap == map)
+ return "-w";
+
+ if (aiTextureMapMode_Mirror == map)
+ return "-m";
- if (aiTextureMapMode_Mirror == map)
- return "-m";
-
- return "-c";
+ return "-c";
}
// ------------------------------------------------------------------------------------------------
-void TextureTransformStep::Execute( aiScene* pScene)
+void TextureTransformStep::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("TransformUVCoordsProcess begin");
-
-
- /* We build a per-mesh list of texture transformations we'll need
- * to apply. To achieve this, we iterate through all materials,
- * find all textures and get their transformations and UV indices.
- * Then we search for all meshes using this material.
- */
- typedef std::list<STransformVecInfo> MeshTrafoList;
- std::vector<MeshTrafoList> meshLists(pScene->mNumMeshes);
-
- for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
-
- 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.file")) {
- STransformVecInfo info;
-
- // Setup a shortcut structure to allow for a fast updating
- // of the UV index later
- TTUpdateInfo update;
- update.mat = (aiMaterial*) mat;
- update.semantic = prop->mSemantic;
- update.index = prop->mIndex;
-
- // Get textured properties and transform
- 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.uvwsrc")) {
- info.uvIndex = *((int*)prop2->mData);
-
- // Store a direct pointer for later use
- update.directShortcut = (unsigned int*) prop2->mData;
- }
-
- else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodeu")) {
- info.mapU = *((aiTextureMapMode*)prop2->mData);
- }
- else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodev")) {
- info.mapV = *((aiTextureMapMode*)prop2->mData);
- }
- else if ( !::strcmp( prop2->mKey.data, "$tex.uvtrafo")) {
- // ValidateDS should check this
- ai_assert(prop2->mDataLength >= 20);
- ::memcpy(&info.mTranslation.x,prop2->mData,sizeof(float)*5);
-
- // Directly remove this property from the list
- mat->mNumProperties--;
- for (unsigned int a3 = a2; a3 < mat->mNumProperties;++a3) {
- mat->mProperties[a3] = mat->mProperties[a3+1];
- }
-
- delete prop2;
-
- // Warn: could be an underflow, but this does not invoke undefined behaviour
- --a2;
- }
- }
-
- // Find out which transformations are to be evaluated
- if (!(configFlags & AI_UVTRAFO_ROTATION)) {
- info.mRotation = 0.f;
- }
- if (!(configFlags & AI_UVTRAFO_SCALING)) {
- info.mScaling = aiVector2D(1.f,1.f);
- }
- if (!(configFlags & AI_UVTRAFO_TRANSLATION)) {
- info.mTranslation = aiVector2D(0.f,0.f);
- }
-
- // Do some preprocessing
- PreProcessUVTransform(info);
- info.uvIndex = std::min(info.uvIndex,AI_MAX_NUMBER_OF_TEXTURECOORDS -1u);
-
- // Find out whether this material is used by more than
- // one mesh. This will make our task much, much more difficult!
- unsigned int cnt = 0;
- for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
- if (pScene->mMeshes[n]->mMaterialIndex == i)
- ++cnt;
- }
-
- if (!cnt)
- continue;
- else if (1 != cnt) {
- // This material is referenced by more than one mesh!
- // So we need to make sure the UV index for the texture
- // is identical for each of it ...
- info.lockedPos = AI_TT_UV_IDX_LOCK_TBD;
- }
-
- // Get all coresponding meshes
- for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
- aiMesh* mesh = pScene->mMeshes[n];
- if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0])
- continue;
-
- unsigned int uv = info.uvIndex;
- if (!mesh->mTextureCoords[uv]) {
- // If the requested UV index is not available, take the first one instead.
- uv = 0;
- }
-
- if (mesh->mNumUVComponents[info.uvIndex] >= 3){
- DefaultLogger::get()->warn("UV transformations on 3D mapping channels are not supported");
- continue;
- }
-
- MeshTrafoList::iterator it;
-
- // Check whether we have this transform setup already
- for (it = meshLists[n].begin();it != meshLists[n].end(); ++it) {
-
- if ((*it) == info && (*it).uvIndex == uv) {
- (*it).updateList.push_back(update);
- break;
- }
- }
-
- if (it == meshLists[n].end()) {
- meshLists[n].push_back(info);
- meshLists[n].back().uvIndex = uv;
- meshLists[n].back().updateList.push_back(update);
- }
- }
- }
- }
- }
-
- char buffer[1024]; // should be sufficiently large
- unsigned int outChannels = 0, inChannels = 0, transformedChannels = 0;
-
- // Now process all meshes. Important: we don't remove unreferenced UV channels.
- // This is a job for the RemoveUnreferencedData-Step.
- for (unsigned int q = 0; q < pScene->mNumMeshes;++q) {
-
- aiMesh* mesh = pScene->mMeshes[q];
- MeshTrafoList& trafo = meshLists[q];
-
- inChannels += mesh->GetNumUVChannels();
-
- if (!mesh->mTextureCoords[0] || trafo.empty() || (trafo.size() == 1 && trafo.begin()->IsUntransformed())) {
- outChannels += mesh->GetNumUVChannels();
- continue;
- }
-
- // Move untransformed UV channels to the first position in the list ....
- // except if we need a new locked index which should be as small as possible
- bool veto = false, need = false;
- unsigned int cnt = 0;
- unsigned int untransformed = 0;
-
- MeshTrafoList::iterator it,it2;
- for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
-
- if (!(*it).IsUntransformed()) {
- need = true;
- }
-
- if ((*it).lockedPos == AI_TT_UV_IDX_LOCK_TBD) {
- // Lock this index and make sure it won't be changed
- (*it).lockedPos = cnt;
- veto = true;
- continue;
- }
-
- if (!veto && it != trafo.begin() && (*it).IsUntransformed()) {
- for (it2 = trafo.begin();it2 != it; ++it2) {
- if (!(*it2).IsUntransformed())
- break;
- }
- trafo.insert(it2,*it);
- trafo.erase(it);
- break;
- }
- }
- if (!need)
- continue;
-
- // Find all that are not at their 'locked' position and move them to it.
- // Conflicts are possible but quite unlikely.
- cnt = 0;
- for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
- if ((*it).lockedPos != AI_TT_UV_IDX_LOCK_NONE && (*it).lockedPos != cnt) {
- it2 = trafo.begin();unsigned int t = 0;
- while (t != (*it).lockedPos)
- ++it2;
-
- if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) {
- DefaultLogger::get()->error("Channel mismatch, can't compute all transformations properly [design bug]");
- continue;
- }
-
- std::swap(*it2,*it);
- if ((*it).lockedPos == untransformed)
- untransformed = cnt;
- }
- }
-
- // ... and add dummies for all unreferenced channels
- // at the end of the list
- bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
- ref[n] = (!mesh->mTextureCoords[n] ? true : false);
-
- for (it = trafo.begin();it != trafo.end(); ++it)
- ref[(*it).uvIndex] = true;
-
- for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
- if (ref[n])
- continue;
- trafo.push_back(STransformVecInfo());
- trafo.back().uvIndex = n;
- }
-
- // Then check whether this list breaks the channel limit.
- // The unimportant ones are at the end of the list, so
- // it shouldn't be too worse if we remove them.
- unsigned int size = (unsigned int)trafo.size();
- if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
-
- if (!DefaultLogger::isNullLogger()) {
- ::sprintf(buffer,"%u UV channels required but just %u available",
- static_cast<unsigned int>(trafo.size()),AI_MAX_NUMBER_OF_TEXTURECOORDS);
-
- DefaultLogger::get()->error(buffer);
- }
- size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
- }
-
-
- aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
- old[n] = mesh->mTextureCoords[n];
-
- // Now continue and generate the output channels. Channels
- // that we're not going to need later can be overridden.
- it = trafo.begin();
- for (unsigned int n = 0; n < trafo.size();++n,++it) {
-
- if (n >= size) {
- // Try to use an untransformed channel for all channels we threw over board
- UpdateUVIndex((*it).updateList,untransformed);
- continue;
- }
-
- outChannels++;
-
- // Write to the log
- if (!DefaultLogger::isNullLogger()) {
- sprintf(buffer,"Mesh %u, channel %u: t(%.3f,%.3f), s(%.3f,%.3f), r(%.3f), %s%s",
- q,n,
- (*it).mTranslation.x,
- (*it).mTranslation.y,
- (*it).mScaling.x,
- (*it).mScaling.y,
- AI_RAD_TO_DEG( (*it).mRotation),
- MappingModeToChar ((*it).mapU),
- MappingModeToChar ((*it).mapV));
-
- DefaultLogger::get()->info(buffer);
- }
-
- // Check whether we need a new buffer here
- if (mesh->mTextureCoords[n]) {
-
- it2 = it;++it2;
- for (unsigned int m = n+1; m < size;++m, ++it2) {
-
- if ((*it2).uvIndex == n){
- it2 = trafo.begin();
- break;
- }
- }
- if (it2 == trafo.begin()){
- mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
- }
- }
- else mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
-
- aiVector3D* src = old[(*it).uvIndex];
- aiVector3D* dest, *end;
- dest = mesh->mTextureCoords[n];
-
- ai_assert(NULL != src);
-
- // Copy the data to the destination array
- if (dest != src)
- ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices);
-
- end = dest + mesh->mNumVertices;
-
- // Build a transformation matrix and transform all UV coords with it
- if (!(*it).IsUntransformed()) {
- const aiVector2D& trl = (*it).mTranslation;
- const aiVector2D& scl = (*it).mScaling;
-
- // fixme: simplify ..
- ++transformedChannels;
- aiMatrix3x3 matrix;
-
- aiMatrix3x3 m2,m3,m4,m5;
-
- m4.a1 = scl.x;
- m4.b2 = scl.y;
-
- m2.a3 = m2.b3 = 0.5f;
- m3.a3 = m3.b3 = -0.5f;
-
- if ((*it).mRotation > AI_TT_ROTATION_EPSILON )
- aiMatrix3x3::RotationZ((*it).mRotation,matrix);
-
- m5.a3 += trl.x; m5.b3 += trl.y;
- matrix = m2 * m4 * matrix * m3 * m5;
-
- for (src = dest; src != end; ++src) { /* manual homogenious divide */
- src->z = 1.f;
- *src = matrix * *src;
- src->x /= src->z;
- src->y /= src->z;
- src->z = 0.f;
- }
- }
-
- // Update all UV indices
- UpdateUVIndex((*it).updateList,n);
- }
- }
-
- // Print some detailled statistics into the log
- if (!DefaultLogger::isNullLogger()) {
-
- if (transformedChannels) {
- ::sprintf(buffer,"TransformUVCoordsProcess end: %u output channels (in: %u, modified: %u)",
- outChannels,inChannels,transformedChannels);
-
- DefaultLogger::get()->info(buffer);
- }
- else DefaultLogger::get()->debug("TransformUVCoordsProcess finished");
- }
+ DefaultLogger::get()->debug("TransformUVCoordsProcess begin");
+
+
+ /* We build a per-mesh list of texture transformations we'll need
+ * to apply. To achieve this, we iterate through all materials,
+ * find all textures and get their transformations and UV indices.
+ * Then we search for all meshes using this material.
+ */
+ typedef std::list<STransformVecInfo> MeshTrafoList;
+ std::vector<MeshTrafoList> meshLists(pScene->mNumMeshes);
+
+ for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
+
+ 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.file")) {
+ STransformVecInfo info;
+
+ // Setup a shortcut structure to allow for a fast updating
+ // of the UV index later
+ TTUpdateInfo update;
+ update.mat = (aiMaterial*) mat;
+ update.semantic = prop->mSemantic;
+ update.index = prop->mIndex;
+
+ // Get textured properties and transform
+ 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.uvwsrc")) {
+ info.uvIndex = *((int*)prop2->mData);
+
+ // Store a direct pointer for later use
+ update.directShortcut = (unsigned int*) prop2->mData;
+ }
+
+ else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodeu")) {
+ info.mapU = *((aiTextureMapMode*)prop2->mData);
+ }
+ else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodev")) {
+ info.mapV = *((aiTextureMapMode*)prop2->mData);
+ }
+ else if ( !::strcmp( prop2->mKey.data, "$tex.uvtrafo")) {
+ // ValidateDS should check this
+ ai_assert(prop2->mDataLength >= 20);
+ ::memcpy(&info.mTranslation.x,prop2->mData,sizeof(float)*5);
+
+ // Directly remove this property from the list
+ mat->mNumProperties--;
+ for (unsigned int a3 = a2; a3 < mat->mNumProperties;++a3) {
+ mat->mProperties[a3] = mat->mProperties[a3+1];
+ }
+
+ delete prop2;
+
+ // Warn: could be an underflow, but this does not invoke undefined behaviour
+ --a2;
+ }
+ }
+
+ // Find out which transformations are to be evaluated
+ if (!(configFlags & AI_UVTRAFO_ROTATION)) {
+ info.mRotation = 0.f;
+ }
+ if (!(configFlags & AI_UVTRAFO_SCALING)) {
+ info.mScaling = aiVector2D(1.f,1.f);
+ }
+ if (!(configFlags & AI_UVTRAFO_TRANSLATION)) {
+ info.mTranslation = aiVector2D(0.f,0.f);
+ }
+
+ // Do some preprocessing
+ PreProcessUVTransform(info);
+ info.uvIndex = std::min(info.uvIndex,AI_MAX_NUMBER_OF_TEXTURECOORDS -1u);
+
+ // Find out whether this material is used by more than
+ // one mesh. This will make our task much, much more difficult!
+ unsigned int cnt = 0;
+ for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
+ if (pScene->mMeshes[n]->mMaterialIndex == i)
+ ++cnt;
+ }
+
+ if (!cnt)
+ continue;
+ else if (1 != cnt) {
+ // This material is referenced by more than one mesh!
+ // So we need to make sure the UV index for the texture
+ // is identical for each of it ...
+ info.lockedPos = AI_TT_UV_IDX_LOCK_TBD;
+ }
+
+ // Get all coresponding meshes
+ for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
+ aiMesh* mesh = pScene->mMeshes[n];
+ if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0])
+ continue;
+
+ unsigned int uv = info.uvIndex;
+ if (!mesh->mTextureCoords[uv]) {
+ // If the requested UV index is not available, take the first one instead.
+ uv = 0;
+ }
+
+ if (mesh->mNumUVComponents[info.uvIndex] >= 3){
+ DefaultLogger::get()->warn("UV transformations on 3D mapping channels are not supported");
+ continue;
+ }
+
+ MeshTrafoList::iterator it;
+
+ // Check whether we have this transform setup already
+ for (it = meshLists[n].begin();it != meshLists[n].end(); ++it) {
+
+ if ((*it) == info && (*it).uvIndex == uv) {
+ (*it).updateList.push_back(update);
+ break;
+ }
+ }
+
+ if (it == meshLists[n].end()) {
+ meshLists[n].push_back(info);
+ meshLists[n].back().uvIndex = uv;
+ meshLists[n].back().updateList.push_back(update);
+ }
+ }
+ }
+ }
+ }
+
+ char buffer[1024]; // should be sufficiently large
+ unsigned int outChannels = 0, inChannels = 0, transformedChannels = 0;
+
+ // Now process all meshes. Important: we don't remove unreferenced UV channels.
+ // This is a job for the RemoveUnreferencedData-Step.
+ for (unsigned int q = 0; q < pScene->mNumMeshes;++q) {
+
+ aiMesh* mesh = pScene->mMeshes[q];
+ MeshTrafoList& trafo = meshLists[q];
+
+ inChannels += mesh->GetNumUVChannels();
+
+ if (!mesh->mTextureCoords[0] || trafo.empty() || (trafo.size() == 1 && trafo.begin()->IsUntransformed())) {
+ outChannels += mesh->GetNumUVChannels();
+ continue;
+ }
+
+ // Move untransformed UV channels to the first position in the list ....
+ // except if we need a new locked index which should be as small as possible
+ bool veto = false, need = false;
+ unsigned int cnt = 0;
+ unsigned int untransformed = 0;
+
+ MeshTrafoList::iterator it,it2;
+ for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
+
+ if (!(*it).IsUntransformed()) {
+ need = true;
+ }
+
+ if ((*it).lockedPos == AI_TT_UV_IDX_LOCK_TBD) {
+ // Lock this index and make sure it won't be changed
+ (*it).lockedPos = cnt;
+ veto = true;
+ continue;
+ }
+
+ if (!veto && it != trafo.begin() && (*it).IsUntransformed()) {
+ for (it2 = trafo.begin();it2 != it; ++it2) {
+ if (!(*it2).IsUntransformed())
+ break;
+ }
+ trafo.insert(it2,*it);
+ trafo.erase(it);
+ break;
+ }
+ }
+ if (!need)
+ continue;
+
+ // Find all that are not at their 'locked' position and move them to it.
+ // Conflicts are possible but quite unlikely.
+ cnt = 0;
+ for (it = trafo.begin();it != trafo.end(); ++it,++cnt) {
+ if ((*it).lockedPos != AI_TT_UV_IDX_LOCK_NONE && (*it).lockedPos != cnt) {
+ it2 = trafo.begin();unsigned int t = 0;
+ while (t != (*it).lockedPos)
+ ++it2;
+
+ if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) {
+ DefaultLogger::get()->error("Channel mismatch, can't compute all transformations properly [design bug]");
+ continue;
+ }
+
+ std::swap(*it2,*it);
+ if ((*it).lockedPos == untransformed)
+ untransformed = cnt;
+ }
+ }
+
+ // ... and add dummies for all unreferenced channels
+ // at the end of the list
+ bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+ ref[n] = (!mesh->mTextureCoords[n] ? true : false);
+
+ for (it = trafo.begin();it != trafo.end(); ++it)
+ ref[(*it).uvIndex] = true;
+
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+ if (ref[n])
+ continue;
+ trafo.push_back(STransformVecInfo());
+ trafo.back().uvIndex = n;
+ }
+
+ // Then check whether this list breaks the channel limit.
+ // The unimportant ones are at the end of the list, so
+ // it shouldn't be too worse if we remove them.
+ unsigned int size = (unsigned int)trafo.size();
+ if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+
+ if (!DefaultLogger::isNullLogger()) {
+ ::ai_snprintf(buffer,1024,"%u UV channels required but just %u available",
+ static_cast<unsigned int>(trafo.size()),AI_MAX_NUMBER_OF_TEXTURECOORDS);
+
+ DefaultLogger::get()->error(buffer);
+ }
+ size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
+ }
+
+
+ aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+ old[n] = mesh->mTextureCoords[n];
+
+ // Now continue and generate the output channels. Channels
+ // that we're not going to need later can be overridden.
+ it = trafo.begin();
+ for (unsigned int n = 0; n < trafo.size();++n,++it) {
+
+ if (n >= size) {
+ // Try to use an untransformed channel for all channels we threw over board
+ UpdateUVIndex((*it).updateList,untransformed);
+ continue;
+ }
+
+ outChannels++;
+
+ // Write to the log
+ if (!DefaultLogger::isNullLogger()) {
+ ::ai_snprintf(buffer,1024,"Mesh %u, channel %u: t(%.3f,%.3f), s(%.3f,%.3f), r(%.3f), %s%s",
+ q,n,
+ (*it).mTranslation.x,
+ (*it).mTranslation.y,
+ (*it).mScaling.x,
+ (*it).mScaling.y,
+ AI_RAD_TO_DEG( (*it).mRotation),
+ MappingModeToChar ((*it).mapU),
+ MappingModeToChar ((*it).mapV));
+
+ DefaultLogger::get()->info(buffer);
+ }
+
+ // Check whether we need a new buffer here
+ if (mesh->mTextureCoords[n]) {
+
+ it2 = it;++it2;
+ for (unsigned int m = n+1; m < size;++m, ++it2) {
+
+ if ((*it2).uvIndex == n){
+ it2 = trafo.begin();
+ break;
+ }
+ }
+ if (it2 == trafo.begin()){
+ mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+ }
+ }
+ else mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+
+ aiVector3D* src = old[(*it).uvIndex];
+ aiVector3D* dest, *end;
+ dest = mesh->mTextureCoords[n];
+
+ ai_assert(NULL != src);
+
+ // Copy the data to the destination array
+ if (dest != src)
+ ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices);
+
+ end = dest + mesh->mNumVertices;
+
+ // Build a transformation matrix and transform all UV coords with it
+ if (!(*it).IsUntransformed()) {
+ const aiVector2D& trl = (*it).mTranslation;
+ const aiVector2D& scl = (*it).mScaling;
+
+ // fixme: simplify ..
+ ++transformedChannels;
+ aiMatrix3x3 matrix;
+
+ aiMatrix3x3 m2,m3,m4,m5;
+
+ m4.a1 = scl.x;
+ m4.b2 = scl.y;
+
+ m2.a3 = m2.b3 = 0.5f;
+ m3.a3 = m3.b3 = -0.5f;
+
+ if ((*it).mRotation > AI_TT_ROTATION_EPSILON )
+ aiMatrix3x3::RotationZ((*it).mRotation,matrix);
+
+ m5.a3 += trl.x; m5.b3 += trl.y;
+ matrix = m2 * m4 * matrix * m3 * m5;
+
+ for (src = dest; src != end; ++src) { /* manual homogenious divide */
+ src->z = 1.f;
+ *src = matrix * *src;
+ src->x /= src->z;
+ src->y /= src->z;
+ src->z = 0.f;
+ }
+ }
+
+ // Update all UV indices
+ UpdateUVIndex((*it).updateList,n);
+ }
+ }
+
+ // Print some detailed statistics into the log
+ if (!DefaultLogger::isNullLogger()) {
+
+ if (transformedChannels) {
+ ::ai_snprintf(buffer,1024,"TransformUVCoordsProcess end: %u output channels (in: %u, modified: %u)",
+ outChannels,inChannels,transformedChannels);
+
+ DefaultLogger::get()->info(buffer);
+ }
+ else DefaultLogger::get()->debug("TransformUVCoordsProcess finished");
+ }
}
diff --git a/src/3rdparty/assimp/code/TextureTransform.h b/src/3rdparty/assimp/code/TextureTransform.h
index 1f8580f54..ccad3bdd9 100644
--- a/src/3rdparty/assimp/code/TextureTransform.h
+++ b/src/3rdparty/assimp/code/TextureTransform.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,15 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "BaseProcess.h"
+#include <assimp/material.h>
+#include <list>
+
struct aiNode;
+struct aiMaterial;
-namespace Assimp {
+namespace Assimp {
-#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
-#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
+#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
+#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
-#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
+#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
// ---------------------------------------------------------------------------
/** Small helper structure representing a shortcut into the material list
@@ -61,21 +65,21 @@ namespace Assimp {
*/
struct TTUpdateInfo
{
- TTUpdateInfo() :
- directShortcut (NULL)
- , mat (NULL)
- , semantic (0)
- , index (0)
- {}
+ TTUpdateInfo() :
+ directShortcut (NULL)
+ , mat (NULL)
+ , semantic (0)
+ , index (0)
+ {}
- //! Direct shortcut, if available
- unsigned int* directShortcut;
+ //! Direct shortcut, if available
+ unsigned int* directShortcut;
- //! Material
- aiMaterial *mat;
+ //! Material
+ aiMaterial *mat;
- //! Texture type and index
- unsigned int semantic, index;
+ //! Texture type and index
+ unsigned int semantic, index;
};
@@ -85,102 +89,102 @@ struct TTUpdateInfo
struct STransformVecInfo : public aiUVTransform
{
- STransformVecInfo()
- : uvIndex (0)
- , mapU (aiTextureMapMode_Wrap)
- , mapV (aiTextureMapMode_Wrap)
- , lockedPos (AI_TT_UV_IDX_LOCK_NONE)
- {}
-
- //! Source texture coordinate index
- unsigned int uvIndex;
-
- //! Texture mapping mode in the u, v direction
- aiTextureMapMode mapU,mapV;
-
- //! Locked destination UV index
- //! AI_TT_UV_IDX_LOCK_TBD - to be determined
- //! AI_TT_UV_IDX_LOCK_NONE - none (default)
- unsigned int lockedPos;
-
- //! Update info - shortcuts into all materials
- //! that are referencing this transform setup
- std::list<TTUpdateInfo> updateList;
-
-
- // -------------------------------------------------------------------
- /** Compare two transform setups
- */
- inline bool operator== (const STransformVecInfo& other) const
- {
- // We use a small epsilon here
- const static float epsilon = 0.05f;
-
- if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
- std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
- {
- return false;
- }
-
- if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
- std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
- {
- return false;
- }
-
- if (std::fabs( mRotation - other.mRotation) > epsilon)
- {
- return false;
- }
- return true;
- }
-
- inline bool operator!= (const STransformVecInfo& other) const
- {
- return !(*this == other);
- }
-
-
- // -------------------------------------------------------------------
- /** Returns whether this is an untransformed texture coordinate set
- */
- inline bool IsUntransformed() const
- {
- return (1.0f == mScaling.x && 1.f == mScaling.y &&
- !mTranslation.x && !mTranslation.y &&
- mRotation < AI_TT_ROTATION_EPSILON);
- }
-
- // -------------------------------------------------------------------
- /** Build a 3x3 matrix from the transformations
- */
- inline void GetMatrix(aiMatrix3x3& mOut)
- {
- mOut = aiMatrix3x3();
-
- if (1.0f != mScaling.x || 1.0f != mScaling.y)
- {
- aiMatrix3x3 mScale;
- mScale.a1 = mScaling.x;
- mScale.b2 = mScaling.y;
- mOut = mScale;
- }
- if (mRotation)
- {
- aiMatrix3x3 mRot;
- mRot.a1 = mRot.b2 = std::cos(mRotation);
+ STransformVecInfo()
+ : uvIndex (0)
+ , mapU (aiTextureMapMode_Wrap)
+ , mapV (aiTextureMapMode_Wrap)
+ , lockedPos (AI_TT_UV_IDX_LOCK_NONE)
+ {}
+
+ //! Source texture coordinate index
+ unsigned int uvIndex;
+
+ //! Texture mapping mode in the u, v direction
+ aiTextureMapMode mapU,mapV;
+
+ //! Locked destination UV index
+ //! AI_TT_UV_IDX_LOCK_TBD - to be determined
+ //! AI_TT_UV_IDX_LOCK_NONE - none (default)
+ unsigned int lockedPos;
+
+ //! Update info - shortcuts into all materials
+ //! that are referencing this transform setup
+ std::list<TTUpdateInfo> updateList;
+
+
+ // -------------------------------------------------------------------
+ /** Compare two transform setups
+ */
+ inline bool operator== (const STransformVecInfo& other) const
+ {
+ // We use a small epsilon here
+ const static float epsilon = 0.05f;
+
+ if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
+ std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
+ {
+ return false;
+ }
+
+ if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
+ std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
+ {
+ return false;
+ }
+
+ if (std::fabs( mRotation - other.mRotation) > epsilon)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ inline bool operator!= (const STransformVecInfo& other) const
+ {
+ return !(*this == other);
+ }
+
+
+ // -------------------------------------------------------------------
+ /** Returns whether this is an untransformed texture coordinate set
+ */
+ inline bool IsUntransformed() const
+ {
+ return (1.0f == mScaling.x && 1.f == mScaling.y &&
+ !mTranslation.x && !mTranslation.y &&
+ mRotation < AI_TT_ROTATION_EPSILON);
+ }
+
+ // -------------------------------------------------------------------
+ /** Build a 3x3 matrix from the transformations
+ */
+ inline void GetMatrix(aiMatrix3x3& mOut)
+ {
+ mOut = aiMatrix3x3();
+
+ if (1.0f != mScaling.x || 1.0f != mScaling.y)
+ {
+ aiMatrix3x3 mScale;
+ mScale.a1 = mScaling.x;
+ mScale.b2 = mScaling.y;
+ mOut = mScale;
+ }
+ if (mRotation)
+ {
+ aiMatrix3x3 mRot;
+ mRot.a1 = mRot.b2 = std::cos(mRotation);
mRot.a2 = mRot.b1 = std::sin(mRotation);
- mRot.a2 = -mRot.a2;
- mOut *= mRot;
- }
- if (mTranslation.x || mTranslation.y)
- {
- aiMatrix3x3 mTrans;
- mTrans.a3 = mTranslation.x;
- mTrans.b3 = mTranslation.y;
- mOut *= mTrans;
- }
- }
+ mRot.a2 = -mRot.a2;
+ mOut *= mRot;
+ }
+ if (mTranslation.x || mTranslation.y)
+ {
+ aiMatrix3x3 mTrans;
+ mTrans.a3 = mTranslation.x;
+ mTrans.b3 = mTranslation.y;
+ mOut *= mTrans;
+ }
+ }
};
@@ -192,34 +196,34 @@ class TextureTransformStep : public BaseProcess
{
public:
- TextureTransformStep();
- ~TextureTransformStep();
+ TextureTransformStep();
+ ~TextureTransformStep();
public:
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
- // -------------------------------------------------------------------
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ void SetupProperties(const Importer* pImp);
protected:
- // -------------------------------------------------------------------
- /** Preprocess a specific UV transformation setup
- *
- * @param info Transformation setup to be preprocessed.
- */
- void PreProcessUVTransform(STransformVecInfo& info);
+ // -------------------------------------------------------------------
+ /** Preprocess a specific UV transformation setup
+ *
+ * @param info Transformation setup to be preprocessed.
+ */
+ void PreProcessUVTransform(STransformVecInfo& info);
private:
- unsigned int configFlags;
+ unsigned int configFlags;
};
}
diff --git a/src/3rdparty/assimp/code/TinyFormatter.h b/src/3rdparty/assimp/code/TinyFormatter.h
index 9818dc0bb..7a5e7d21f 100644
--- a/src/3rdparty/assimp/code/TinyFormatter.h
+++ b/src/3rdparty/assimp/code/TinyFormatter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
namespace Assimp {
- namespace Formatter {
+ namespace Formatter {
// ------------------------------------------------------------------------------------------------
/** stringstream utility. Usage:
@@ -62,102 +62,102 @@ namespace Assimp {
*
* @endcode */
template < typename T,
- typename CharTraits = std::char_traits<T>,
- typename Allocator = std::allocator<T>
->
-class basic_formatter
+ typename CharTraits = std::char_traits<T>,
+ typename Allocator = std::allocator<T>
+>
+class basic_formatter
{
public:
- typedef class std::basic_string<
- T,CharTraits,Allocator
- > string;
+ typedef class std::basic_string<
+ T,CharTraits,Allocator
+ > string;
- typedef class std::basic_ostringstream<
- T,CharTraits,Allocator
- > stringstream;
+ typedef class std::basic_ostringstream<
+ T,CharTraits,Allocator
+ > stringstream;
public:
- basic_formatter() {}
+ basic_formatter() {}
- /* Allow basic_formatter<T>'s to be used almost interchangeably
- * with std::(w)string or const (w)char* arguments because the
- * conversion c'tor is called implicitly. */
- template <typename TT>
- basic_formatter(const TT& sin) {
- underlying << sin;
- }
+ /* Allow basic_formatter<T>'s to be used almost interchangeably
+ * with std::(w)string or const (w)char* arguments because the
+ * conversion c'tor is called implicitly. */
+ template <typename TT>
+ basic_formatter(const TT& sin) {
+ underlying << sin;
+ }
- // The problem described here:
- // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
- // can also cause trouble here. Apparently, older gcc versions sometimes copy temporaries
- // being bound to const ref& function parameters. Copying streams is not permitted, though.
- // This workaround avoids this by manually specifying a copy ctor.
+ // The problem described here:
+ // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462
+ // can also cause trouble here. Apparently, older gcc versions sometimes copy temporaries
+ // being bound to const ref& function parameters. Copying streams is not permitted, though.
+ // This workaround avoids this by manually specifying a copy ctor.
#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
- basic_formatter(const basic_formatter& other) {
- underlying << (string)other;
- }
+ explicit basic_formatter(const basic_formatter& other) {
+ underlying << (string)other;
+ }
#endif
-
+
public:
- operator string () const {
- return underlying.str();
- }
-
-
- /* note - this is declared const because binding temporaries does only
- * work for const references, so many function prototypes will
- * include const basic_formatter<T>& s but might still want to
- * modify the formatted string without the need for a full copy.*/
- template <typename TToken>
- const basic_formatter& operator << (const TToken& s) const {
- underlying << s;
- return *this;
- }
-
- template <typename TToken>
- basic_formatter& operator << (const TToken& s) {
- underlying << s;
- return *this;
- }
-
-
- // comma operator overloaded as well, choose your preferred way.
- template <typename TToken>
- const basic_formatter& operator, (const TToken& s) const {
- underlying << s;
- return *this;
- }
-
- template <typename TToken>
- basic_formatter& operator, (const TToken& s) {
- underlying << s;
- return *this;
- }
-
- // Fix for MSVC8
- // See https://sourceforge.net/projects/assimp/forums/forum/817654/topic/4372824
- template <typename TToken>
- basic_formatter& operator, (TToken& s) {
- underlying << s;
- return *this;
- }
+ operator string () const {
+ return underlying.str();
+ }
+
+
+ /* note - this is declared const because binding temporaries does only
+ * work for const references, so many function prototypes will
+ * include const basic_formatter<T>& s but might still want to
+ * modify the formatted string without the need for a full copy.*/
+ template <typename TToken>
+ const basic_formatter& operator << (const TToken& s) const {
+ underlying << s;
+ return *this;
+ }
+
+ template <typename TToken>
+ basic_formatter& operator << (const TToken& s) {
+ underlying << s;
+ return *this;
+ }
+
+
+ // comma operator overloaded as well, choose your preferred way.
+ template <typename TToken>
+ const basic_formatter& operator, (const TToken& s) const {
+ underlying << s;
+ return *this;
+ }
+
+ template <typename TToken>
+ basic_formatter& operator, (const TToken& s) {
+ underlying << s;
+ return *this;
+ }
+
+ // Fix for MSVC8
+ // See https://sourceforge.net/projects/assimp/forums/forum/817654/topic/4372824
+ template <typename TToken>
+ basic_formatter& operator, (TToken& s) {
+ underlying << s;
+ return *this;
+ }
private:
- mutable stringstream underlying;
+ mutable stringstream underlying;
};
typedef basic_formatter< char > format;
typedef basic_formatter< wchar_t > wformat;
-} // ! namespace Formatter
+} // ! namespace Formatter
} // ! namespace Assimp
#endif
diff --git a/src/3rdparty/assimp/code/TriangulateProcess.cpp b/src/3rdparty/assimp/code/TriangulateProcess.cpp
index 147e38ece..f19f85037 100644
--- a/src/3rdparty/assimp/code/TriangulateProcess.cpp
+++ b/src/3rdparty/assimp/code/TriangulateProcess.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -58,12 +58,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* a file
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
#include "TriangulateProcess.h"
#include "ProcessHelper.h"
#include "PolyTools.h"
+#include <memory>
//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
//#define AI_BUILD_TRIANGULATE_DEBUG_POLYS
@@ -79,37 +80,37 @@ using namespace Assimp;
// Constructor to be privately used by Importer
TriangulateProcess::TriangulateProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
TriangulateProcess::~TriangulateProcess()
{
- // nothing to do here
+ // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool TriangulateProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_Triangulate) != 0;
+ return (pFlags & aiProcess_Triangulate) != 0;
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void TriangulateProcess::Execute( aiScene* pScene)
{
- DefaultLogger::get()->debug("TriangulateProcess begin");
-
- bool bHas = false;
- for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
- {
- if( TriangulateMesh( pScene->mMeshes[a]))
- bHas = true;
- }
- if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated.");
- else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done.");
+ DefaultLogger::get()->debug("TriangulateProcess begin");
+
+ bool bHas = false;
+ for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
+ {
+ if( TriangulateMesh( pScene->mMeshes[a]))
+ bHas = true;
+ }
+ if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated.");
+ else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done.");
}
@@ -117,411 +118,411 @@ void TriangulateProcess::Execute( aiScene* pScene)
// Triangulates the given mesh.
bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh)
{
- // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
- if (!pMesh->mPrimitiveTypes) {
- bool bNeed = false;
-
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
- const aiFace& face = pMesh->mFaces[a];
-
- if( face.mNumIndices != 3) {
- bNeed = true;
- }
- }
- if (!bNeed)
- return false;
- }
- else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
- return false;
- }
-
- // Find out how many output faces we'll get
- unsigned int numOut = 0, max_out = 0;
- bool get_normals = true;
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
- aiFace& face = pMesh->mFaces[a];
- if (face.mNumIndices <= 4) {
- get_normals = false;
- }
- if( face.mNumIndices <= 3) {
- numOut++;
-
- }
- else {
- numOut += face.mNumIndices-2;
- max_out = std::max(max_out,face.mNumIndices);
- }
- }
-
- // Just another check whether aiMesh::mPrimitiveTypes is correct
- assert(numOut != pMesh->mNumFaces);
-
- aiVector3D* nor_out = NULL;
-
- // if we don't have normals yet, but expect them to be a cheap side
- // product of triangulation anyway, allocate storage for them.
- if (!pMesh->mNormals && get_normals) {
- // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
- // nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
- }
-
- // the output mesh will contain triangles, but no polys anymore
- pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
- pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
-
- aiFace* out = new aiFace[numOut](), *curOut = out;
- std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
- std::vector<aiVector2D> temp_verts(max_out+2);
-
- // Apply vertex colors to represent the face winding?
+ // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases
+ if (!pMesh->mPrimitiveTypes) {
+ bool bNeed = false;
+
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ const aiFace& face = pMesh->mFaces[a];
+
+ if( face.mNumIndices != 3) {
+ bNeed = true;
+ }
+ }
+ if (!bNeed)
+ return false;
+ }
+ else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) {
+ return false;
+ }
+
+ // Find out how many output faces we'll get
+ unsigned int numOut = 0, max_out = 0;
+ bool get_normals = true;
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ aiFace& face = pMesh->mFaces[a];
+ if (face.mNumIndices <= 4) {
+ get_normals = false;
+ }
+ if( face.mNumIndices <= 3) {
+ numOut++;
+
+ }
+ else {
+ numOut += face.mNumIndices-2;
+ max_out = std::max(max_out,face.mNumIndices);
+ }
+ }
+
+ // Just another check whether aiMesh::mPrimitiveTypes is correct
+ assert(numOut != pMesh->mNumFaces);
+
+ aiVector3D* nor_out = NULL;
+
+ // if we don't have normals yet, but expect them to be a cheap side
+ // product of triangulation anyway, allocate storage for them.
+ if (!pMesh->mNormals && get_normals) {
+ // XXX need a mechanism to inform the GenVertexNormals process to treat these normals as preprocessed per-face normals
+ // nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+ }
+
+ // the output mesh will contain triangles, but no polys anymore
+ pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON;
+
+ aiFace* out = new aiFace[numOut](), *curOut = out;
+ std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
+ std::vector<aiVector2D> temp_verts(max_out+2);
+
+ // Apply vertex colors to represent the face winding?
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
- if (!pMesh->mColors[0])
- pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
- else
- new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
+ if (!pMesh->mColors[0])
+ pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices];
+ else
+ new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices];
- aiColor4D* clr = pMesh->mColors[0];
+ aiColor4D* clr = pMesh->mColors[0];
#endif
-
+
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
- FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
+ FILE* fout = fopen(POLY_OUTPUT_FILE,"a");
#endif
- const aiVector3D* verts = pMesh->mVertices;
+ const aiVector3D* verts = pMesh->mVertices;
- // use boost::scoped_array to avoid slow std::vector<bool> specialiations
- boost::scoped_array<bool> done(new bool[max_out]);
- for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
- aiFace& face = pMesh->mFaces[a];
+ // use std::unique_ptr to avoid slow std::vector<bool> specialiations
+ std::unique_ptr<bool[]> done(new bool[max_out]);
+ for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
+ aiFace& face = pMesh->mFaces[a];
- unsigned int* idx = face.mIndices;
- int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
+ unsigned int* idx = face.mIndices;
+ int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
- // Apply vertex colors to represent the face winding?
+ // Apply vertex colors to represent the face winding?
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
- for (unsigned int i = 0; i < face.mNumIndices; ++i) {
- aiColor4D& c = clr[idx[i]];
- c.r = (i+1) / (float)max;
- c.b = 1.f - c.r;
- }
+ for (unsigned int i = 0; i < face.mNumIndices; ++i) {
+ aiColor4D& c = clr[idx[i]];
+ c.r = (i+1) / (float)max;
+ c.b = 1.f - c.r;
+ }
#endif
- aiFace* const last_face = curOut;
-
- // if it's a simple point,line or triangle: just copy it
- if( face.mNumIndices <= 3)
- {
- aiFace& nface = *curOut++;
- nface.mNumIndices = face.mNumIndices;
- nface.mIndices = face.mIndices;
-
- face.mIndices = NULL;
- continue;
- }
- // optimized code for quadrilaterals
- else if ( face.mNumIndices == 4) {
-
- // quads can have at maximum one concave vertex. Determine
- // this vertex (if it exists) and start tri-fanning from
- // it.
- unsigned int start_vertex = 0;
- for (unsigned int i = 0; i < 4; ++i) {
- const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
- const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
- const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
-
- const aiVector3D& v = verts[face.mIndices[i]];
-
- aiVector3D left = (v0-v);
- aiVector3D diag = (v1-v);
- aiVector3D right = (v2-v);
-
- left.Normalize();
- diag.Normalize();
- right.Normalize();
-
- const float angle = std::acos(left*diag) + std::acos(right*diag);
- if (angle > AI_MATH_PI_F) {
- // this is the concave point
- start_vertex = i;
- break;
- }
- }
-
- const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
-
- aiFace& nface = *curOut++;
- nface.mNumIndices = 3;
- nface.mIndices = face.mIndices;
-
- nface.mIndices[0] = temp[start_vertex];
- nface.mIndices[1] = temp[(start_vertex + 1) % 4];
- nface.mIndices[2] = temp[(start_vertex + 2) % 4];
-
- aiFace& sface = *curOut++;
- sface.mNumIndices = 3;
- sface.mIndices = new unsigned int[3];
-
- sface.mIndices[0] = temp[start_vertex];
- sface.mIndices[1] = temp[(start_vertex + 2) % 4];
- sface.mIndices[2] = temp[(start_vertex + 3) % 4];
-
- // prevent double deletion of the indices field
- face.mIndices = NULL;
- continue;
- }
- else
- {
- // A polygon with more than 3 vertices can be either concave or convex.
- // Usually everything we're getting is convex and we could easily
- // triangulate by trifanning. However, LightWave is probably the only
- // modeling suite to make extensive use of highly concave, monster polygons ...
- // so we need to apply the full 'ear cutting' algorithm to get it right.
-
- // RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
- // We project it onto a plane to get a 2d triangle.
-
- // Collect all vertices of of the polygon.
- for (tmp = 0; tmp < max; ++tmp) {
- temp_verts3d[tmp] = verts[idx[tmp]];
- }
-
- // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
- aiVector3D n;
- NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
- if (nor_out) {
- for (tmp = 0; tmp < max; ++tmp)
- nor_out[idx[tmp]] = n;
- }
-
- // Select largest normal coordinate to ignore for projection
- const float ax = (n.x>0 ? n.x : -n.x);
- const float ay = (n.y>0 ? n.y : -n.y);
- const float az = (n.z>0 ? n.z : -n.z);
-
- unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
- float inv = n.z;
- if (ax > ay) {
- if (ax > az) { /* no x coord. projection to yz */
- ac = 1; bc = 2;
- inv = n.x;
- }
- }
- else if (ay > az) { /* no y coord. projection to zy */
- ac = 2; bc = 0;
- inv = n.y;
- }
-
- // Swap projection axes to take the negated projection vector into account
- if (inv < 0.f) {
- std::swap(ac,bc);
- }
-
- for (tmp =0; tmp < max; ++tmp) {
- temp_verts[tmp].x = verts[idx[tmp]][ac];
- temp_verts[tmp].y = verts[idx[tmp]][bc];
- done[tmp] = false;
- }
-
-
+ aiFace* const last_face = curOut;
+
+ // if it's a simple point,line or triangle: just copy it
+ if( face.mNumIndices <= 3)
+ {
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = face.mNumIndices;
+ nface.mIndices = face.mIndices;
+
+ face.mIndices = NULL;
+ continue;
+ }
+ // optimized code for quadrilaterals
+ else if ( face.mNumIndices == 4) {
+
+ // quads can have at maximum one concave vertex. Determine
+ // this vertex (if it exists) and start tri-fanning from
+ // it.
+ unsigned int start_vertex = 0;
+ for (unsigned int i = 0; i < 4; ++i) {
+ const aiVector3D& v0 = verts[face.mIndices[(i+3) % 4]];
+ const aiVector3D& v1 = verts[face.mIndices[(i+2) % 4]];
+ const aiVector3D& v2 = verts[face.mIndices[(i+1) % 4]];
+
+ const aiVector3D& v = verts[face.mIndices[i]];
+
+ aiVector3D left = (v0-v);
+ aiVector3D diag = (v1-v);
+ aiVector3D right = (v2-v);
+
+ left.Normalize();
+ diag.Normalize();
+ right.Normalize();
+
+ const float angle = std::acos(left*diag) + std::acos(right*diag);
+ if (angle > AI_MATH_PI_F) {
+ // this is the concave point
+ start_vertex = i;
+ break;
+ }
+ }
+
+ const unsigned int temp[] = {face.mIndices[0], face.mIndices[1], face.mIndices[2], face.mIndices[3]};
+
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+ nface.mIndices = face.mIndices;
+
+ nface.mIndices[0] = temp[start_vertex];
+ nface.mIndices[1] = temp[(start_vertex + 1) % 4];
+ nface.mIndices[2] = temp[(start_vertex + 2) % 4];
+
+ aiFace& sface = *curOut++;
+ sface.mNumIndices = 3;
+ sface.mIndices = new unsigned int[3];
+
+ sface.mIndices[0] = temp[start_vertex];
+ sface.mIndices[1] = temp[(start_vertex + 2) % 4];
+ sface.mIndices[2] = temp[(start_vertex + 3) % 4];
+
+ // prevent double deletion of the indices field
+ face.mIndices = NULL;
+ continue;
+ }
+ else
+ {
+ // A polygon with more than 3 vertices can be either concave or convex.
+ // Usually everything we're getting is convex and we could easily
+ // triangulate by trifanning. However, LightWave is probably the only
+ // modeling suite to make extensive use of highly concave, monster polygons ...
+ // so we need to apply the full 'ear cutting' algorithm to get it right.
+
+ // RERQUIREMENT: polygon is expected to be simple and *nearly* planar.
+ // We project it onto a plane to get a 2d triangle.
+
+ // Collect all vertices of of the polygon.
+ for (tmp = 0; tmp < max; ++tmp) {
+ temp_verts3d[tmp] = verts[idx[tmp]];
+ }
+
+ // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
+ aiVector3D n;
+ NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
+ if (nor_out) {
+ for (tmp = 0; tmp < max; ++tmp)
+ nor_out[idx[tmp]] = n;
+ }
+
+ // Select largest normal coordinate to ignore for projection
+ const float ax = (n.x>0 ? n.x : -n.x);
+ const float ay = (n.y>0 ? n.y : -n.y);
+ const float az = (n.z>0 ? n.z : -n.z);
+
+ unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */
+ float inv = n.z;
+ if (ax > ay) {
+ if (ax > az) { /* no x coord. projection to yz */
+ ac = 1; bc = 2;
+ inv = n.x;
+ }
+ }
+ else if (ay > az) { /* no y coord. projection to zy */
+ ac = 2; bc = 0;
+ inv = n.y;
+ }
+
+ // Swap projection axes to take the negated projection vector into account
+ if (inv < 0.f) {
+ std::swap(ac,bc);
+ }
+
+ for (tmp =0; tmp < max; ++tmp) {
+ temp_verts[tmp].x = verts[idx[tmp]][ac];
+ temp_verts[tmp].y = verts[idx[tmp]][bc];
+ done[tmp] = false;
+ }
+
+
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
- // plot the plane onto which we mapped the polygon to a 2D ASCII pic
- aiVector2D bmin,bmax;
- ArrayBounds(&temp_verts[0],max,bmin,bmax);
-
- char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
- std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
-
- for (int i =0; i < max; ++i) {
- const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
- const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
- char* loc = grid[y]+x;
- if (grid[y][x] != ' ') {
- for(;*loc != ' '; ++loc);
- *loc++ = '_';
- }
- *(loc+sprintf(loc,"%i",i)) = ' ';
- }
-
-
- for(size_t y = 0; y < POLY_GRID_Y; ++y) {
- grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
- fprintf(fout,"%s\n",grid[y]);
- }
-
- fprintf(fout,"\ntriangulation sequence: ");
+ // plot the plane onto which we mapped the polygon to a 2D ASCII pic
+ aiVector2D bmin,bmax;
+ ArrayBounds(&temp_verts[0],max,bmin,bmax);
+
+ char grid[POLY_GRID_Y][POLY_GRID_X+POLY_GRID_XPAD];
+ std::fill_n((char*)grid,POLY_GRID_Y*(POLY_GRID_X+POLY_GRID_XPAD),' ');
+
+ for (int i =0; i < max; ++i) {
+ const aiVector2D& v = (temp_verts[i] - bmin) / (bmax-bmin);
+ const size_t x = static_cast<size_t>(v.x*(POLY_GRID_X-1)), y = static_cast<size_t>(v.y*(POLY_GRID_Y-1));
+ char* loc = grid[y]+x;
+ if (grid[y][x] != ' ') {
+ for(;*loc != ' '; ++loc);
+ *loc++ = '_';
+ }
+ *(loc+::ai_snprintf(loc, POLY_GRID_XPAD,"%i",i)) = ' ';
+ }
+
+
+ for(size_t y = 0; y < POLY_GRID_Y; ++y) {
+ grid[y][POLY_GRID_X+POLY_GRID_XPAD-1] = '\0';
+ fprintf(fout,"%s\n",grid[y]);
+ }
+
+ fprintf(fout,"\ntriangulation sequence: ");
#endif
- //
- // FIXME: currently this is the slow O(kn) variant with a worst case
- // complexity of O(n^2) (I think). Can be done in O(n).
- while (num > 3) {
-
- // Find the next ear of the polygon
- int num_found = 0;
- for (ear = next;;prev = ear,ear = next) {
-
- // break after we looped two times without a positive match
- for (next=ear+1;done[(next>=max?next=0:next)];++next);
- if (next < ear) {
- if (++num_found == 2) {
- break;
- }
- }
- const aiVector2D* pnt1 = &temp_verts[ear],
- *pnt0 = &temp_verts[prev],
- *pnt2 = &temp_verts[next];
-
- // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
- if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
- continue;
- }
-
- // and no other point may be contained in this triangle
- for ( tmp = 0; tmp < max; ++tmp) {
-
- // We need to compare the actual values because it's possible that multiple indexes in
- // the polygon are referring to the same position. concave_polygon.obj is a sample
- //
- // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
- // PointInTriangle() I'm guessing that it's actually possible to construct
- // input data that would cause us to end up with no ears. The problem is,
- // which epsilon? If we chose a too large value, we'd get wrong results
- const aiVector2D& vtmp = temp_verts[tmp];
- if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
- break;
- }
- }
- if (tmp != max) {
- continue;
- }
-
- // this vertex is an ear
- break;
- }
- if (num_found == 2) {
-
- // Due to the 'two ear theorem', every simple polygon with more than three points must
- // have 2 'ears'. Here's definitely someting wrong ... but we don't give up yet.
- //
-
- // Instead we're continuting with the standard trifanning algorithm which we'd
- // use if we had only convex polygons. That's life.
- DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
-
+ //
+ // FIXME: currently this is the slow O(kn) variant with a worst case
+ // complexity of O(n^2) (I think). Can be done in O(n).
+ while (num > 3) {
+
+ // Find the next ear of the polygon
+ int num_found = 0;
+ for (ear = next;;prev = ear,ear = next) {
+
+ // break after we looped two times without a positive match
+ for (next=ear+1;done[(next>=max?next=0:next)];++next);
+ if (next < ear) {
+ if (++num_found == 2) {
+ break;
+ }
+ }
+ const aiVector2D* pnt1 = &temp_verts[ear],
+ *pnt0 = &temp_verts[prev],
+ *pnt2 = &temp_verts[next];
+
+ // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
+ if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1)) {
+ continue;
+ }
+
+ // and no other point may be contained in this triangle
+ for ( tmp = 0; tmp < max; ++tmp) {
+
+ // We need to compare the actual values because it's possible that multiple indexes in
+ // the polygon are referring to the same position. concave_polygon.obj is a sample
+ //
+ // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
+ // PointInTriangle() I'm guessing that it's actually possible to construct
+ // input data that would cause us to end up with no ears. The problem is,
+ // which epsilon? If we chose a too large value, we'd get wrong results
+ const aiVector2D& vtmp = temp_verts[tmp];
+ if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
+ break;
+ }
+ }
+ if (tmp != max) {
+ continue;
+ }
+
+ // this vertex is an ear
+ break;
+ }
+ if (num_found == 2) {
+
+ // Due to the 'two ear theorem', every simple polygon with more than three points must
+ // have 2 'ears'. Here's definitely someting wrong ... but we don't give up yet.
+ //
+
+ // Instead we're continuting with the standard trifanning algorithm which we'd
+ // use if we had only convex polygons. That's life.
+ DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
+
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
- fprintf(fout,"critical error here, no ear found! ");
+ fprintf(fout,"critical error here, no ear found! ");
#endif
- num = 0;
- break;
-
- curOut -= (max-num); /* undo all previous work */
- for (tmp = 0; tmp < max-2; ++tmp) {
- aiFace& nface = *curOut++;
-
- nface.mNumIndices = 3;
- if (!nface.mIndices)
- nface.mIndices = new unsigned int[3];
-
- nface.mIndices[0] = 0;
- nface.mIndices[1] = tmp+1;
- nface.mIndices[2] = tmp+2;
-
- }
- num = 0;
- break;
- }
-
- aiFace& nface = *curOut++;
- nface.mNumIndices = 3;
-
- if (!nface.mIndices) {
- nface.mIndices = new unsigned int[3];
- }
-
- // setup indices for the new triangle ...
- nface.mIndices[0] = prev;
- nface.mIndices[1] = ear;
- nface.mIndices[2] = next;
-
- // exclude the ear from most further processing
- done[ear] = true;
- --num;
- }
- if (num > 0) {
- // We have three indices forming the last 'ear' remaining. Collect them.
- aiFace& nface = *curOut++;
- nface.mNumIndices = 3;
- if (!nface.mIndices) {
- nface.mIndices = new unsigned int[3];
- }
-
- for (tmp = 0; done[tmp]; ++tmp);
- nface.mIndices[0] = tmp;
-
- for (++tmp; done[tmp]; ++tmp);
- nface.mIndices[1] = tmp;
-
- for (++tmp; done[tmp]; ++tmp);
- nface.mIndices[2] = tmp;
-
- }
- }
+ num = 0;
+ break;
+
+ curOut -= (max-num); /* undo all previous work */
+ for (tmp = 0; tmp < max-2; ++tmp) {
+ aiFace& nface = *curOut++;
+
+ nface.mNumIndices = 3;
+ if (!nface.mIndices)
+ nface.mIndices = new unsigned int[3];
+
+ nface.mIndices[0] = 0;
+ nface.mIndices[1] = tmp+1;
+ nface.mIndices[2] = tmp+2;
+
+ }
+ num = 0;
+ break;
+ }
+
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+
+ if (!nface.mIndices) {
+ nface.mIndices = new unsigned int[3];
+ }
+
+ // setup indices for the new triangle ...
+ nface.mIndices[0] = prev;
+ nface.mIndices[1] = ear;
+ nface.mIndices[2] = next;
+
+ // exclude the ear from most further processing
+ done[ear] = true;
+ --num;
+ }
+ if (num > 0) {
+ // We have three indices forming the last 'ear' remaining. Collect them.
+ aiFace& nface = *curOut++;
+ nface.mNumIndices = 3;
+ if (!nface.mIndices) {
+ nface.mIndices = new unsigned int[3];
+ }
+
+ for (tmp = 0; done[tmp]; ++tmp);
+ nface.mIndices[0] = tmp;
+
+ for (++tmp; done[tmp]; ++tmp);
+ nface.mIndices[1] = tmp;
+
+ for (++tmp; done[tmp]; ++tmp);
+ nface.mIndices[2] = tmp;
+
+ }
+ }
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
-
- for(aiFace* f = last_face; f != curOut; ++f) {
- unsigned int* i = f->mIndices;
- fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
- }
-
- fprintf(fout,"\n*********************************************************************\n");
- fflush(fout);
-
+
+ for(aiFace* f = last_face; f != curOut; ++f) {
+ unsigned int* i = f->mIndices;
+ fprintf(fout," (%i %i %i)",i[0],i[1],i[2]);
+ }
+
+ fprintf(fout,"\n*********************************************************************\n");
+ fflush(fout);
+
#endif
- for(aiFace* f = last_face; f != curOut; ) {
- unsigned int* i = f->mIndices;
+ for(aiFace* f = last_face; f != curOut; ) {
+ unsigned int* i = f->mIndices;
- // drop dumb 0-area triangles
- if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
- DefaultLogger::get()->debug("Dropping triangle with area 0");
- --curOut;
+ // drop dumb 0-area triangles
+ if (std::fabs(GetArea2D(temp_verts[i[0]],temp_verts[i[1]],temp_verts[i[2]])) < 1e-5f) {
+ DefaultLogger::get()->debug("Dropping triangle with area 0");
+ --curOut;
- delete[] f->mIndices;
- f->mIndices = NULL;
+ delete[] f->mIndices;
+ f->mIndices = NULL;
- for(aiFace* ff = f; ff != curOut; ++ff) {
- ff->mNumIndices = (ff+1)->mNumIndices;
- ff->mIndices = (ff+1)->mIndices;
- (ff+1)->mIndices = NULL;
- }
- continue;
- }
+ for(aiFace* ff = f; ff != curOut; ++ff) {
+ ff->mNumIndices = (ff+1)->mNumIndices;
+ ff->mIndices = (ff+1)->mIndices;
+ (ff+1)->mIndices = NULL;
+ }
+ continue;
+ }
- i[0] = idx[i[0]];
- i[1] = idx[i[1]];
- i[2] = idx[i[2]];
- ++f;
- }
+ i[0] = idx[i[0]];
+ i[1] = idx[i[1]];
+ i[2] = idx[i[2]];
+ ++f;
+ }
- delete[] face.mIndices;
- face.mIndices = NULL;
- }
+ delete[] face.mIndices;
+ face.mIndices = NULL;
+ }
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
- fclose(fout);
+ fclose(fout);
#endif
- // kill the old faces
- delete [] pMesh->mFaces;
+ // kill the old faces
+ delete [] pMesh->mFaces;
- // ... and store the new ones
- pMesh->mFaces = out;
- pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
- return true;
+ // ... and store the new ones
+ pMesh->mFaces = out;
+ pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */
+ return true;
}
#endif // !! ASSIMP_BUILD_NO_TRIANGULATE_PROCESS
diff --git a/src/3rdparty/assimp/code/TriangulateProcess.h b/src/3rdparty/assimp/code/TriangulateProcess.h
index a75c8d822..97b5004e1 100644
--- a/src/3rdparty/assimp/code/TriangulateProcess.h
+++ b/src/3rdparty/assimp/code/TriangulateProcess.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,22 +23,22 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Defines a post processing step to triangulate all faces
+/** @file Defines a post processing step to triangulate all faces
with more than three vertices.
*/
#ifndef AI_TRIANGULATEPROCESS_H_INC
@@ -61,31 +61,31 @@ class ASSIMP_API TriangulateProcess : public BaseProcess
{
public:
- TriangulateProcess();
- ~TriangulateProcess();
+ TriangulateProcess();
+ ~TriangulateProcess();
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);
+ // -------------------------------------------------------------------
+ /** 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);
public:
- // -------------------------------------------------------------------
- /** Triangulates the given mesh.
- * @param pMesh The mesh to triangulate.
- */
- bool TriangulateMesh( aiMesh* pMesh);
+ // -------------------------------------------------------------------
+ /** Triangulates the given mesh.
+ * @param pMesh The mesh to triangulate.
+ */
+ bool TriangulateMesh( aiMesh* pMesh);
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/UnrealLoader.cpp b/src/3rdparty/assimp/code/UnrealLoader.cpp
index df1796042..ad839fb25 100644
--- a/src/3rdparty/assimp/code/UnrealLoader.cpp
+++ b/src/3rdparty/assimp/code/UnrealLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_3D_IMPORTER
@@ -56,384 +56,387 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "fast_atof.h"
#include "ConvertToLHProcess.h"
+#include <assimp/Importer.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+
+#include <memory>
+
using namespace Assimp;
static const aiImporterDesc desc = {
- "Unreal Mesh Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "3d uc"
+ "Unreal Mesh Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "3d uc"
};
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
UnrealImporter::UnrealImporter()
-: configFrameID (0)
-, configHandleFlags (true)
+: configFrameID (0)
+, configHandleFlags (true)
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
UnrealImporter::~UnrealImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool UnrealImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
{
- return SimpleExtensionCheck(pFile,"3d","uc");
+ return SimpleExtensionCheck(pFile,"3d","uc");
}
// ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported
const aiImporterDesc* UnrealImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void UnrealImporter::SetupProperties(const Importer* pImp)
{
- // The
- // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the
- // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1);
- if(static_cast<unsigned int>(-1) == configFrameID) {
- configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
- }
-
- // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true
- configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1));
+ // The
+ // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the
+ // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1);
+ if(static_cast<unsigned int>(-1) == configFrameID) {
+ configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+ }
+
+ // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true
+ configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1));
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void UnrealImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void UnrealImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
- // For any of the 3 files being passed get the three correct paths
- // First of all, determine file extension
- std::string::size_type pos = pFile.find_last_of('.');
- std::string extension = GetExtension(pFile);
-
- std::string d_path,a_path,uc_path;
- if (extension == "3d") {
- // jjjj_d.3d
- // jjjj_a.3d
- pos = pFile.find_last_of('_');
- if (std::string::npos == pos) {
- throw DeadlyImportError("UNREAL: Unexpected naming scheme");
- }
- extension = pFile.substr(0,pos);
- }
- else {
- extension = pFile.substr(0,pos);
- }
-
- // build proper paths
- d_path = extension+"_d.3d";
- a_path = extension+"_a.3d";
- uc_path = extension+".uc";
-
- DefaultLogger::get()->debug("UNREAL: data file is " + d_path);
- DefaultLogger::get()->debug("UNREAL: aniv file is " + a_path);
- DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path);
-
- // and open the files ... we can't live without them
- IOStream* p = pIOHandler->Open(d_path);
- if (!p)
- throw DeadlyImportError("UNREAL: Unable to open _d file");
- StreamReaderLE d_reader(pIOHandler->Open(d_path));
-
- const uint16_t numTris = d_reader.GetI2();
- const uint16_t numVert = d_reader.GetI2();
- d_reader.IncPtr(44);
- if (!numTris || numVert < 3)
- throw DeadlyImportError("UNREAL: Invalid number of vertices/triangles");
-
- // maximum texture index
- unsigned int maxTexIdx = 0;
-
- // collect triangles
- std::vector<Unreal::Triangle> triangles(numTris);
- for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
- Unreal::Triangle& tri = *it;
-
- for (unsigned int i = 0; i < 3;++i) {
-
- tri.mVertex[i] = d_reader.GetI2();
- if (tri.mVertex[i] >= numTris) {
- DefaultLogger::get()->warn("UNREAL: vertex index out of range");
- tri.mVertex[i] = 0;
- }
- }
- tri.mType = d_reader.GetI1();
-
- // handle mesh flagss?
- if (configHandleFlags)
- tri.mType = Unreal::MF_NORMAL_OS;
- else {
- // ignore MOD and MASKED for the moment, treat them as two-sided
- if (tri.mType == Unreal::MF_NORMAL_MOD_TS || tri.mType == Unreal::MF_NORMAL_MASKED_TS)
- tri.mType = Unreal::MF_NORMAL_TS;
- }
- d_reader.IncPtr(1);
-
- for (unsigned int i = 0; i < 3;++i)
- for (unsigned int i2 = 0; i2 < 2;++i2)
- tri.mTex[i][i2] = d_reader.GetI1();
-
- tri.mTextureNum = d_reader.GetI1();
- maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum);
- d_reader.IncPtr(1);
- }
-
- p = pIOHandler->Open(a_path);
- if (!p)
- throw DeadlyImportError("UNREAL: Unable to open _a file");
- StreamReaderLE a_reader(pIOHandler->Open(a_path));
-
- // read number of frames
- const uint32_t numFrames = a_reader.GetI2();
- if (configFrameID >= numFrames)
- throw DeadlyImportError("UNREAL: The requested frame does not exist");
-
- uint32_t st = a_reader.GetI2();
- if (st != numVert*4)
- throw DeadlyImportError("UNREAL: Unexpected aniv file length");
-
- // skip to our frame
- a_reader.IncPtr(configFrameID *numVert*4);
-
- // collect vertices
- std::vector<aiVector3D> vertices(numVert);
- for (std::vector<aiVector3D>::iterator it = vertices.begin(), end = vertices.end(); it != end; ++it) {
- int32_t val = a_reader.GetI4();
- Unreal::DecompressVertex(*it,val);
- }
-
- // list of textures.
- std::vector< std::pair<unsigned int, std::string> > textures;
-
- // allocate the output scene
- aiNode* nd = pScene->mRootNode = new aiNode();
- nd->mName.Set("<UnrealRoot>");
-
- // we can live without the uc file if necessary
- boost::scoped_ptr<IOStream> pb (pIOHandler->Open(uc_path));
- if (pb.get()) {
-
- std::vector<char> _data;
- TextFileToBuffer(pb.get(),_data);
- const char* data = &_data[0];
-
- std::vector< std::pair< std::string,std::string > > tempTextures;
-
- // do a quick search in the UC file for some known, usually texture-related, tags
- for (;*data;++data) {
- if (TokenMatchI(data,"#exec",5)) {
- SkipSpacesAndLineEnd(&data);
-
- // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...]
- if (TokenMatchI(data,"TEXTURE",7)) {
- SkipSpacesAndLineEnd(&data);
-
- if (TokenMatchI(data,"IMPORT",6)) {
- tempTextures.push_back(std::pair< std::string,std::string >());
- std::pair< std::string,std::string >& me = tempTextures.back();
- for (;!IsLineEnd(*data);++data) {
- if (!::ASSIMP_strincmp(data,"NAME=",5)) {
- const char *d = data+=5;
- for (;!IsSpaceOrNewLine(*data);++data);
- me.first = std::string(d,(size_t)(data-d));
- }
- else if (!::ASSIMP_strincmp(data,"FILE=",5)) {
- const char *d = data+=5;
- for (;!IsSpaceOrNewLine(*data);++data);
- me.second = std::string(d,(size_t)(data-d));
- }
- }
- if (!me.first.length() || !me.second.length())
- tempTextures.pop_back();
- }
- }
- // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1
- // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2
- else if (TokenMatchI(data,"MESHMAP",7)) {
- SkipSpacesAndLineEnd(&data);
-
- if (TokenMatchI(data,"SETTEXTURE",10)) {
-
- textures.push_back(std::pair<unsigned int, std::string>());
- std::pair<unsigned int, std::string>& me = textures.back();
-
- for (;!IsLineEnd(*data);++data) {
- if (!::ASSIMP_strincmp(data,"NUM=",4)) {
- data += 4;
- me.first = strtoul10(data,&data);
- }
- else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) {
- data += 8;
- const char *d = data;
- for (;!IsSpaceOrNewLine(*data);++data);
- me.second = std::string(d,(size_t)(data-d));
-
- // try to find matching path names, doesn't care if we don't find them
- for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin();
- it != tempTextures.end(); ++it) {
- if ((*it).first == me.second) {
- me.second = (*it).second;
- break;
- }
- }
- }
- }
- }
- else if (TokenMatchI(data,"SCALE",5)) {
-
- for (;!IsLineEnd(*data);++data) {
- if (data[0] == 'X' && data[1] == '=') {
- data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1);
- }
- else if (data[0] == 'Y' && data[1] == '=') {
- data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2);
- }
- else if (data[0] == 'Z' && data[1] == '=') {
- data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3);
- }
- }
- }
- }
- }
- }
- }
- else {
- DefaultLogger::get()->error("Unable to open .uc file");
- }
-
- std::vector<Unreal::TempMat> materials;
- materials.reserve(textures.size()*2+5);
-
- // find out how many output meshes and materials we'll have and build material indices
- for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
- Unreal::Triangle& tri = *it;
- Unreal::TempMat mat(tri);
- std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
- if (nt == materials.end()) {
- // add material
- tri.matIndex = materials.size();
- mat.numFaces = 1;
- materials.push_back(mat);
-
- ++pScene->mNumMeshes;
- }
- else {
- tri.matIndex = static_cast<unsigned int>(nt-materials.begin());
- ++nt->numFaces;
- }
- }
-
- if (!pScene->mNumMeshes) {
- throw DeadlyImportError("UNREAL: Unable to find valid mesh data");
- }
-
- // allocate meshes and bind them to the node graph
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
-
- nd->mNumMeshes = pScene->mNumMeshes;
- nd->mMeshes = new unsigned int[nd->mNumMeshes];
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
- aiMesh* m = pScene->mMeshes[i] = new aiMesh();
- m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
- const unsigned int num = materials[i].numFaces;
- m->mFaces = new aiFace [num];
- m->mVertices = new aiVector3D [num*3];
- m->mTextureCoords[0] = new aiVector3D [num*3];
-
- nd->mMeshes[i] = i;
-
- // create materials, too
- aiMaterial* mat = new aiMaterial();
- pScene->mMaterials[i] = mat;
-
- // all white by default - texture rulez
- aiColor3D color(1.f,1.f,1.f);
-
- aiString s;
- ::sprintf(s.data,"mat%i_tx%i_",i,materials[i].tex);
-
- // set the two-sided flag
- if (materials[i].type == Unreal::MF_NORMAL_TS) {
- const int twosided = 1;
- mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
- ::strcat(s.data,"ts_");
- }
- else ::strcat(s.data,"os_");
-
- // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
- if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
- const float opac = 0.9f;
- mat->AddProperty(&opac,1,AI_MATKEY_OPACITY);
- ::strcat(s.data,"tran_");
- }
- else ::strcat(s.data,"opaq_");
-
- // a special name for the weapon attachment point
- if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
- s.length = ::sprintf(s.data,"$WeaponTag$");
- color = aiColor3D(0.f,0.f,0.f);
- }
-
- // set color and name
- mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE);
- s.length = ::strlen(s.data);
- mat->AddProperty(&s,AI_MATKEY_NAME);
-
- // set texture, if any
- const unsigned int tex = materials[i].tex;
- for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) {
- if ((*it).first == tex) {
- s.Set((*it).second);
- mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
- break;
- }
- }
- }
-
- // fill them.
- for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) {
- Unreal::Triangle& tri = *it;
- Unreal::TempMat mat(tri);
- std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
-
- aiMesh* mesh = pScene->mMeshes[nt-materials.begin()];
- aiFace& f = mesh->mFaces[mesh->mNumFaces++];
- f.mIndices = new unsigned int[f.mNumIndices = 3];
-
- for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) {
- f.mIndices[i] = mesh->mNumVertices;
-
- mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ];
- mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
- }
- }
-
- // convert to RH
- MakeLeftHandedProcess hero;
- hero.Execute(pScene);
-
- FlipWindingOrderProcess flipper;
- flipper.Execute(pScene);
+ // For any of the 3 files being passed get the three correct paths
+ // First of all, determine file extension
+ std::string::size_type pos = pFile.find_last_of('.');
+ std::string extension = GetExtension(pFile);
+
+ std::string d_path,a_path,uc_path;
+ if (extension == "3d") {
+ // jjjj_d.3d
+ // jjjj_a.3d
+ pos = pFile.find_last_of('_');
+ if (std::string::npos == pos) {
+ throw DeadlyImportError("UNREAL: Unexpected naming scheme");
+ }
+ extension = pFile.substr(0,pos);
+ }
+ else {
+ extension = pFile.substr(0,pos);
+ }
+
+ // build proper paths
+ d_path = extension+"_d.3d";
+ a_path = extension+"_a.3d";
+ uc_path = extension+".uc";
+
+ DefaultLogger::get()->debug("UNREAL: data file is " + d_path);
+ DefaultLogger::get()->debug("UNREAL: aniv file is " + a_path);
+ DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path);
+
+ // and open the files ... we can't live without them
+ IOStream* p = pIOHandler->Open(d_path);
+ if (!p)
+ throw DeadlyImportError("UNREAL: Unable to open _d file");
+ StreamReaderLE d_reader(pIOHandler->Open(d_path));
+
+ const uint16_t numTris = d_reader.GetI2();
+ const uint16_t numVert = d_reader.GetI2();
+ d_reader.IncPtr(44);
+ if (!numTris || numVert < 3)
+ throw DeadlyImportError("UNREAL: Invalid number of vertices/triangles");
+
+ // maximum texture index
+ unsigned int maxTexIdx = 0;
+
+ // collect triangles
+ std::vector<Unreal::Triangle> triangles(numTris);
+ for (auto & tri : triangles) {
+ for (unsigned int i = 0; i < 3;++i) {
+
+ tri.mVertex[i] = d_reader.GetI2();
+ if (tri.mVertex[i] >= numTris) {
+ DefaultLogger::get()->warn("UNREAL: vertex index out of range");
+ tri.mVertex[i] = 0;
+ }
+ }
+ tri.mType = d_reader.GetI1();
+
+ // handle mesh flagss?
+ if (configHandleFlags)
+ tri.mType = Unreal::MF_NORMAL_OS;
+ else {
+ // ignore MOD and MASKED for the moment, treat them as two-sided
+ if (tri.mType == Unreal::MF_NORMAL_MOD_TS || tri.mType == Unreal::MF_NORMAL_MASKED_TS)
+ tri.mType = Unreal::MF_NORMAL_TS;
+ }
+ d_reader.IncPtr(1);
+
+ for (unsigned int i = 0; i < 3;++i)
+ for (unsigned int i2 = 0; i2 < 2;++i2)
+ tri.mTex[i][i2] = d_reader.GetI1();
+
+ tri.mTextureNum = d_reader.GetI1();
+ maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum);
+ d_reader.IncPtr(1);
+ }
+
+ p = pIOHandler->Open(a_path);
+ if (!p)
+ throw DeadlyImportError("UNREAL: Unable to open _a file");
+ StreamReaderLE a_reader(pIOHandler->Open(a_path));
+
+ // read number of frames
+ const uint32_t numFrames = a_reader.GetI2();
+ if (configFrameID >= numFrames)
+ throw DeadlyImportError("UNREAL: The requested frame does not exist");
+
+ uint32_t st = a_reader.GetI2();
+ if (st != numVert*4)
+ throw DeadlyImportError("UNREAL: Unexpected aniv file length");
+
+ // skip to our frame
+ a_reader.IncPtr(configFrameID *numVert*4);
+
+ // collect vertices
+ std::vector<aiVector3D> vertices(numVert);
+ for (auto &vertex : vertices) {
+ int32_t val = a_reader.GetI4();
+ Unreal::DecompressVertex(vertex ,val);
+ }
+
+ // list of textures.
+ std::vector< std::pair<unsigned int, std::string> > textures;
+
+ // allocate the output scene
+ aiNode* nd = pScene->mRootNode = new aiNode();
+ nd->mName.Set("<UnrealRoot>");
+
+ // we can live without the uc file if necessary
+ std::unique_ptr<IOStream> pb (pIOHandler->Open(uc_path));
+ if (pb.get()) {
+
+ std::vector<char> _data;
+ TextFileToBuffer(pb.get(),_data);
+ const char* data = &_data[0];
+
+ std::vector< std::pair< std::string,std::string > > tempTextures;
+
+ // do a quick search in the UC file for some known, usually texture-related, tags
+ for (;*data;++data) {
+ if (TokenMatchI(data,"#exec",5)) {
+ SkipSpacesAndLineEnd(&data);
+
+ // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...]
+ if (TokenMatchI(data,"TEXTURE",7)) {
+ SkipSpacesAndLineEnd(&data);
+
+ if (TokenMatchI(data,"IMPORT",6)) {
+ tempTextures.push_back(std::pair< std::string,std::string >());
+ std::pair< std::string,std::string >& me = tempTextures.back();
+ for (;!IsLineEnd(*data);++data) {
+ if (!::ASSIMP_strincmp(data,"NAME=",5)) {
+ const char *d = data+=5;
+ for (;!IsSpaceOrNewLine(*data);++data);
+ me.first = std::string(d,(size_t)(data-d));
+ }
+ else if (!::ASSIMP_strincmp(data,"FILE=",5)) {
+ const char *d = data+=5;
+ for (;!IsSpaceOrNewLine(*data);++data);
+ me.second = std::string(d,(size_t)(data-d));
+ }
+ }
+ if (!me.first.length() || !me.second.length())
+ tempTextures.pop_back();
+ }
+ }
+ // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1
+ // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2
+ else if (TokenMatchI(data,"MESHMAP",7)) {
+ SkipSpacesAndLineEnd(&data);
+
+ if (TokenMatchI(data,"SETTEXTURE",10)) {
+
+ textures.push_back(std::pair<unsigned int, std::string>());
+ std::pair<unsigned int, std::string>& me = textures.back();
+
+ for (;!IsLineEnd(*data);++data) {
+ if (!::ASSIMP_strincmp(data,"NUM=",4)) {
+ data += 4;
+ me.first = strtoul10(data,&data);
+ }
+ else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) {
+ data += 8;
+ const char *d = data;
+ for (;!IsSpaceOrNewLine(*data);++data);
+ me.second = std::string(d,(size_t)(data-d));
+
+ // try to find matching path names, doesn't care if we don't find them
+ for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin();
+ it != tempTextures.end(); ++it) {
+ if ((*it).first == me.second) {
+ me.second = (*it).second;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (TokenMatchI(data,"SCALE",5)) {
+
+ for (;!IsLineEnd(*data);++data) {
+ if (data[0] == 'X' && data[1] == '=') {
+ data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1);
+ }
+ else if (data[0] == 'Y' && data[1] == '=') {
+ data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2);
+ }
+ else if (data[0] == 'Z' && data[1] == '=') {
+ data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ DefaultLogger::get()->error("Unable to open .uc file");
+ }
+
+ std::vector<Unreal::TempMat> materials;
+ materials.reserve(textures.size()*2+5);
+
+ // find out how many output meshes and materials we'll have and build material indices
+ for (Unreal::Triangle &tri : triangles) {
+ Unreal::TempMat mat(tri);
+ std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
+ if (nt == materials.end()) {
+ // add material
+ tri.matIndex = materials.size();
+ mat.numFaces = 1;
+ materials.push_back(mat);
+
+ ++pScene->mNumMeshes;
+ }
+ else {
+ tri.matIndex = static_cast<unsigned int>(nt-materials.begin());
+ ++nt->numFaces;
+ }
+ }
+
+ if (!pScene->mNumMeshes) {
+ throw DeadlyImportError("UNREAL: Unable to find valid mesh data");
+ }
+
+ // allocate meshes and bind them to the node graph
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
+
+ nd->mNumMeshes = pScene->mNumMeshes;
+ nd->mMeshes = new unsigned int[nd->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ aiMesh* m = pScene->mMeshes[i] = new aiMesh();
+ m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ const unsigned int num = materials[i].numFaces;
+ m->mFaces = new aiFace [num];
+ m->mVertices = new aiVector3D [num*3];
+ m->mTextureCoords[0] = new aiVector3D [num*3];
+
+ nd->mMeshes[i] = i;
+
+ // create materials, too
+ aiMaterial* mat = new aiMaterial();
+ pScene->mMaterials[i] = mat;
+
+ // all white by default - texture rulez
+ aiColor3D color(1.f,1.f,1.f);
+
+ aiString s;
+ ::ai_snprintf( s.data, MAXLEN, "mat%u_tx%u_",i,materials[i].tex );
+
+ // set the two-sided flag
+ if (materials[i].type == Unreal::MF_NORMAL_TS) {
+ const int twosided = 1;
+ mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
+ ::strcat(s.data,"ts_");
+ }
+ else ::strcat(s.data,"os_");
+
+ // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
+ if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
+ const float opac = 0.9f;
+ mat->AddProperty(&opac,1,AI_MATKEY_OPACITY);
+ ::strcat(s.data,"tran_");
+ }
+ else ::strcat(s.data,"opaq_");
+
+ // a special name for the weapon attachment point
+ if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
+ s.length = ::ai_snprintf( s.data, MAXLEN, "$WeaponTag$" );
+ color = aiColor3D(0.f,0.f,0.f);
+ }
+
+ // set color and name
+ mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE);
+ s.length = ::strlen(s.data);
+ mat->AddProperty(&s,AI_MATKEY_NAME);
+
+ // set texture, if any
+ const unsigned int tex = materials[i].tex;
+ for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) {
+ if ((*it).first == tex) {
+ s.Set((*it).second);
+ mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+ break;
+ }
+ }
+ }
+
+ // fill them.
+ for (const Unreal::Triangle &tri : triangles) {
+ Unreal::TempMat mat(tri);
+ std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
+
+ aiMesh* mesh = pScene->mMeshes[nt-materials.begin()];
+ aiFace& f = mesh->mFaces[mesh->mNumFaces++];
+ f.mIndices = new unsigned int[f.mNumIndices = 3];
+
+ for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) {
+ f.mIndices[i] = mesh->mNumVertices;
+
+ mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ];
+ mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
+ }
+ }
+
+ // convert to RH
+ MakeLeftHandedProcess hero;
+ hero.Execute(pScene);
+
+ FlipWindingOrderProcess flipper;
+ flipper.Execute(pScene);
}
#endif // !! ASSIMP_BUILD_NO_3D_IMPORTER
diff --git a/src/3rdparty/assimp/code/UnrealLoader.h b/src/3rdparty/assimp/code/UnrealLoader.h
index 805c8218a..93648ca82 100644
--- a/src/3rdparty/assimp/code/UnrealLoader.h
+++ b/src/3rdparty/assimp/code/UnrealLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,97 +45,101 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_3D_LOADER_H
#include "BaseImporter.h"
-namespace Assimp {
+#include <stdint.h>
+
+namespace Assimp {
namespace Unreal {
- /*
- 0 = Normal one-sided
- 1 = Normal two-sided
- 2 = Translucent two-sided
- 3 = Masked two-sided
- 4 = Modulation blended two-sided
- 8 = Placeholder triangle for weapon positioning (invisible)
- */
+ /*
+ 0 = Normal one-sided
+ 1 = Normal two-sided
+ 2 = Translucent two-sided
+ 3 = Masked two-sided
+ 4 = Modulation blended two-sided
+ 8 = Placeholder triangle for weapon positioning (invisible)
+ */
enum MeshFlags {
- MF_NORMAL_OS = 0,
- MF_NORMAL_TS = 1,
- MF_NORMAL_TRANS_TS = 2,
- MF_NORMAL_MASKED_TS = 3,
- MF_NORMAL_MOD_TS = 4,
- MF_WEAPON_PLACEHOLDER = 8
+ MF_NORMAL_OS = 0,
+ MF_NORMAL_TS = 1,
+ MF_NORMAL_TRANS_TS = 2,
+ MF_NORMAL_MASKED_TS = 3,
+ MF_NORMAL_MOD_TS = 4,
+ MF_WEAPON_PLACEHOLDER = 8
};
- // a single triangle
+ // a single triangle
struct Triangle {
- uint16_t mVertex[3]; // Vertex indices
+ uint16_t mVertex[3]; // Vertex indices
char mType; // James' Mesh Type
char mColor; // Color for flat and Gourand Shaded
unsigned char mTex[3][2]; // Texture UV coordinates
unsigned char mTextureNum; // Source texture offset
char mFlags; // Unreal Mesh Flags (unused)
-
+
unsigned int matIndex;
};
// temporary representation for a material
-struct TempMat {
- TempMat()
- : numFaces (0)
- {}
-
- TempMat(const Triangle& in)
- : type ((Unreal::MeshFlags)in.mType)
- , tex (in.mTextureNum)
- , numFaces (0)
- {}
-
- // type of mesh
- Unreal::MeshFlags type;
-
- // index of texture
- unsigned int tex;
-
- // number of faces using us
- unsigned int numFaces;
-
- // for std::find
- bool operator == (const TempMat& o ) {
- return (tex == o.tex && type == o.type);
- }
+struct TempMat {
+ TempMat()
+ : type()
+ , tex()
+ , numFaces (0)
+ {}
+
+ explicit TempMat(const Triangle& in)
+ : type ((Unreal::MeshFlags)in.mType)
+ , tex (in.mTextureNum)
+ , numFaces (0)
+ {}
+
+ // type of mesh
+ Unreal::MeshFlags type;
+
+ // index of texture
+ unsigned int tex;
+
+ // number of faces using us
+ unsigned int numFaces;
+
+ // for std::find
+ bool operator == (const TempMat& o ) {
+ return (tex == o.tex && type == o.type);
+ }
};
struct Vertex
{
- int32_t X : 11;
- int32_t Y : 11;
- int32_t Z : 10;
+ int32_t X : 11;
+ int32_t Y : 11;
+ int32_t Z : 10;
};
- // UNREAL vertex compression
+ // UNREAL vertex compression
inline void CompressVertex(const aiVector3D& v, uint32_t& out)
{
- union {
- Vertex n;
- int32_t t;
- };
- n.X = (int32_t)v.x;
- n.Y = (int32_t)v.y;
- n.Z = (int32_t)v.z;
- out = t;
+ union {
+ Vertex n;
+ int32_t t;
+ };
+ n.X = (int32_t)v.x;
+ n.Y = (int32_t)v.y;
+ n.Z = (int32_t)v.z;
+ out = t;
}
- // UNREAL vertex decompression
+ // UNREAL vertex decompression
inline void DecompressVertex(aiVector3D& v, int32_t in)
{
- union {
- Vertex n;
- int32_t i;
- };
- i = in;
-
- v.x = (float)n.X;
- v.y = (float)n.Y;
- v.z = (float)n.Z;
+ union {
+ Vertex n;
+ int32_t i;
+ };
+ i = in;
+
+ v.x = (float)n.X;
+ v.y = (float)n.Y;
+ v.z = (float)n.Z;
}
} // end namespace Unreal
@@ -146,53 +150,53 @@ inline void DecompressVertex(aiVector3D& v, int32_t in)
class UnrealImporter : public BaseImporter
{
public:
- UnrealImporter();
- ~UnrealImporter();
+ UnrealImporter();
+ ~UnrealImporter();
public:
- // -------------------------------------------------------------------
- /** @brief Returns whether we can handle the format of the given file
- *
- * See BaseImporter::CanRead() for details.
- **/
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** @brief Returns whether we can handle the format of the given file
+ *
+ * See BaseImporter::CanRead() for details.
+ **/
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** @brief Called by Importer::GetExtensionList()
- *
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** @brief Called by Importer::GetExtensionList()
+ *
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** @brief Setup properties for the importer
- *
- * See BaseImporter::SetupProperties() for details
- */
- void SetupProperties(const Importer* pImp);
+ // -------------------------------------------------------------------
+ /** @brief Setup properties for the importer
+ *
+ * See BaseImporter::SetupProperties() for details
+ */
+ void SetupProperties(const Importer* pImp);
- // -------------------------------------------------------------------
- /** @brief Imports the given file into the given scene structure.
- *
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** @brief Imports the given file into the given scene structure.
+ *
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- //! frame to be loaded
- uint32_t configFrameID;
+ //! frame to be loaded
+ uint32_t configFrameID;
- //! process surface flags
- bool configHandleFlags;
+ //! process surface flags
+ bool configHandleFlags;
}; // !class UnrealImporter
diff --git a/src/3rdparty/assimp/code/ValidateDataStructure.cpp b/src/3rdparty/assimp/code/ValidateDataStructure.cpp
index 20b0b1892..48647f344 100644
--- a/src/3rdparty/assimp/code/ValidateDataStructure.cpp
+++ b/src/3rdparty/assimp/code/ValidateDataStructure.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,32 +25,33 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file ValidateDataStructure.cpp
- * @brief Implementation of the post processing step to validate
+ * @brief Implementation of the post processing step to validate
* the data structure returned by Assimp.
*/
-#include "AssimpPCH.h"
+
// internal headers
#include "ValidateDataStructure.h"
#include "BaseImporter.h"
#include "fast_atof.h"
#include "ProcessHelper.h"
+#include <memory>
// CRT headers
#include <stdarg.h>
@@ -59,7 +60,8 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
-ValidateDSProcess::ValidateDSProcess()
+ValidateDSProcess::ValidateDSProcess() :
+ mScene()
{}
// ------------------------------------------------------------------------------------------------
@@ -71,898 +73,897 @@ ValidateDSProcess::~ValidateDSProcess()
// Returns whether the processing step is present in the given flag field.
bool ValidateDSProcess::IsActive( unsigned int pFlags) const
{
- return (pFlags & aiProcess_ValidateDataStructure) != 0;
+ return (pFlags & aiProcess_ValidateDataStructure) != 0;
}
// ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...)
{
- ai_assert(NULL != msg);
+ ai_assert(NULL != msg);
- va_list args;
- va_start(args,msg);
+ va_list args;
+ va_start(args,msg);
- char szBuffer[3000];
- const int iLen = vsprintf(szBuffer,msg,args);
- ai_assert(iLen > 0);
+ char szBuffer[3000];
+ const int iLen = vsprintf(szBuffer,msg,args);
+ ai_assert(iLen > 0);
- va_end(args);
+ va_end(args);
#ifdef ASSIMP_BUILD_DEBUG
- ai_assert( false );
+ ai_assert( false );
#endif
- throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen));
+ throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen));
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::ReportWarning(const char* msg,...)
{
- ai_assert(NULL != msg);
+ ai_assert(NULL != msg);
- va_list args;
- va_start(args,msg);
+ va_list args;
+ va_start(args,msg);
- char szBuffer[3000];
- const int iLen = vsprintf(szBuffer,msg,args);
- ai_assert(iLen > 0);
+ char szBuffer[3000];
+ const int iLen = vsprintf(szBuffer,msg,args);
+ ai_assert(iLen > 0);
- va_end(args);
- DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
+ va_end(args);
+ DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
}
// ------------------------------------------------------------------------------------------------
inline int HasNameMatch(const aiString& in, aiNode* node)
{
- int result = (node->mName == in ? 1 : 0 );
- for (unsigned int i = 0; i < node->mNumChildren;++i) {
- result += HasNameMatch(in,node->mChildren[i]);
- }
- return result;
+ int result = (node->mName == in ? 1 : 0 );
+ for (unsigned int i = 0; i < node->mNumChildren;++i) {
+ result += HasNameMatch(in,node->mChildren[i]);
+ }
+ return result;
}
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
- const char* firstName, const char* secondName)
+inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size,
+ const char* firstName, const char* secondName)
{
- // validate all entries
- if (size)
- {
- if (!parray)
- {
- ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
- firstName, secondName, size);
- }
- for (unsigned int i = 0; i < size;++i)
- {
- if (!parray[i])
- {
- ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
- firstName,i,secondName,size);
- }
- Validate(parray[i]);
- }
- }
+ // validate all entries
+ if (size)
+ {
+ if (!parray)
+ {
+ ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
+ firstName, secondName, size);
+ }
+ for (unsigned int i = 0; i < size;++i)
+ {
+ if (!parray[i])
+ {
+ ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
+ firstName,i,secondName,size);
+ }
+ Validate(parray[i]);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
- const char* firstName, const char* secondName)
+inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size,
+ const char* firstName, const char* secondName)
{
- // validate all entries
- if (size)
- {
- if (!parray) {
- ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
- firstName, secondName, size);
- }
- for (unsigned int i = 0; i < size;++i)
- {
- if (!parray[i])
- {
- ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
- firstName,i,secondName,size);
- }
- Validate(parray[i]);
-
- // check whether there are duplicate names
- for (unsigned int a = i+1; a < size;++a)
- {
- if (parray[i]->mName == parray[a]->mName)
- {
- this->ReportError("aiScene::%s[%i] has the same name as "
- "aiScene::%s[%i]",firstName, i,secondName, a);
- }
- }
- }
- }
+ // validate all entries
+ if (size)
+ {
+ if (!parray) {
+ ReportError("aiScene::%s is NULL (aiScene::%s is %i)",
+ firstName, secondName, size);
+ }
+ for (unsigned int i = 0; i < size;++i)
+ {
+ if (!parray[i])
+ {
+ ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)",
+ firstName,i,secondName,size);
+ }
+ Validate(parray[i]);
+
+ // check whether there are duplicate names
+ for (unsigned int a = i+1; a < size;++a)
+ {
+ if (parray[i]->mName == parray[a]->mName)
+ {
+ this->ReportError("aiScene::%s[%i] has the same name as "
+ "aiScene::%s[%i]",firstName, i,secondName, a);
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
template <typename T>
-inline void ValidateDSProcess::DoValidationWithNameCheck(T** array,
- unsigned int size, const char* firstName,
- const char* secondName)
+inline void ValidateDSProcess::DoValidationWithNameCheck(T** array,
+ unsigned int size, const char* firstName,
+ const char* secondName)
{
- // validate all entries
- DoValidationEx(array,size,firstName,secondName);
-
- for (unsigned int i = 0; i < size;++i)
- {
- int res = HasNameMatch(array[i]->mName,mScene->mRootNode);
- if (!res) {
- ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)",
- firstName,i,array[i]->mName.data);
- }
- else if (1 != res) {
- ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name",
- firstName,i,array[i]->mName.data);
- }
- }
+ // validate all entries
+ DoValidationEx(array,size,firstName,secondName);
+
+ for (unsigned int i = 0; i < size;++i)
+ {
+ int res = HasNameMatch(array[i]->mName,mScene->mRootNode);
+ if (!res) {
+ ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)",
+ firstName,i,array[i]->mName.data);
+ }
+ else if (1 != res) {
+ ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name",
+ firstName,i,array[i]->mName.data);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void ValidateDSProcess::Execute( aiScene* pScene)
{
- this->mScene = pScene;
- DefaultLogger::get()->debug("ValidateDataStructureProcess begin");
-
- // validate the node graph of the scene
- Validate(pScene->mRootNode);
-
- // validate all meshes
- if (pScene->mNumMeshes) {
- DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes");
- }
- else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
- ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
- }
- else if (pScene->mMeshes) {
- ReportError("aiScene::mMeshes is non-null although there are no meshes");
- }
-
- // validate all animations
- if (pScene->mNumAnimations) {
- DoValidation(pScene->mAnimations,pScene->mNumAnimations,
- "mAnimations","mNumAnimations");
- }
- else if (pScene->mAnimations) {
- ReportError("aiScene::mAnimations is non-null although there are no animations");
- }
-
- // validate all cameras
- if (pScene->mNumCameras) {
- DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras,
- "mCameras","mNumCameras");
- }
- else if (pScene->mCameras) {
- ReportError("aiScene::mCameras is non-null although there are no cameras");
- }
-
- // validate all lights
- if (pScene->mNumLights) {
- DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights,
- "mLights","mNumLights");
- }
- else if (pScene->mLights) {
- ReportError("aiScene::mLights is non-null although there are no lights");
- }
-
- // validate all textures
- if (pScene->mNumTextures) {
- DoValidation(pScene->mTextures,pScene->mNumTextures,
- "mTextures","mNumTextures");
- }
- else if (pScene->mTextures) {
- ReportError("aiScene::mTextures is non-null although there are no textures");
- }
-
- // validate all materials
- if (pScene->mNumMaterials) {
- DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials");
- }
+ this->mScene = pScene;
+ DefaultLogger::get()->debug("ValidateDataStructureProcess begin");
+
+ // validate the node graph of the scene
+ Validate(pScene->mRootNode);
+
+ // validate all meshes
+ if (pScene->mNumMeshes) {
+ DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes");
+ }
+ else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
+ ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
+ }
+ else if (pScene->mMeshes) {
+ ReportError("aiScene::mMeshes is non-null although there are no meshes");
+ }
+
+ // validate all animations
+ if (pScene->mNumAnimations) {
+ DoValidation(pScene->mAnimations,pScene->mNumAnimations,
+ "mAnimations","mNumAnimations");
+ }
+ else if (pScene->mAnimations) {
+ ReportError("aiScene::mAnimations is non-null although there are no animations");
+ }
+
+ // validate all cameras
+ if (pScene->mNumCameras) {
+ DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras,
+ "mCameras","mNumCameras");
+ }
+ else if (pScene->mCameras) {
+ ReportError("aiScene::mCameras is non-null although there are no cameras");
+ }
+
+ // validate all lights
+ if (pScene->mNumLights) {
+ DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights,
+ "mLights","mNumLights");
+ }
+ else if (pScene->mLights) {
+ ReportError("aiScene::mLights is non-null although there are no lights");
+ }
+
+ // validate all textures
+ if (pScene->mNumTextures) {
+ DoValidation(pScene->mTextures,pScene->mNumTextures,
+ "mTextures","mNumTextures");
+ }
+ else if (pScene->mTextures) {
+ ReportError("aiScene::mTextures is non-null although there are no textures");
+ }
+
+ // validate all materials
+ if (pScene->mNumMaterials) {
+ DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials");
+ }
#if 0
- // NOTE: ScenePreprocessor generates a default material if none is there
- else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
- ReportError("aiScene::mNumMaterials is 0. At least one material must be there");
- }
+ // NOTE: ScenePreprocessor generates a default material if none is there
+ else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) {
+ ReportError("aiScene::mNumMaterials is 0. At least one material must be there");
+ }
#endif
- else if (pScene->mMaterials) {
- ReportError("aiScene::mMaterials is non-null although there are no materials");
- }
+ else if (pScene->mMaterials) {
+ ReportError("aiScene::mMaterials is non-null although there are no materials");
+ }
-// if (!has)ReportError("The aiScene data structure is empty");
- DefaultLogger::get()->debug("ValidateDataStructureProcess end");
+// if (!has)ReportError("The aiScene data structure is empty");
+ DefaultLogger::get()->debug("ValidateDataStructureProcess end");
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiLight* pLight)
{
- if (pLight->mType == aiLightSource_UNDEFINED)
- ReportWarning("aiLight::mType is aiLightSource_UNDEFINED");
-
- if (!pLight->mAttenuationConstant &&
- !pLight->mAttenuationLinear &&
- !pLight->mAttenuationQuadratic) {
- ReportWarning("aiLight::mAttenuationXXX - all are zero");
- }
-
- if (pLight->mAngleInnerCone > pLight->mAngleOuterCone)
- ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone");
-
- if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack()
- && pLight->mColorSpecular.IsBlack())
- {
- ReportWarning("aiLight::mColorXXX - all are black and won't have any influence");
- }
+ if (pLight->mType == aiLightSource_UNDEFINED)
+ ReportWarning("aiLight::mType is aiLightSource_UNDEFINED");
+
+ if (!pLight->mAttenuationConstant &&
+ !pLight->mAttenuationLinear &&
+ !pLight->mAttenuationQuadratic) {
+ ReportWarning("aiLight::mAttenuationXXX - all are zero");
+ }
+
+ if (pLight->mAngleInnerCone > pLight->mAngleOuterCone)
+ ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone");
+
+ if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack()
+ && pLight->mColorSpecular.IsBlack())
+ {
+ ReportWarning("aiLight::mColorXXX - all are black and won't have any influence");
+ }
}
-
+
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiCamera* pCamera)
{
- if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
- ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
+ if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear)
+ ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear");
- // FIX: there are many 3ds files with invalid FOVs. No reason to
- // reject them at all ... a warning is appropriate.
- if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
- ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV);
+ // FIX: there are many 3ds files with invalid FOVs. No reason to
+ // reject them at all ... a warning is appropriate.
+ if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI)
+ ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV);
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh)
{
- // validate the material index of the mesh
- if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials)
- {
- ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)",
- pMesh->mMaterialIndex,mScene->mNumMaterials-1);
- }
-
- Validate(&pMesh->mName);
-
- for (unsigned int i = 0; i < pMesh->mNumFaces; ++i)
- {
- aiFace& face = pMesh->mFaces[i];
-
- if (pMesh->mPrimitiveTypes)
- {
- switch (face.mNumIndices)
- {
- case 0:
- ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i);
- case 1:
- if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
- {
- ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes "
- "does not report the POINT flag",i);
- }
- break;
- case 2:
- if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE))
- {
- ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes "
- "does not report the LINE flag",i);
- }
- break;
- case 3:
- if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE))
- {
- ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes "
- "does not report the TRIANGLE flag",i);
- }
- break;
- default:
- if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON))
- {
- this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes "
- "does not report the POLYGON flag",i);
- }
- break;
- };
- }
-
- if (!face.mIndices)
- ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
- }
-
- // positions must always be there ...
- if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
- ReportError("The mesh contains no vertices");
- }
-
- if (pMesh->mNumVertices > AI_MAX_VERTICES) {
- ReportError("Mesh has too many vertices: %u, but the limit is %u",pMesh->mNumVertices,AI_MAX_VERTICES);
- }
- if (pMesh->mNumFaces > AI_MAX_FACES) {
- ReportError("Mesh has too many faces: %u, but the limit is %u",pMesh->mNumFaces,AI_MAX_FACES);
- }
-
- // if tangents are there there must also be bitangent vectors ...
- if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL)) {
- ReportError("If there are tangents, bitangent vectors must be present as well");
- }
-
- // faces, too
- if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
- ReportError("Mesh contains no faces");
- }
-
- // now check whether the face indexing layout is correct:
- // unique vertices, pseudo-indexed.
- std::vector<bool> abRefList;
- abRefList.resize(pMesh->mNumVertices,false);
- for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
- {
- aiFace& face = pMesh->mFaces[i];
- if (face.mNumIndices > AI_MAX_FACE_INDICES) {
- ReportError("Face %u has too many faces: %u, but the limit is %u",i,face.mNumIndices,AI_MAX_FACE_INDICES);
- }
-
- for (unsigned int a = 0; a < face.mNumIndices;++a)
- {
- if (face.mIndices[a] >= pMesh->mNumVertices) {
- ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
- }
- // the MSB flag is temporarily used by the extra verbose
- // mode to tell us that the JoinVerticesProcess might have
- // been executed already.
- if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && abRefList[face.mIndices[a]])
- {
- ReportError("aiMesh::mVertices[%i] is referenced twice - second "
- "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
- }
- abRefList[face.mIndices[a]] = true;
- }
- }
-
- // check whether there are vertices that aren't referenced by a face
- bool b = false;
- for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
- if (!abRefList[i])b = true;
- }
- abRefList.clear();
- if (b)ReportWarning("There are unreferenced vertices");
-
- // texture channel 2 may not be set if channel 1 is zero ...
- {
- unsigned int i = 0;
- for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
- {
- if (!pMesh->HasTextureCoords(i))break;
- }
- for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
- if (pMesh->HasTextureCoords(i))
- {
- ReportError("Texture coordinate channel %i exists "
- "although the previous channel was NULL.",i);
- }
- }
- // the same for the vertex colors
- {
- unsigned int i = 0;
- for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
- {
- if (!pMesh->HasVertexColors(i))break;
- }
- for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
- if (pMesh->HasVertexColors(i))
- {
- ReportError("Vertex color channel %i is exists "
- "although the previous channel was NULL.",i);
- }
- }
-
-
- // now validate all bones
- if (pMesh->mNumBones)
- {
- if (!pMesh->mBones)
- {
- ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
- pMesh->mNumBones);
- }
- boost::scoped_array<float> afSum(NULL);
- if (pMesh->mNumVertices)
- {
- afSum.reset(new float[pMesh->mNumVertices]);
- for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
- afSum[i] = 0.0f;
- }
-
- // check whether there are duplicate bone names
- for (unsigned int i = 0; i < pMesh->mNumBones;++i)
- {
- const aiBone* bone = pMesh->mBones[i];
- if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) {
- ReportError("Bone %u has too many weights: %u, but the limit is %u",i,bone->mNumWeights,AI_MAX_BONE_WEIGHTS);
- }
-
- if (!pMesh->mBones[i])
- {
- ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
- i,pMesh->mNumBones);
- }
- Validate(pMesh,pMesh->mBones[i],afSum.get());
-
- for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
- {
- if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName)
- {
- ReportError("aiMesh::mBones[%i] has the same name as "
- "aiMesh::mBones[%i]",i,a);
- }
- }
- }
- // check whether all bone weights for a vertex sum to 1.0 ...
- for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
- {
- if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) {
- ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
- }
- }
- }
- else if (pMesh->mBones)
- {
- ReportError("aiMesh::mBones is non-null although there are no bones");
- }
+ // validate the material index of the mesh
+ if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials)
+ {
+ ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)",
+ pMesh->mMaterialIndex,mScene->mNumMaterials-1);
+ }
+
+ Validate(&pMesh->mName);
+
+ for (unsigned int i = 0; i < pMesh->mNumFaces; ++i)
+ {
+ aiFace& face = pMesh->mFaces[i];
+
+ if (pMesh->mPrimitiveTypes)
+ {
+ switch (face.mNumIndices)
+ {
+ case 0:
+ ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i);
+ case 1:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
+ {
+ ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes "
+ "does not report the POINT flag",i);
+ }
+ break;
+ case 2:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE))
+ {
+ ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes "
+ "does not report the LINE flag",i);
+ }
+ break;
+ case 3:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE))
+ {
+ ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes "
+ "does not report the TRIANGLE flag",i);
+ }
+ break;
+ default:
+ if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON))
+ {
+ this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes "
+ "does not report the POLYGON flag",i);
+ }
+ break;
+ };
+ }
+
+ if (!face.mIndices)
+ ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
+ }
+
+ // positions must always be there ...
+ if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) {
+ ReportError("The mesh contains no vertices");
+ }
+
+ if (pMesh->mNumVertices > AI_MAX_VERTICES) {
+ ReportError("Mesh has too many vertices: %u, but the limit is %u",pMesh->mNumVertices,AI_MAX_VERTICES);
+ }
+ if (pMesh->mNumFaces > AI_MAX_FACES) {
+ ReportError("Mesh has too many faces: %u, but the limit is %u",pMesh->mNumFaces,AI_MAX_FACES);
+ }
+
+ // if tangents are there there must also be bitangent vectors ...
+ if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL)) {
+ ReportError("If there are tangents, bitangent vectors must be present as well");
+ }
+
+ // faces, too
+ if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) {
+ ReportError("Mesh contains no faces");
+ }
+
+ // now check whether the face indexing layout is correct:
+ // unique vertices, pseudo-indexed.
+ std::vector<bool> abRefList;
+ abRefList.resize(pMesh->mNumVertices,false);
+ for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
+ {
+ aiFace& face = pMesh->mFaces[i];
+ if (face.mNumIndices > AI_MAX_FACE_INDICES) {
+ ReportError("Face %u has too many faces: %u, but the limit is %u",i,face.mNumIndices,AI_MAX_FACE_INDICES);
+ }
+
+ for (unsigned int a = 0; a < face.mNumIndices;++a)
+ {
+ if (face.mIndices[a] >= pMesh->mNumVertices) {
+ ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
+ }
+ // the MSB flag is temporarily used by the extra verbose
+ // mode to tell us that the JoinVerticesProcess might have
+ // been executed already.
+ if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && abRefList[face.mIndices[a]])
+ {
+ ReportError("aiMesh::mVertices[%i] is referenced twice - second "
+ "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
+ }
+ abRefList[face.mIndices[a]] = true;
+ }
+ }
+
+ // check whether there are vertices that aren't referenced by a face
+ bool b = false;
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
+ if (!abRefList[i])b = true;
+ }
+ abRefList.clear();
+ if (b)ReportWarning("There are unreferenced vertices");
+
+ // texture channel 2 may not be set if channel 1 is zero ...
+ {
+ unsigned int i = 0;
+ for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ {
+ if (!pMesh->HasTextureCoords(i))break;
+ }
+ for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+ if (pMesh->HasTextureCoords(i))
+ {
+ ReportError("Texture coordinate channel %i exists "
+ "although the previous channel was NULL.",i);
+ }
+ }
+ // the same for the vertex colors
+ {
+ unsigned int i = 0;
+ for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
+ {
+ if (!pMesh->HasVertexColors(i))break;
+ }
+ for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
+ if (pMesh->HasVertexColors(i))
+ {
+ ReportError("Vertex color channel %i is exists "
+ "although the previous channel was NULL.",i);
+ }
+ }
+
+
+ // now validate all bones
+ if (pMesh->mNumBones)
+ {
+ if (!pMesh->mBones)
+ {
+ ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
+ pMesh->mNumBones);
+ }
+ std::unique_ptr<float[]> afSum(nullptr);
+ if (pMesh->mNumVertices)
+ {
+ afSum.reset(new float[pMesh->mNumVertices]);
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
+ afSum[i] = 0.0f;
+ }
+
+ // check whether there are duplicate bone names
+ for (unsigned int i = 0; i < pMesh->mNumBones;++i)
+ {
+ const aiBone* bone = pMesh->mBones[i];
+ if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) {
+ ReportError("Bone %u has too many weights: %u, but the limit is %u",i,bone->mNumWeights,AI_MAX_BONE_WEIGHTS);
+ }
+
+ if (!pMesh->mBones[i])
+ {
+ ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
+ i,pMesh->mNumBones);
+ }
+ Validate(pMesh,pMesh->mBones[i],afSum.get());
+
+ for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
+ {
+ if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName)
+ {
+ ReportError("aiMesh::mBones[%i] has the same name as "
+ "aiMesh::mBones[%i]",i,a);
+ }
+ }
+ }
+ // check whether all bone weights for a vertex sum to 1.0 ...
+ for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
+ {
+ if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) {
+ ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
+ }
+ }
+ }
+ else if (pMesh->mBones)
+ {
+ ReportError("aiMesh::mBones is non-null although there are no bones");
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMesh* pMesh,
- const aiBone* pBone,float* afSum)
+ const aiBone* pBone,float* afSum)
{
- this->Validate(&pBone->mName);
-
- if (!pBone->mNumWeights) {
- ReportError("aiBone::mNumWeights is zero");
- }
-
- // check whether all vertices affected by this bone are valid
- for (unsigned int i = 0; i < pBone->mNumWeights;++i)
- {
- if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) {
- ReportError("aiBone::mWeights[%i].mVertexId is out of range",i);
- }
- else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) {
- ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i);
- }
- afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
- }
+ this->Validate(&pBone->mName);
+
+ if (!pBone->mNumWeights) {
+ ReportError("aiBone::mNumWeights is zero");
+ }
+
+ // check whether all vertices affected by this bone are valid
+ for (unsigned int i = 0; i < pBone->mNumWeights;++i)
+ {
+ if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) {
+ ReportError("aiBone::mWeights[%i].mVertexId is out of range",i);
+ }
+ else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) {
+ ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i);
+ }
+ afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
{
- Validate(&pAnimation->mName);
-
- // validate all materials
- if (pAnimation->mNumChannels)
- {
- if (!pAnimation->mChannels) {
- ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
- pAnimation->mNumChannels);
- }
- for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
- {
- if (!pAnimation->mChannels[i])
- {
- ReportError("aiAnimation::mChannels[%i] is NULL (aiAnimation::mNumChannels is %i)",
- i, pAnimation->mNumChannels);
- }
- Validate(pAnimation, pAnimation->mChannels[i]);
- }
- }
- else ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
-
- // Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
- // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
+ Validate(&pAnimation->mName);
+
+ // validate all materials
+ if (pAnimation->mNumChannels)
+ {
+ if (!pAnimation->mChannels) {
+ ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
+ pAnimation->mNumChannels);
+ }
+ for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
+ {
+ if (!pAnimation->mChannels[i])
+ {
+ ReportError("aiAnimation::mChannels[%i] is NULL (aiAnimation::mNumChannels is %i)",
+ i, pAnimation->mNumChannels);
+ }
+ Validate(pAnimation, pAnimation->mChannels[i]);
+ }
+ }
+ else ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
+
+ // Animation duration is allowed to be zero in cases where the anim contains only a single key frame.
+ // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero");
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
- aiTextureType type)
+ aiTextureType type)
{
- const char* szType = TextureTypeToString(type);
-
- // ****************************************************************************
- // Search all keys of the material ...
- // textures must be specified with ascending indices
- // (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...)
- // ****************************************************************************
-
- int iNumIndices = 0;
- int iIndex = -1;
- for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
- {
- aiMaterialProperty* prop = pMaterial->mProperties[i];
- if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type) {
- iIndex = std::max(iIndex, (int) prop->mIndex);
- ++iNumIndices;
-
- if (aiPTI_String != prop->mType)
- ReportError("Material property %s is expected to be a string",prop->mKey.data);
- }
- }
- if (iIndex +1 != iNumIndices) {
- ReportError("%s #%i is set, but there are only %i %s textures",
- szType,iIndex,iNumIndices,szType);
- }
- if (!iNumIndices)return;
- std::vector<aiTextureMapping> mappings(iNumIndices);
-
- // Now check whether all UV indices are valid ...
- bool bNoSpecified = true;
- for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
- {
- aiMaterialProperty* prop = pMaterial->mProperties[i];
- if (prop->mSemantic != type)continue;
-
- if ((int)prop->mIndex >= iNumIndices)
- {
- ReportError("Found texture property with index %i, although there "
- "are only %i textures of type %s",
- prop->mIndex, iNumIndices, szType);
- }
-
- if (!::strcmp(prop->mKey.data,"$tex.mapping")) {
- if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping))
- {
- ReportError("Material property %s%i is expected to be an integer (size is %i)",
- prop->mKey.data,prop->mIndex,prop->mDataLength);
- }
- mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
- }
- else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) {
- if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform))
- {
- ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
- prop->mKey.data,prop->mIndex, prop->mDataLength);
- }
- mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
- }
- else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
- if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
- {
- ReportError("Material property %s%i is expected to be an integer (size is %i)",
- prop->mKey.data,prop->mIndex,prop->mDataLength);
- }
- bNoSpecified = false;
-
- // Ignore UV indices for texture channels that are not there ...
-
- // Get the value
- iIndex = *((unsigned int*)prop->mData);
-
- // Check whether there is a mesh using this material
- // which has not enough UV channels ...
- for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
- {
- aiMesh* mesh = this->mScene->mMeshes[a];
- if(mesh->mMaterialIndex == (unsigned int)i)
- {
- int iChannels = 0;
- while (mesh->HasTextureCoords(iChannels))++iChannels;
- if (iIndex >= iChannels)
- {
- ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
- iIndex,prop->mKey.data,a,iChannels);
- }
- }
- }
- }
- }
- if (bNoSpecified)
- {
- // Assume that all textures are using the first UV channel
- for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
- {
- aiMesh* mesh = mScene->mMeshes[a];
- if(mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV)
- {
- if (!mesh->mTextureCoords[0])
- {
- // This is a special case ... it could be that the
- // original mesh format intended the use of a special
- // mapping here.
- ReportWarning("UV-mapped texture, but there are no UV coords");
- }
- }
- }
- }
+ const char* szType = TextureTypeToString(type);
+
+ // ****************************************************************************
+ // Search all keys of the material ...
+ // textures must be specified with ascending indices
+ // (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...)
+ // ****************************************************************************
+
+ int iNumIndices = 0;
+ int iIndex = -1;
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
+ {
+ aiMaterialProperty* prop = pMaterial->mProperties[i];
+ if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type) {
+ iIndex = std::max(iIndex, (int) prop->mIndex);
+ ++iNumIndices;
+
+ if (aiPTI_String != prop->mType)
+ ReportError("Material property %s is expected to be a string",prop->mKey.data);
+ }
+ }
+ if (iIndex +1 != iNumIndices) {
+ ReportError("%s #%i is set, but there are only %i %s textures",
+ szType,iIndex,iNumIndices,szType);
+ }
+ if (!iNumIndices)return;
+ std::vector<aiTextureMapping> mappings(iNumIndices);
+
+ // Now check whether all UV indices are valid ...
+ bool bNoSpecified = true;
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
+ {
+ aiMaterialProperty* prop = pMaterial->mProperties[i];
+ if (prop->mSemantic != type)continue;
+
+ if ((int)prop->mIndex >= iNumIndices)
+ {
+ ReportError("Found texture property with index %i, although there "
+ "are only %i textures of type %s",
+ prop->mIndex, iNumIndices, szType);
+ }
+
+ if (!::strcmp(prop->mKey.data,"$tex.mapping")) {
+ if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping))
+ {
+ ReportError("Material property %s%i is expected to be an integer (size is %i)",
+ prop->mKey.data,prop->mIndex,prop->mDataLength);
+ }
+ mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
+ }
+ else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) {
+ if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform))
+ {
+ ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
+ prop->mKey.data,prop->mIndex, prop->mDataLength);
+ }
+ mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
+ }
+ else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
+ if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
+ {
+ ReportError("Material property %s%i is expected to be an integer (size is %i)",
+ prop->mKey.data,prop->mIndex,prop->mDataLength);
+ }
+ bNoSpecified = false;
+
+ // Ignore UV indices for texture channels that are not there ...
+
+ // Get the value
+ iIndex = *((unsigned int*)prop->mData);
+
+ // Check whether there is a mesh using this material
+ // which has not enough UV channels ...
+ for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
+ {
+ aiMesh* mesh = this->mScene->mMeshes[a];
+ if(mesh->mMaterialIndex == (unsigned int)i)
+ {
+ int iChannels = 0;
+ while (mesh->HasTextureCoords(iChannels))++iChannels;
+ if (iIndex >= iChannels)
+ {
+ ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
+ iIndex,prop->mKey.data,a,iChannels);
+ }
+ }
+ }
+ }
+ }
+ if (bNoSpecified)
+ {
+ // Assume that all textures are using the first UV channel
+ for (unsigned int a = 0; a < mScene->mNumMeshes;++a)
+ {
+ aiMesh* mesh = mScene->mMeshes[a];
+ if(mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV)
+ {
+ if (!mesh->mTextureCoords[0])
+ {
+ // This is a special case ... it could be that the
+ // original mesh format intended the use of a special
+ // mapping here.
+ ReportWarning("UV-mapped texture, but there are no UV coords");
+ }
+ }
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
{
- // check whether there are material keys that are obviously not legal
- for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
- {
- const aiMaterialProperty* prop = pMaterial->mProperties[i];
- if (!prop) {
- ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
- i,pMaterial->mNumProperties);
- }
- if (!prop->mDataLength || !prop->mData) {
- ReportError("aiMaterial::mProperties[%i].mDataLength or "
- "aiMaterial::mProperties[%i].mData is 0",i,i);
- }
- // check all predefined types
- if (aiPTI_String == prop->mType) {
- // FIX: strings are now stored in a less expensive way, but we can't use the
- // validation routine for 'normal' aiStrings
- uint32_t len;
- if (prop->mDataLength < 5 || prop->mDataLength < 4 + (len=*reinterpret_cast<uint32_t*>(prop->mData)) + 1) {
- ReportError("aiMaterial::mProperties[%i].mDataLength is "
- "too small to contain a string (%i, needed: %i)",
- i,prop->mDataLength,sizeof(aiString));
- }
- if(prop->mData[prop->mDataLength-1]) {
- ReportError("Missing null-terminator in string material property");
- }
- // Validate((const aiString*)prop->mData);
- }
- else if (aiPTI_Float == prop->mType) {
- if (prop->mDataLength < sizeof(float)) {
- ReportError("aiMaterial::mProperties[%i].mDataLength is "
- "too small to contain a float (%i, needed: %i)",
- i,prop->mDataLength,sizeof(float));
- }
- }
- else if (aiPTI_Integer == prop->mType) {
- if (prop->mDataLength < sizeof(int)) {
- ReportError("aiMaterial::mProperties[%i].mDataLength is "
- "too small to contain an integer (%i, needed: %i)",
- i,prop->mDataLength,sizeof(int));
- }
- }
- // TODO: check whether there is a key with an unknown name ...
- }
-
- // make some more specific tests
- float fTemp;
- int iShading;
- if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) {
- switch ((aiShadingMode)iShading)
- {
- case aiShadingMode_Blinn:
- case aiShadingMode_CookTorrance:
- case aiShadingMode_Phong:
-
- if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) {
- ReportWarning("A specular shading model is specified but there is no "
- "AI_MATKEY_SHININESS key");
- }
- if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) {
- ReportWarning("A specular shading model is specified but the value of the "
- "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
- }
- break;
- default: ;
- };
- }
-
- if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01f)) {
- ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
- }
-
- // Check whether there are invalid texture keys
- // TODO: that's a relict of the past, where texture type and index were baked
- // into the material string ... we could do that in one single pass.
- SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
- SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
- SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
- SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE);
- SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY);
- SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
- SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
- SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
- SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
- SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
- SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
+ // check whether there are material keys that are obviously not legal
+ for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
+ {
+ const aiMaterialProperty* prop = pMaterial->mProperties[i];
+ if (!prop) {
+ ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
+ i,pMaterial->mNumProperties);
+ }
+ if (!prop->mDataLength || !prop->mData) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength or "
+ "aiMaterial::mProperties[%i].mData is 0",i,i);
+ }
+ // check all predefined types
+ if (aiPTI_String == prop->mType) {
+ // FIX: strings are now stored in a less expensive way, but we can't use the
+ // validation routine for 'normal' aiStrings
+ if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast<uint32_t*>(prop->mData)) + 1) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain a string (%i, needed: %i)",
+ i,prop->mDataLength,sizeof(aiString));
+ }
+ if(prop->mData[prop->mDataLength-1]) {
+ ReportError("Missing null-terminator in string material property");
+ }
+ // Validate((const aiString*)prop->mData);
+ }
+ else if (aiPTI_Float == prop->mType) {
+ if (prop->mDataLength < sizeof(float)) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain a float (%i, needed: %i)",
+ i,prop->mDataLength,sizeof(float));
+ }
+ }
+ else if (aiPTI_Integer == prop->mType) {
+ if (prop->mDataLength < sizeof(int)) {
+ ReportError("aiMaterial::mProperties[%i].mDataLength is "
+ "too small to contain an integer (%i, needed: %i)",
+ i,prop->mDataLength,sizeof(int));
+ }
+ }
+ // TODO: check whether there is a key with an unknown name ...
+ }
+
+ // make some more specific tests
+ float fTemp;
+ int iShading;
+ if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) {
+ switch ((aiShadingMode)iShading)
+ {
+ case aiShadingMode_Blinn:
+ case aiShadingMode_CookTorrance:
+ case aiShadingMode_Phong:
+
+ if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) {
+ ReportWarning("A specular shading model is specified but there is no "
+ "AI_MATKEY_SHININESS key");
+ }
+ if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) {
+ ReportWarning("A specular shading model is specified but the value of the "
+ "AI_MATKEY_SHININESS_STRENGTH key is 0.0");
+ }
+ break;
+ default: ;
+ };
+ }
+
+ if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01f)) {
+ ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
+ }
+
+ // Check whether there are invalid texture keys
+ // TODO: that's a relict of the past, where texture type and index were baked
+ // into the material string ... we could do that in one single pass.
+ SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
+ SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
+ SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE);
+ SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY);
+ SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
+ SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
+ SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
+ SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
+ SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiTexture* pTexture)
{
- // the data section may NEVER be NULL
- if (!pTexture->pcData) {
- ReportError("aiTexture::pcData is NULL");
- }
- if (pTexture->mHeight)
- {
- if (!pTexture->mWidth)ReportError("aiTexture::mWidth is zero "
- "(aiTexture::mHeight is %i, uncompressed texture)",pTexture->mHeight);
- }
- else
- {
- if (!pTexture->mWidth) {
- ReportError("aiTexture::mWidth is zero (compressed texture)");
- }
- if ('\0' != pTexture->achFormatHint[3]) {
- ReportWarning("aiTexture::achFormatHint must be zero-terminated");
- }
- else if ('.' == pTexture->achFormatHint[0]) {
- ReportWarning("aiTexture::achFormatHint should contain a file extension "
- "without a leading dot (format hint: %s).",pTexture->achFormatHint);
- }
- }
-
- const char* sz = pTexture->achFormatHint;
- if ((sz[0] >= 'A' && sz[0] <= 'Z') ||
- (sz[1] >= 'A' && sz[1] <= 'Z') ||
- (sz[2] >= 'A' && sz[2] <= 'Z') ||
- (sz[3] >= 'A' && sz[3] <= 'Z')) {
- ReportError("aiTexture::achFormatHint contains non-lowercase letters");
- }
+ // the data section may NEVER be NULL
+ if (!pTexture->pcData) {
+ ReportError("aiTexture::pcData is NULL");
+ }
+ if (pTexture->mHeight)
+ {
+ if (!pTexture->mWidth)ReportError("aiTexture::mWidth is zero "
+ "(aiTexture::mHeight is %i, uncompressed texture)",pTexture->mHeight);
+ }
+ else
+ {
+ if (!pTexture->mWidth) {
+ ReportError("aiTexture::mWidth is zero (compressed texture)");
+ }
+ if ('\0' != pTexture->achFormatHint[3]) {
+ ReportWarning("aiTexture::achFormatHint must be zero-terminated");
+ }
+ else if ('.' == pTexture->achFormatHint[0]) {
+ ReportWarning("aiTexture::achFormatHint should contain a file extension "
+ "without a leading dot (format hint: %s).",pTexture->achFormatHint);
+ }
+ }
+
+ const char* sz = pTexture->achFormatHint;
+ if ((sz[0] >= 'A' && sz[0] <= 'Z') ||
+ (sz[1] >= 'A' && sz[1] <= 'Z') ||
+ (sz[2] >= 'A' && sz[2] <= 'Z') ||
+ (sz[3] >= 'A' && sz[3] <= 'Z')) {
+ ReportError("aiTexture::achFormatHint contains non-lowercase letters");
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
- const aiNodeAnim* pNodeAnim)
+ const aiNodeAnim* pNodeAnim)
{
- Validate(&pNodeAnim->mNodeName);
-
- if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys)
- ReportError("Empty node animation channel");
-
- // otherwise check whether one of the keys exceeds the total duration of the animation
- if (pNodeAnim->mNumPositionKeys)
- {
- if (!pNodeAnim->mPositionKeys)
- {
- this->ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)",
- pNodeAnim->mNumPositionKeys);
- }
- double dLast = -10e10;
- for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i)
- {
- // ScenePreprocessor will compute the duration if still the default value
- // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
- // seems to be due the compilers register usage/width.
- if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration+0.001)
- {
- ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger "
- "than aiAnimation::mDuration (which is %.5f)",i,
- (float)pNodeAnim->mPositionKeys[i].mTime,
- (float)pAnimation->mDuration);
- }
- if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast)
- {
- ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
- "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i,
- (float)pNodeAnim->mPositionKeys[i].mTime,
- i-1, (float)dLast);
- }
- dLast = pNodeAnim->mPositionKeys[i].mTime;
- }
- }
- // rotation keys
- if (pNodeAnim->mNumRotationKeys)
- {
- if (!pNodeAnim->mRotationKeys)
- {
- this->ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)",
- pNodeAnim->mNumRotationKeys);
- }
- double dLast = -10e10;
- for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i)
- {
- if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration+0.001)
- {
- ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger "
- "than aiAnimation::mDuration (which is %.5f)",i,
- (float)pNodeAnim->mRotationKeys[i].mTime,
- (float)pAnimation->mDuration);
- }
- if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast)
- {
- ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
- "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i,
- (float)pNodeAnim->mRotationKeys[i].mTime,
- i-1, (float)dLast);
- }
- dLast = pNodeAnim->mRotationKeys[i].mTime;
- }
- }
- // scaling keys
- if (pNodeAnim->mNumScalingKeys)
- {
- if (!pNodeAnim->mScalingKeys) {
- ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)",
- pNodeAnim->mNumScalingKeys);
- }
- double dLast = -10e10;
- for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i)
- {
- if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration+0.001)
- {
- ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger "
- "than aiAnimation::mDuration (which is %.5f)",i,
- (float)pNodeAnim->mScalingKeys[i].mTime,
- (float)pAnimation->mDuration);
- }
- if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast)
- {
- ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
- "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,
- (float)pNodeAnim->mScalingKeys[i].mTime,
- i-1, (float)dLast);
- }
- dLast = pNodeAnim->mScalingKeys[i].mTime;
- }
- }
-
- if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys &&
- !pNodeAnim->mNumPositionKeys)
- {
- ReportError("A node animation channel must have at least one subtrack");
- }
+ Validate(&pNodeAnim->mNodeName);
+
+ if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys)
+ ReportError("Empty node animation channel");
+
+ // otherwise check whether one of the keys exceeds the total duration of the animation
+ if (pNodeAnim->mNumPositionKeys)
+ {
+ if (!pNodeAnim->mPositionKeys)
+ {
+ this->ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)",
+ pNodeAnim->mNumPositionKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i)
+ {
+ // ScenePreprocessor will compute the duration if still the default value
+ // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
+ // seems to be due the compilers register usage/width.
+ if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mPositionKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mPositionKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mPositionKeys[i].mTime;
+ }
+ }
+ // rotation keys
+ if (pNodeAnim->mNumRotationKeys)
+ {
+ if (!pNodeAnim->mRotationKeys)
+ {
+ this->ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)",
+ pNodeAnim->mNumRotationKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i)
+ {
+ if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mRotationKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mRotationKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mRotationKeys[i].mTime;
+ }
+ }
+ // scaling keys
+ if (pNodeAnim->mNumScalingKeys)
+ {
+ if (!pNodeAnim->mScalingKeys) {
+ ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)",
+ pNodeAnim->mNumScalingKeys);
+ }
+ double dLast = -10e10;
+ for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i)
+ {
+ if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration+0.001)
+ {
+ ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger "
+ "than aiAnimation::mDuration (which is %.5f)",i,
+ (float)pNodeAnim->mScalingKeys[i].mTime,
+ (float)pAnimation->mDuration);
+ }
+ if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast)
+ {
+ ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller "
+ "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,
+ (float)pNodeAnim->mScalingKeys[i].mTime,
+ i-1, (float)dLast);
+ }
+ dLast = pNodeAnim->mScalingKeys[i].mTime;
+ }
+ }
+
+ if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys &&
+ !pNodeAnim->mNumPositionKeys)
+ {
+ ReportError("A node animation channel must have at least one subtrack");
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiNode* pNode)
{
- if (!pNode)ReportError("A node of the scenegraph is NULL");
- if (pNode != mScene->mRootNode && !pNode->mParent)
- this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
-
- this->Validate(&pNode->mName);
-
- // validate all meshes
- if (pNode->mNumMeshes)
- {
- if (!pNode->mMeshes)
- {
- ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
- pNode->mNumMeshes);
- }
- std::vector<bool> abHadMesh;
- abHadMesh.resize(mScene->mNumMeshes,false);
- for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
- {
- if (pNode->mMeshes[i] >= mScene->mNumMeshes)
- {
- ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
- pNode->mMeshes[i],mScene->mNumMeshes-1);
- }
- if (abHadMesh[pNode->mMeshes[i]])
- {
- ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)",
- i,pNode->mMeshes[i]);
- }
- abHadMesh[pNode->mMeshes[i]] = true;
- }
- }
- if (pNode->mNumChildren)
- {
- if (!pNode->mChildren) {
- ReportError("aiNode::mChildren is NULL (aiNode::mNumChildren is %i)",
- pNode->mNumChildren);
- }
- for (unsigned int i = 0; i < pNode->mNumChildren;++i) {
- Validate(pNode->mChildren[i]);
- }
- }
+ if (!pNode)ReportError("A node of the scenegraph is NULL");
+ if (pNode != mScene->mRootNode && !pNode->mParent)
+ this->ReportError("A node has no valid parent (aiNode::mParent is NULL)");
+
+ this->Validate(&pNode->mName);
+
+ // validate all meshes
+ if (pNode->mNumMeshes)
+ {
+ if (!pNode->mMeshes)
+ {
+ ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)",
+ pNode->mNumMeshes);
+ }
+ std::vector<bool> abHadMesh;
+ abHadMesh.resize(mScene->mNumMeshes,false);
+ for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
+ {
+ if (pNode->mMeshes[i] >= mScene->mNumMeshes)
+ {
+ ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)",
+ pNode->mMeshes[i],mScene->mNumMeshes-1);
+ }
+ if (abHadMesh[pNode->mMeshes[i]])
+ {
+ ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)",
+ i,pNode->mMeshes[i]);
+ }
+ abHadMesh[pNode->mMeshes[i]] = true;
+ }
+ }
+ if (pNode->mNumChildren)
+ {
+ if (!pNode->mChildren) {
+ ReportError("aiNode::mChildren is NULL (aiNode::mNumChildren is %i)",
+ pNode->mNumChildren);
+ }
+ for (unsigned int i = 0; i < pNode->mNumChildren;++i) {
+ Validate(pNode->mChildren[i]);
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void ValidateDSProcess::Validate( const aiString* pString)
{
- if (pString->length > MAXLEN)
- {
- this->ReportError("aiString::length is too large (%i, maximum is %i)",
- pString->length,MAXLEN);
- }
- const char* sz = pString->data;
- while (true)
- {
- if ('\0' == *sz)
- {
- if (pString->length != (unsigned int)(sz-pString->data))
- ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
- break;
- }
- else if (sz >= &pString->data[MAXLEN])
- ReportError("aiString::data is invalid. There is no terminal character");
- ++sz;
- }
+ if (pString->length > MAXLEN)
+ {
+ this->ReportError("aiString::length is too large (%i, maximum is %i)",
+ pString->length,MAXLEN);
+ }
+ const char* sz = pString->data;
+ while (true)
+ {
+ if ('\0' == *sz)
+ {
+ if (pString->length != (unsigned int)(sz-pString->data))
+ ReportError("aiString::data is invalid: the terminal zero is at a wrong offset");
+ break;
+ }
+ else if (sz >= &pString->data[MAXLEN])
+ ReportError("aiString::data is invalid. There is no terminal character");
+ ++sz;
+ }
}
diff --git a/src/3rdparty/assimp/code/ValidateDataStructure.h b/src/3rdparty/assimp/code/ValidateDataStructure.h
index 2b7fa3721..87f158b37 100644
--- a/src/3rdparty/assimp/code/ValidateDataStructure.h
+++ b/src/3rdparty/assimp/code/ValidateDataStructure.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,7 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_VALIDATEPROCESS_H_INC
#define AI_VALIDATEPROCESS_H_INC
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
+#include <assimp/material.h>
#include "BaseProcess.h"
struct aiBone;
@@ -55,8 +56,10 @@ struct aiTexture;
struct aiMaterial;
struct aiNode;
struct aiString;
+struct aiCamera;
+struct aiLight;
-namespace Assimp {
+namespace Assimp {
// --------------------------------------------------------------------------------------
/** Validates the whole ASSIMP scene data structure for correctness.
@@ -66,113 +69,113 @@ class ValidateDSProcess : public BaseProcess
{
public:
- ValidateDSProcess();
- ~ValidateDSProcess();
+ ValidateDSProcess();
+ ~ValidateDSProcess();
public:
- // -------------------------------------------------------------------
- bool IsActive( unsigned int pFlags) const;
+ // -------------------------------------------------------------------
+ bool IsActive( unsigned int pFlags) const;
- // -------------------------------------------------------------------
- void Execute( aiScene* pScene);
+ // -------------------------------------------------------------------
+ void Execute( aiScene* pScene);
protected:
- // -------------------------------------------------------------------
- /** Report a validation error. This will throw an exception,
- * control won't return.
- * @param msg Format string for sprintf().*/
- AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX;
-
-
- // -------------------------------------------------------------------
- /** Report a validation warning. This won't throw an exception,
- * control will return to the callera.
- * @param msg Format string for sprintf().*/
- void ReportWarning(const char* msg,...);
-
-
- // -------------------------------------------------------------------
- /** Validates a mesh
- * @param pMesh Input mesh*/
- void Validate( const aiMesh* pMesh);
-
- // -------------------------------------------------------------------
- /** Validates a bone
- * @param pMesh Input mesh
- * @param pBone Input bone*/
- void Validate( const aiMesh* pMesh,const aiBone* pBone,float* afSum);
-
- // -------------------------------------------------------------------
- /** Validates an animation
- * @param pAnimation Input animation*/
- void Validate( const aiAnimation* pAnimation);
-
- // -------------------------------------------------------------------
- /** Validates a material
- * @param pMaterial Input material*/
- void Validate( const aiMaterial* pMaterial);
-
- // -------------------------------------------------------------------
- /** Search the material data structure for invalid or corrupt
- * texture keys.
- * @param pMaterial Input material
- * @param type Type of the texture*/
- void SearchForInvalidTextures(const aiMaterial* pMaterial,
- aiTextureType type);
-
- // -------------------------------------------------------------------
- /** Validates a texture
- * @param pTexture Input texture*/
- void Validate( const aiTexture* pTexture);
-
- // -------------------------------------------------------------------
- /** Validates a light source
- * @param pLight Input light
- */
- void Validate( const aiLight* pLight);
-
- // -------------------------------------------------------------------
- /** Validates a camera
- * @param pCamera Input camera*/
- void Validate( const aiCamera* pCamera);
-
- // -------------------------------------------------------------------
- /** Validates a bone animation channel
- * @param pAnimation Animation channel.
- * @param pBoneAnim Input bone animation */
- void Validate( const aiAnimation* pAnimation,
- const aiNodeAnim* pBoneAnim);
-
- // -------------------------------------------------------------------
- /** Validates a node and all of its subnodes
- * @param Node Input node*/
- void Validate( const aiNode* pNode);
-
- // -------------------------------------------------------------------
- /** Validates a string
- * @param pString Input string*/
- void Validate( const aiString* pString);
+ // -------------------------------------------------------------------
+ /** Report a validation error. This will throw an exception,
+ * control won't return.
+ * @param msg Format string for sprintf().*/
+ AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX;
+
+
+ // -------------------------------------------------------------------
+ /** Report a validation warning. This won't throw an exception,
+ * control will return to the callera.
+ * @param msg Format string for sprintf().*/
+ void ReportWarning(const char* msg,...);
+
+
+ // -------------------------------------------------------------------
+ /** Validates a mesh
+ * @param pMesh Input mesh*/
+ void Validate( const aiMesh* pMesh);
+
+ // -------------------------------------------------------------------
+ /** Validates a bone
+ * @param pMesh Input mesh
+ * @param pBone Input bone*/
+ void Validate( const aiMesh* pMesh,const aiBone* pBone,float* afSum);
+
+ // -------------------------------------------------------------------
+ /** Validates an animation
+ * @param pAnimation Input animation*/
+ void Validate( const aiAnimation* pAnimation);
+
+ // -------------------------------------------------------------------
+ /** Validates a material
+ * @param pMaterial Input material*/
+ void Validate( const aiMaterial* pMaterial);
+
+ // -------------------------------------------------------------------
+ /** Search the material data structure for invalid or corrupt
+ * texture keys.
+ * @param pMaterial Input material
+ * @param type Type of the texture*/
+ void SearchForInvalidTextures(const aiMaterial* pMaterial,
+ aiTextureType type);
+
+ // -------------------------------------------------------------------
+ /** Validates a texture
+ * @param pTexture Input texture*/
+ void Validate( const aiTexture* pTexture);
+
+ // -------------------------------------------------------------------
+ /** Validates a light source
+ * @param pLight Input light
+ */
+ void Validate( const aiLight* pLight);
+
+ // -------------------------------------------------------------------
+ /** Validates a camera
+ * @param pCamera Input camera*/
+ void Validate( const aiCamera* pCamera);
+
+ // -------------------------------------------------------------------
+ /** Validates a bone animation channel
+ * @param pAnimation Animation channel.
+ * @param pBoneAnim Input bone animation */
+ void Validate( const aiAnimation* pAnimation,
+ const aiNodeAnim* pBoneAnim);
+
+ // -------------------------------------------------------------------
+ /** Validates a node and all of its subnodes
+ * @param Node Input node*/
+ void Validate( const aiNode* pNode);
+
+ // -------------------------------------------------------------------
+ /** Validates a string
+ * @param pString Input string*/
+ void Validate( const aiString* pString);
private:
- // template to validate one of the aiScene::mXXX arrays
- template <typename T>
- inline void DoValidation(T** array, unsigned int size,
- const char* firstName, const char* secondName);
-
- // extended version: checks whethr T::mName occurs twice
- template <typename T>
- inline void DoValidationEx(T** array, unsigned int size,
- const char* firstName, const char* secondName);
-
- // extension to the first template which does also search
- // the nodegraph for an item with the same name
- template <typename T>
- inline void DoValidationWithNameCheck(T** array, unsigned int size,
- const char* firstName, const char* secondName);
-
- aiScene* mScene;
+ // template to validate one of the aiScene::mXXX arrays
+ template <typename T>
+ inline void DoValidation(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ // extended version: checks whethr T::mName occurs twice
+ template <typename T>
+ inline void DoValidationEx(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ // extension to the first template which does also search
+ // the nodegraph for an item with the same name
+ template <typename T>
+ inline void DoValidationWithNameCheck(T** array, unsigned int size,
+ const char* firstName, const char* secondName);
+
+ aiScene* mScene;
};
diff --git a/src/3rdparty/assimp/code/Version.cpp b/src/3rdparty/assimp/code/Version.cpp
new file mode 100644
index 000000000..42862baac
--- /dev/null
+++ b/src/3rdparty/assimp/code/Version.cpp
@@ -0,0 +1,169 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+// Actually just a dummy, used by the compiler to build the precompiled header.
+
+#include "./../include/assimp/version.h"
+#include "./../include/assimp/scene.h"
+#include "ScenePrivate.h"
+
+static const unsigned int MajorVersion = 3;
+static const unsigned int MinorVersion = 3;
+
+// --------------------------------------------------------------------------------
+// Legal information string - dont'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) 2008-2010, assimp team\n"
+"License under the terms and conditions of the 3-clause BSD license\n"
+"http://assimp.sourceforge.net\n"
+;
+
+// ------------------------------------------------------------------------------------------------
+// Get legal string
+ASSIMP_API const char* aiGetLegalString () {
+ return LEGAL_INFORMATION;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get Assimp minor version
+ASSIMP_API unsigned int aiGetVersionMinor () {
+ return MinorVersion;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get Assimp major version
+ASSIMP_API unsigned int aiGetVersionMajor () {
+ return MajorVersion;
+}
+
+// ------------------------------------------------------------------------------------------------
+// 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;
+}
+
+// include current build revision, which is even updated from time to time -- :-)
+#include "revision.h"
+
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API unsigned int aiGetVersionRevision ()
+{
+ return GitVersion;
+}
+
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API aiScene::aiScene()
+ : mFlags(0)
+ , mRootNode(NULL)
+ , mNumMeshes(0)
+ , mMeshes(NULL)
+ , mNumMaterials(0)
+ , mMaterials(NULL)
+ , mNumAnimations(0)
+ , mAnimations(NULL)
+ , mNumTextures(0)
+ , mTextures(NULL)
+ , mNumLights(0)
+ , mLights(NULL)
+ , mNumCameras(0)
+ , mCameras(NULL)
+ , mPrivate(new Assimp::ScenePrivateData())
+ {
+ }
+
+// ------------------------------------------------------------------------------------------------
+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;
+
+ delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
+}
+
diff --git a/src/3rdparty/assimp/code/Vertex.h b/src/3rdparty/assimp/code/Vertex.h
index cc92a571b..5e2cf6986 100644
--- a/src/3rdparty/assimp/code/Vertex.h
+++ b/src/3rdparty/assimp/code/Vertex.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Defines a helper class to represent an interleaved vertex
along with arithmetic operations to support vertex operations
such as subdivision, smoothing etc.
-
+
While the code is kept as general as possible, arithmetic operations
that are not currently well-defined (and would cause compile errors
due to missing operators in the math library), are commented.
@@ -48,270 +48,273 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_VERTEX_H_INC
#define AI_VERTEX_H_INC
+#include <assimp/vector3.h>
+#include <assimp/mesh.h>
+#include <assimp/ai_assert.h>
#include <functional>
-namespace Assimp {
-
- ///////////////////////////////////////////////////////////////////////////
- // std::plus-family operates on operands with identical types - we need to
- // support all the (vectype op float) combinations in vector maths.
- // Providing T(float) would open the way to endless implicit conversions.
- ///////////////////////////////////////////////////////////////////////////
- namespace Intern {
- template <typename T0, typename T1, typename TRES = T0> struct plus {
- TRES operator() (const T0& t0, const T1& t1) const {
- return t0+t1;
- }
- };
- template <typename T0, typename T1, typename TRES = T0> struct minus {
- TRES operator() (const T0& t0, const T1& t1) const {
- return t0-t1;
- }
- };
- template <typename T0, typename T1, typename TRES = T0> struct multiplies {
- TRES operator() (const T0& t0, const T1& t1) const {
- return t0*t1;
- }
- };
- template <typename T0, typename T1, typename TRES = T0> struct divides {
- TRES operator() (const T0& t0, const T1& t1) const {
- return t0/t1;
- }
- };
- }
+namespace Assimp {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // std::plus-family operates on operands with identical types - we need to
+ // support all the (vectype op float) combinations in vector maths.
+ // Providing T(float) would open the way to endless implicit conversions.
+ ///////////////////////////////////////////////////////////////////////////
+ namespace Intern {
+ template <typename T0, typename T1, typename TRES = T0> struct plus {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0+t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct minus {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0-t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct multiplies {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0*t1;
+ }
+ };
+ template <typename T0, typename T1, typename TRES = T0> struct divides {
+ TRES operator() (const T0& t0, const T1& t1) const {
+ return t0/t1;
+ }
+ };
+ }
// ------------------------------------------------------------------------------------------------
-/** Intermediate description a vertex with all possible components. Defines a full set of
+/** Intermediate description a vertex with all possible components. Defines a full set of
* operators, so you may use such a 'Vertex' in basic arithmetics. All operators are applied
* to *all* vertex components equally. This is useful for stuff like interpolation
* or subdivision, but won't work if special handling is required for some vertex components. */
// ------------------------------------------------------------------------------------------------
class Vertex
{
- friend Vertex operator + (const Vertex&,const Vertex&);
- friend Vertex operator - (const Vertex&,const Vertex&);
+ friend Vertex operator + (const Vertex&,const Vertex&);
+ friend Vertex operator - (const Vertex&,const Vertex&);
-// friend Vertex operator + (const Vertex&,float);
-// friend Vertex operator - (const Vertex&,float);
- friend Vertex operator * (const Vertex&,float);
- friend Vertex operator / (const Vertex&,float);
+// friend Vertex operator + (const Vertex&,float);
+// friend Vertex operator - (const Vertex&,float);
+ friend Vertex operator * (const Vertex&,float);
+ friend Vertex operator / (const Vertex&,float);
-// friend Vertex operator + (float, const Vertex&);
-// friend Vertex operator - (float, const Vertex&);
- friend Vertex operator * (float, const Vertex&);
-// friend Vertex operator / (float, const Vertex&);
+// friend Vertex operator + (float, const Vertex&);
+// friend Vertex operator - (float, const Vertex&);
+ friend Vertex operator * (float, const Vertex&);
+// friend Vertex operator / (float, const Vertex&);
public:
- Vertex() {}
+ Vertex() {}
- // ----------------------------------------------------------------------------
- /** Extract a particular vertex from a mesh and interleave all components */
- explicit Vertex(const aiMesh* msh, unsigned int idx) {
- ai_assert(idx < msh->mNumVertices);
- position = msh->mVertices[idx];
+ // ----------------------------------------------------------------------------
+ /** Extract a particular vertex from a mesh and interleave all components */
+ explicit Vertex(const aiMesh* msh, unsigned int idx) {
+ ai_assert(idx < msh->mNumVertices);
+ position = msh->mVertices[idx];
- if (msh->HasNormals()) {
- normal = msh->mNormals[idx];
- }
+ if (msh->HasNormals()) {
+ normal = msh->mNormals[idx];
+ }
- if (msh->HasTangentsAndBitangents()) {
- tangent = msh->mTangents[idx];
- bitangent = msh->mBitangents[idx];
- }
+ if (msh->HasTangentsAndBitangents()) {
+ tangent = msh->mTangents[idx];
+ bitangent = msh->mBitangents[idx];
+ }
- for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
- texcoords[i] = msh->mTextureCoords[i][idx];
- }
+ for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
+ texcoords[i] = msh->mTextureCoords[i][idx];
+ }
- for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
- colors[i] = msh->mColors[i][idx];
- }
- }
+ for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
+ colors[i] = msh->mColors[i][idx];
+ }
+ }
public:
- Vertex& operator += (const Vertex& v) {
- *this = *this+v;
- return *this;
- }
+ Vertex& operator += (const Vertex& v) {
+ *this = *this+v;
+ return *this;
+ }
- Vertex& operator -= (const Vertex& v) {
- *this = *this-v;
- return *this;
- }
+ Vertex& operator -= (const Vertex& v) {
+ *this = *this-v;
+ return *this;
+ }
/*
- Vertex& operator += (float v) {
- *this = *this+v;
- return *this;
- }
-
- Vertex& operator -= (float v) {
- *this = *this-v;
- return *this;
- }
+ Vertex& operator += (float v) {
+ *this = *this+v;
+ return *this;
+ }
+
+ Vertex& operator -= (float v) {
+ *this = *this-v;
+ return *this;
+ }
*/
- Vertex& operator *= (float v) {
- *this = *this*v;
- return *this;
- }
+ Vertex& operator *= (float v) {
+ *this = *this*v;
+ return *this;
+ }
- Vertex& operator /= (float v) {
- *this = *this/v;
- return *this;
- }
+ Vertex& operator /= (float v) {
+ *this = *this/v;
+ return *this;
+ }
public:
- // ----------------------------------------------------------------------------
- /** Convert back to non-interleaved storage */
- void SortBack(aiMesh* out, unsigned int idx) const {
+ // ----------------------------------------------------------------------------
+ /** Convert back to non-interleaved storage */
+ void SortBack(aiMesh* out, unsigned int idx) const {
- ai_assert(idx<out->mNumVertices);
- out->mVertices[idx] = position;
+ ai_assert(idx<out->mNumVertices);
+ out->mVertices[idx] = position;
- if (out->HasNormals()) {
- out->mNormals[idx] = normal;
- }
+ if (out->HasNormals()) {
+ out->mNormals[idx] = normal;
+ }
- if (out->HasTangentsAndBitangents()) {
- out->mTangents[idx] = tangent;
- out->mBitangents[idx] = bitangent;
- }
+ if (out->HasTangentsAndBitangents()) {
+ out->mTangents[idx] = tangent;
+ out->mBitangents[idx] = bitangent;
+ }
- for(unsigned int i = 0; out->HasTextureCoords(i); ++i) {
- out->mTextureCoords[i][idx] = texcoords[i];
- }
+ for(unsigned int i = 0; out->HasTextureCoords(i); ++i) {
+ out->mTextureCoords[i][idx] = texcoords[i];
+ }
- for(unsigned int i = 0; out->HasVertexColors(i); ++i) {
- out->mColors[i][idx] = colors[i];
- }
- }
+ for(unsigned int i = 0; out->HasVertexColors(i); ++i) {
+ out->mColors[i][idx] = colors[i];
+ }
+ }
private:
- // ----------------------------------------------------------------------------
- /** Construct from two operands and a binary operation to combine them */
- template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
- // this is a heavy task for the compiler to optimize ... *pray*
-
- Vertex res;
- res.position = op<aiVector3D>()(v0.position,v1.position);
- res.normal = op<aiVector3D>()(v0.normal,v1.normal);
- res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent);
- res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent);
-
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]);
- }
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
- res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]);
- }
- return res;
- }
-
- // ----------------------------------------------------------------------------
- /** This time binary arithmetics of v0 with a floating-point number */
- template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, float f) {
- // this is a heavy task for the compiler to optimize ... *pray*
-
- Vertex res;
- res.position = op<aiVector3D,float,aiVector3D>()(v0.position,f);
- res.normal = op<aiVector3D,float,aiVector3D>()(v0.normal,f);
- res.tangent = op<aiVector3D,float,aiVector3D>()(v0.tangent,f);
- res.bitangent = op<aiVector3D,float,aiVector3D>()(v0.bitangent,f);
-
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- res.texcoords[i] = op<aiVector3D,float,aiVector3D>()(v0.texcoords[i],f);
- }
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
- res.colors[i] = op<aiColor4D,float,aiColor4D>()(v0.colors[i],f);
- }
- return res;
- }
-
- // ----------------------------------------------------------------------------
- /** This time binary arithmetics of v0 with a floating-point number */
- template <template <typename, typename, typename> class op> static Vertex BinaryOp(float f, const Vertex& v0) {
- // this is a heavy task for the compiler to optimize ... *pray*
-
- Vertex res;
- res.position = op<float,aiVector3D,aiVector3D>()(f,v0.position);
- res.normal = op<float,aiVector3D,aiVector3D>()(f,v0.normal);
- res.tangent = op<float,aiVector3D,aiVector3D>()(f,v0.tangent);
- res.bitangent = op<float,aiVector3D,aiVector3D>()(f,v0.bitangent);
-
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
- res.texcoords[i] = op<float,aiVector3D,aiVector3D>()(f,v0.texcoords[i]);
- }
- for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
- res.colors[i] = op<float,aiColor4D,aiColor4D>()(f,v0.colors[i]);
- }
- return res;
- }
+ // ----------------------------------------------------------------------------
+ /** Construct from two operands and a binary operation to combine them */
+ template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<aiVector3D>()(v0.position,v1.position);
+ res.normal = op<aiVector3D>()(v0.normal,v1.normal);
+ res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent);
+ res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]);
+ }
+ return res;
+ }
+
+ // ----------------------------------------------------------------------------
+ /** This time binary arithmetics of v0 with a floating-point number */
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, float f) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<aiVector3D,float,aiVector3D>()(v0.position,f);
+ res.normal = op<aiVector3D,float,aiVector3D>()(v0.normal,f);
+ res.tangent = op<aiVector3D,float,aiVector3D>()(v0.tangent,f);
+ res.bitangent = op<aiVector3D,float,aiVector3D>()(v0.bitangent,f);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<aiVector3D,float,aiVector3D>()(v0.texcoords[i],f);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<aiColor4D,float,aiColor4D>()(v0.colors[i],f);
+ }
+ return res;
+ }
+
+ // ----------------------------------------------------------------------------
+ /** This time binary arithmetics of v0 with a floating-point number */
+ template <template <typename, typename, typename> class op> static Vertex BinaryOp(float f, const Vertex& v0) {
+ // this is a heavy task for the compiler to optimize ... *pray*
+
+ Vertex res;
+ res.position = op<float,aiVector3D,aiVector3D>()(f,v0.position);
+ res.normal = op<float,aiVector3D,aiVector3D>()(f,v0.normal);
+ res.tangent = op<float,aiVector3D,aiVector3D>()(f,v0.tangent);
+ res.bitangent = op<float,aiVector3D,aiVector3D>()(f,v0.bitangent);
+
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ res.texcoords[i] = op<float,aiVector3D,aiVector3D>()(f,v0.texcoords[i]);
+ }
+ for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+ res.colors[i] = op<float,aiColor4D,aiColor4D>()(f,v0.colors[i]);
+ }
+ return res;
+ }
public:
- aiVector3D position;
- aiVector3D normal;
- aiVector3D tangent, bitangent;
+ aiVector3D position;
+ aiVector3D normal;
+ aiVector3D tangent, bitangent;
- aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
+ aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
};
// ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE Vertex operator + (const Vertex& v0,const Vertex& v1) {
- return Vertex::BinaryOp<std::plus>(v0,v1);
+ return Vertex::BinaryOp<std::plus>(v0,v1);
}
AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) {
- return Vertex::BinaryOp<std::minus>(v0,v1);
+ return Vertex::BinaryOp<std::minus>(v0,v1);
}
// ------------------------------------------------------------------------------------------------
/*
AI_FORCE_INLINE Vertex operator + (const Vertex& v0,float f) {
- return Vertex::BinaryOp<Intern::plus>(v0,f);
+ return Vertex::BinaryOp<Intern::plus>(v0,f);
}
AI_FORCE_INLINE Vertex operator - (const Vertex& v0,float f) {
- return Vertex::BinaryOp<Intern::minus>(v0,f);
+ return Vertex::BinaryOp<Intern::minus>(v0,f);
}
*/
AI_FORCE_INLINE Vertex operator * (const Vertex& v0,float f) {
- return Vertex::BinaryOp<Intern::multiplies>(v0,f);
+ return Vertex::BinaryOp<Intern::multiplies>(v0,f);
}
AI_FORCE_INLINE Vertex operator / (const Vertex& v0,float f) {
- return Vertex::BinaryOp<Intern::multiplies>(v0,1.f/f);
+ return Vertex::BinaryOp<Intern::multiplies>(v0,1.f/f);
}
// ------------------------------------------------------------------------------------------------
/*
AI_FORCE_INLINE Vertex operator + (float f,const Vertex& v0) {
- return Vertex::BinaryOp<Intern::plus>(f,v0);
+ return Vertex::BinaryOp<Intern::plus>(f,v0);
}
AI_FORCE_INLINE Vertex operator - (float f,const Vertex& v0) {
- return Vertex::BinaryOp<Intern::minus>(f,v0);
+ return Vertex::BinaryOp<Intern::minus>(f,v0);
}
*/
AI_FORCE_INLINE Vertex operator * (float f,const Vertex& v0) {
- return Vertex::BinaryOp<Intern::multiplies>(f,v0);
+ return Vertex::BinaryOp<Intern::multiplies>(f,v0);
}
/*
AI_FORCE_INLINE Vertex operator / (float f,const Vertex& v0) {
- return Vertex::BinaryOp<Intern::divides>(f,v0);
+ return Vertex::BinaryOp<Intern::divides>(f,v0);
}
*/
diff --git a/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp b/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp
index ef859aaa7..6de55ab34 100644
--- a/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp
+++ b/src/3rdparty/assimp/code/VertexTriangleAdjacency.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -42,94 +42,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the VertexTriangleAdjacency helper class
*/
-#include "AssimpPCH.h"
-
// 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*/)
+ 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(3 == pcFace->mNumIndices);
- iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
- iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
- iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
- }
- }
-
- this->iNumVertices = 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)
- {
- pi[pcFace->mIndices[0]]++;
- pi[pcFace->mIndices[1]]++;
- pi[pcFace->mIndices[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 int idx = pcFace->mIndices[0];
- mAdjacencyTable[pi[idx]++] = iSum;
-
- idx = pcFace->mIndices[1];
- mAdjacencyTable[pi[idx]++] = iSum;
-
- idx = pcFace->mIndices[2];
- mAdjacencyTable[pi[idx]++] = 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;
+ // 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(3 == pcFace->mNumIndices);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]);
+ iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]);
+ }
+ }
+
+ this->iNumVertices = 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)
+ {
+ pi[pcFace->mIndices[0]]++;
+ pi[pcFace->mIndices[1]]++;
+ pi[pcFace->mIndices[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 int idx = pcFace->mIndices[0];
+ mAdjacencyTable[pi[idx]++] = iSum;
+
+ idx = pcFace->mIndices[1];
+ mAdjacencyTable[pi[idx]++] = iSum;
+
+ idx = pcFace->mIndices[2];
+ mAdjacencyTable[pi[idx]++] = 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;
+ // delete allocated storage
+ delete[] mOffsetTable;
+ delete[] mAdjacencyTable;
+ delete[] mLiveTriangles;
}
diff --git a/src/3rdparty/assimp/code/VertexTriangleAdjacency.h b/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
index 9a60fc942..218607508 100644
--- a/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
+++ b/src/3rdparty/assimp/code/VertexTriangleAdjacency.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -43,11 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_VTADJACENCY_H_INC
#include "BaseProcess.h"
-#include "../include/assimp/types.h"
-#include "../include/assimp/ai_assert.h"
+#include <assimp/types.h>
+#include <assimp/ai_assert.h>
struct aiMesh;
-namespace Assimp {
+struct aiFace;
+
+namespace Assimp {
// --------------------------------------------------------------------------------------------
/** @brief The VertexTriangleAdjacency class computes a vertex-triangle
@@ -60,63 +62,63 @@ 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 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 Destructor */
+ ~VertexTriangleAdjacency();
public:
- // ----------------------------------------------------------------------------
- /** @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 < iNumVertices);
- 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 < iNumVertices && NULL != mLiveTriangles);
- return mLiveTriangles[iVertIndex];
- }
+ // ----------------------------------------------------------------------------
+ /** @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 < iNumVertices);
+ 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 < iNumVertices && NULL != mLiveTriangles);
+ return mLiveTriangles[iVertIndex];
+ }
public:
- //! Offset table
- unsigned int* mOffsetTable;
+ //! Offset table
+ unsigned int* mOffsetTable;
- //! Adjacency table
- unsigned int* mAdjacencyTable;
+ //! Adjacency table
+ unsigned int* mAdjacencyTable;
- //! Table containing the number of referenced triangles per vertex
- unsigned int* mLiveTriangles;
+ //! Table containing the number of referenced triangles per vertex
+ unsigned int* mLiveTriangles;
- //! Debug: Number of referenced vertices
- unsigned int iNumVertices;
+ //! Debug: Number of referenced vertices
+ unsigned int iNumVertices;
};
}
diff --git a/src/3rdparty/assimp/code/Win32DebugLogStream.h b/src/3rdparty/assimp/code/Win32DebugLogStream.h
index 5bcb03406..c7bd8ca62 100644
--- a/src/3rdparty/assimp/code/Win32DebugLogStream.h
+++ b/src/3rdparty/assimp/code/Win32DebugLogStream.h
@@ -3,48 +3,48 @@
#ifdef WIN32
-#include "../include/assimp/LogStream.hpp"
+#include <assimp/LogStream.hpp>
#include "windows.h"
-namespace Assimp {
+namespace Assimp {
// ---------------------------------------------------------------------------
-/** @class Win32DebugLogStream
- * @brief Logs into the debug stream from win32.
+/** @class Win32DebugLogStream
+ * @brief Logs into the debug stream from win32.
*/
class Win32DebugLogStream :
- public LogStream
+ public LogStream
{
public:
- /** @brief Default constructor */
- Win32DebugLogStream();
-
- /** @brief Destructor */
- ~Win32DebugLogStream();
-
- /** @brief Writer */
- void write(const char* messgae);
+ /** @brief Default constructor */
+ Win32DebugLogStream();
+
+ /** @brief Destructor */
+ ~Win32DebugLogStream();
+
+ /** @brief Writer */
+ void write(const char* messgae);
};
// ---------------------------------------------------------------------------
-// Default constructor
+// Default constructor
inline Win32DebugLogStream::Win32DebugLogStream()
{}
// ---------------------------------------------------------------------------
-// Default constructor
+// Default constructor
inline Win32DebugLogStream::~Win32DebugLogStream()
{}
// ---------------------------------------------------------------------------
-// Write method
+// Write method
inline void Win32DebugLogStream::write(const char* message)
{
- OutputDebugStringA( message);
+ OutputDebugStringA( message);
}
// ---------------------------------------------------------------------------
-} // Namespace Assimp
+} // Namespace Assimp
#endif // ! WIN32
#endif // guard
diff --git a/src/3rdparty/assimp/code/XFileExporter.cpp b/src/3rdparty/assimp/code/XFileExporter.cpp
new file mode 100644
index 000000000..8d5e75d3e
--- /dev/null
+++ b/src/3rdparty/assimp/code/XFileExporter.cpp
@@ -0,0 +1,532 @@
+/*
+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.
+
+@author: Richard Steffen, 2014
+----------------------------------------------------------------------
+*/
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
+#include "XFileExporter.h"
+#include "ConvertToLHProcess.h"
+#include "Bitmap.h"
+#include "BaseImporter.h"
+#include "fast_atof.h"
+#include "SceneCombiner.h"
+#include "DefaultIOSystem.h"
+#include <ctime>
+#include <set>
+#include <memory>
+#include "Exceptional.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/light.h>
+
+using namespace Assimp;
+
+namespace Assimp
+{
+
+// ------------------------------------------------------------------------------------------------
+// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
+void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+ std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
+ std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
+
+ // create/copy Properties
+ ExportProperties props(*pProperties);
+
+ // set standard properties if not set
+ if (!props.HasPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT)) props.SetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT, false);
+
+ // invoke the exporter
+ XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props);
+
+ // we're still here - export successfully completed. Write result to the given IOSYstem
+ std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+ if(outfile == NULL) {
+ throw DeadlyExportError("could not open output .x file: " + std::string(pFile));
+ }
+
+ // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
+ outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
+}
+
+} // end of namespace Assimp
+
+
+// ------------------------------------------------------------------------------------------------
+// Constructor for a specific scene to export
+XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties)
+ : mProperties(pProperties),
+ mIOSystem(pIOSystem),
+ mPath(path),
+ mFile(file),
+ mScene(pScene),
+ mSceneOwned(false),
+ endstr("\n")
+{
+ // make sure that all formatting happens using the standard, C locale and not the user's current locale
+ mOutput.imbue( std::locale("C") );
+ mOutput.precision(16);
+
+ // start writing
+ WriteFile();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor
+XFileExporter::~XFileExporter()
+{
+ if(mSceneOwned) {
+ delete mScene;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Starts writing the contents
+void XFileExporter::WriteFile()
+{
+ // note, that all realnumber values must be comma separated in x files
+ mOutput.setf(std::ios::fixed);
+ mOutput.precision(16); // precission for double
+
+ // entry of writing the file
+ WriteHeader();
+
+ mOutput << startstr << "Frame DXCC_ROOT {" << endstr;
+ PushTag();
+
+ aiMatrix4x4 I; // identity
+ WriteFrameTransform(I);
+
+ WriteNode(mScene->mRootNode);
+ PopTag();
+
+ mOutput << startstr << "}" << endstr;
+
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes the asset header
+void XFileExporter::WriteHeader()
+{
+ if (mProperties->GetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT) == true)
+ mOutput << startstr << "xof 0303txt 0064" << endstr;
+ else
+ mOutput << startstr << "xof 0303txt 0032" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template Frame {" << endstr;
+ PushTag();
+ mOutput << startstr << "<3d82ab46-62da-11cf-ab39-0020af71e433>" << endstr;
+ mOutput << startstr << "[...]" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template Matrix4x4 {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f6f23f45-7686-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "array FLOAT matrix[16];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template FrameTransformMatrix {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f6f23f41-7686-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "Matrix4x4 frameMatrix;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template Vector {" << endstr;
+ PushTag();
+ mOutput << startstr << "<3d82ab5e-62da-11cf-ab39-0020af71e433>" << endstr;
+ mOutput << startstr << "FLOAT x;" << endstr;
+ mOutput << startstr << "FLOAT y;" << endstr;
+ mOutput << startstr << "FLOAT z;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template MeshFace {" << endstr;
+ PushTag();
+ mOutput << startstr << "<3d82ab5f-62da-11cf-ab39-0020af71e433>" << endstr;
+ mOutput << startstr << "DWORD nFaceVertexIndices;" << endstr;
+ mOutput << startstr << "array DWORD faceVertexIndices[nFaceVertexIndices];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template Mesh {" << endstr;
+ PushTag();
+ mOutput << startstr << "<3d82ab44-62da-11cf-ab39-0020af71e433>" << endstr;
+ mOutput << startstr << "DWORD nVertices;" << endstr;
+ mOutput << startstr << "array Vector vertices[nVertices];" << endstr;
+ mOutput << startstr << "DWORD nFaces;" << endstr;
+ mOutput << startstr << "array MeshFace faces[nFaces];" << endstr;
+ mOutput << startstr << "[...]" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template MeshNormals {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f6f23f43-7686-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "DWORD nNormals;" << endstr;
+ mOutput << startstr << "array Vector normals[nNormals];" << endstr;
+ mOutput << startstr << "DWORD nFaceNormals;" << endstr;
+ mOutput << startstr << "array MeshFace faceNormals[nFaceNormals];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template Coords2d {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f6f23f44-7686-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "FLOAT u;" << endstr;
+ mOutput << startstr << "FLOAT v;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template MeshTextureCoords {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f6f23f40-7686-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "DWORD nTextureCoords;" << endstr;
+ mOutput << startstr << "array Coords2d textureCoords[nTextureCoords];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template ColorRGBA {" << endstr;
+ PushTag();
+ mOutput << startstr << "<35ff44e0-6c7c-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "FLOAT red;" << endstr;
+ mOutput << startstr << "FLOAT green;" << endstr;
+ mOutput << startstr << "FLOAT blue;" << endstr;
+ mOutput << startstr << "FLOAT alpha;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template IndexedColor {" << endstr;
+ PushTag();
+ mOutput << startstr << "<1630b820-7842-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "DWORD index;" << endstr;
+ mOutput << startstr << "ColorRGBA indexColor;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template MeshVertexColors {" << endstr;
+ PushTag();
+ mOutput << startstr << "<1630b821-7842-11cf-8f52-0040333594a3>" << endstr;
+ mOutput << startstr << "DWORD nVertexColors;" << endstr;
+ mOutput << startstr << "array IndexedColor vertexColors[nVertexColors];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template VertexElement {" << endstr;
+ PushTag();
+ mOutput << startstr << "<f752461c-1e23-48f6-b9f8-8350850f336f>" << endstr;
+ mOutput << startstr << "DWORD Type;" << endstr;
+ mOutput << startstr << "DWORD Method;" << endstr;
+ mOutput << startstr << "DWORD Usage;" << endstr;
+ mOutput << startstr << "DWORD UsageIndex;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+ mOutput << startstr << "template DeclData {" << endstr;
+ PushTag();
+ mOutput << startstr << "<bf22e553-292c-4781-9fea-62bd554bdd93>" << endstr;
+ mOutput << startstr << "DWORD nElements;" << endstr;
+ mOutput << startstr << "array VertexElement Elements[nElements];" << endstr;
+ mOutput << startstr << "DWORD nDWords;" << endstr;
+ mOutput << startstr << "array DWORD data[nDWords];" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ mOutput << endstr;
+}
+
+
+// Writes the material setup
+void XFileExporter::WriteFrameTransform(aiMatrix4x4& m)
+{
+ mOutput << startstr << "FrameTransformMatrix {" << endstr << " ";
+ PushTag();
+ mOutput << startstr << m.a1 << ", " << m.b1 << ", " << m.c1 << ", " << m.d1 << "," << endstr;
+ mOutput << startstr << m.a2 << ", " << m.b2 << ", " << m.c2 << ", " << m.d2 << "," << endstr;
+ mOutput << startstr << m.a3 << ", " << m.b3 << ", " << m.c3 << ", " << m.d3 << "," << endstr;
+ mOutput << startstr << m.a4 << ", " << m.b4 << ", " << m.c4 << ", " << m.d4 << ";;" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr << endstr;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Recursively writes the given node
+void XFileExporter::WriteNode( aiNode* pNode)
+{
+ if (pNode->mName.length==0)
+ {
+ std::stringstream ss;
+ ss << "Node_" << pNode;
+ pNode->mName.Set(ss.str());
+ }
+ mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr;
+
+ PushTag();
+
+ aiMatrix4x4 m = pNode->mTransformation;
+
+ WriteFrameTransform(m);
+
+ for (size_t i = 0; i < pNode->mNumMeshes; ++i)
+ WriteMesh(mScene->mMeshes[pNode->mMeshes[i]]);
+
+ // recursive call the Nodes
+ for (size_t i = 0; i < pNode->mNumChildren; ++i)
+ WriteNode(pNode->mChildren[i]);
+
+ PopTag();
+
+ mOutput << startstr << "}" << endstr << endstr;
+}
+
+void XFileExporter::WriteMesh(aiMesh* mesh)
+{
+ mOutput << startstr << "Mesh " << toXFileString(mesh->mName) << "_mShape" << " {" << endstr;
+
+ PushTag();
+
+ // write all the vertices
+ mOutput << startstr << mesh->mNumVertices << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumVertices; a++)
+ {
+ aiVector3D &v = mesh->mVertices[a];
+ mOutput << startstr << v[0] << ";"<< v[1] << ";" << v[2] << ";";
+ if (a < mesh->mNumVertices - 1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+
+ // write all the faces
+ mOutput << startstr << mesh->mNumFaces << ";" << endstr;
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ const aiFace& face = mesh->mFaces[a];
+ mOutput << startstr << face.mNumIndices << ";";
+ // must be counter clockwise triangle
+ //for(int b = face.mNumIndices - 1; b >= 0 ; --b)
+ for(size_t b = 0; b < face.mNumIndices ; ++b)
+ {
+ mOutput << face.mIndices[b];
+ //if (b > 0)
+ if (b<face.mNumIndices-1)
+ mOutput << ",";
+ else
+ mOutput << ";";
+ }
+
+ if (a < mesh->mNumFaces - 1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+
+ mOutput << endstr;
+
+ if (mesh->HasTextureCoords(0))
+ {
+ const aiMaterial* mat = mScene->mMaterials[mesh->mMaterialIndex];
+ aiString relpath;
+ mat->Get(_AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0, relpath);
+
+ mOutput << startstr << "MeshMaterialList {" << endstr;
+ PushTag();
+ mOutput << startstr << "1;" << endstr; // number of materials
+ mOutput << startstr << mesh->mNumFaces << ";" << endstr; // number of faces
+ mOutput << startstr;
+ for( size_t a = 0; a < mesh->mNumFaces; ++a )
+ {
+ mOutput << "0"; // the material index
+ if (a < mesh->mNumFaces - 1)
+ mOutput << ", ";
+ else
+ mOutput << ";" << endstr;
+ }
+ mOutput << startstr << "Material {" << endstr;
+ PushTag();
+ mOutput << startstr << "1.0; 1.0; 1.0; 1.000000;;" << endstr;
+ mOutput << startstr << "1.000000;" << endstr; // power
+ mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // specularity
+ mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // emission
+ mOutput << startstr << "TextureFilename { \"";
+
+ writePath(relpath);
+
+ mOutput << "\"; }" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ PopTag();
+ mOutput << startstr << "}" << endstr;
+ }
+
+ // write normals (every vertex has one)
+ if (mesh->HasNormals())
+ {
+ mOutput << endstr << startstr << "MeshNormals {" << endstr;
+ mOutput << startstr << mesh->mNumVertices << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumVertices; a++)
+ {
+ aiVector3D &v = mesh->mNormals[a];
+ // because we have a LHS and also changed wth winding, we need to invert the normals again
+ mOutput << startstr << -v[0] << ";"<< -v[1] << ";" << -v[2] << ";";
+ if (a < mesh->mNumVertices - 1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+
+ mOutput << startstr << mesh->mNumFaces << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumFaces; a++)
+ {
+ const aiFace& face = mesh->mFaces[a];
+ mOutput << startstr << face.mNumIndices << ";";
+
+ //for(int b = face.mNumIndices-1; b >= 0 ; --b)
+ for(size_t b = 0; b < face.mNumIndices ; ++b)
+ {
+ mOutput << face.mIndices[b];
+ //if (b > 0)
+ if (b<face.mNumIndices-1)
+ mOutput << ",";
+ else
+ mOutput << ";";
+ }
+
+ if (a < mesh->mNumFaces-1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+ mOutput << startstr << "}" << endstr;
+ }
+
+ // write texture UVs if available
+ if (mesh->HasTextureCoords(0))
+ {
+ mOutput << endstr << startstr << "MeshTextureCoords {" << endstr;
+ mOutput << startstr << mesh->mNumVertices << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumVertices; a++)
+ //for (int a = (int)mesh->mNumVertices-1; a >=0 ; a--)
+ {
+ aiVector3D& uv = mesh->mTextureCoords[0][a]; // uv of first uv layer for the vertex
+ mOutput << startstr << uv.x << ";" << uv.y;
+ if (a < mesh->mNumVertices-1)
+ //if (a >0 )
+ mOutput << ";," << endstr;
+ else
+ mOutput << ";;" << endstr;
+ }
+ mOutput << startstr << "}" << endstr;
+ }
+
+ // write color channel if available
+ if (mesh->HasVertexColors(0))
+ {
+ mOutput << endstr << startstr << "MeshVertexColors {" << endstr;
+ mOutput << startstr << mesh->mNumVertices << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumVertices; a++)
+ {
+ aiColor4D& mColors = mesh->mColors[0][a]; // color of first vertex color set for the vertex
+ mOutput << startstr << a << ";" << mColors.r << ";" << mColors.g << ";" << mColors.b << ";" << mColors.a << ";;";
+ if (a < mesh->mNumVertices-1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+ mOutput << startstr << "}" << endstr;
+ }
+ /*
+ else
+ {
+ mOutput << endstr << startstr << "MeshVertexColors {" << endstr;
+ mOutput << startstr << mesh->mNumVertices << ";" << endstr;
+ for (size_t a = 0; a < mesh->mNumVertices; a++)
+ {
+ aiColor4D* mColors = mesh->mColors[a];
+ mOutput << startstr << a << ";0.500000;0.000000;0.000000;0.500000;;";
+ if (a < mesh->mNumVertices-1)
+ mOutput << "," << endstr;
+ else
+ mOutput << ";" << endstr;
+ }
+ mOutput << startstr << "}" << endstr;
+ }
+ */
+ PopTag();
+ mOutput << startstr << "}" << endstr << endstr;
+
+}
+
+std::string XFileExporter::toXFileString(aiString &name)
+{
+ std::string pref = ""; // node name prefix to prevent unexpected start of string
+ std::string str = pref + std::string(name.C_Str());
+ for (int i=0; i < (int) str.length(); ++i)
+ {
+ if ((str[i] >= '0' && str[i] <= '9') || // 0-9
+ (str[i] >= 'A' && str[i] <= 'Z') || // A-Z
+ (str[i] >= 'a' && str[i] <= 'z')) // a-z
+ continue;
+ str[i] = '_';
+ }
+ return str;
+}
+
+void XFileExporter::writePath(aiString path)
+{
+ std::string str = std::string(path.C_Str());
+ BaseImporter::ConvertUTF8toISO8859_1(str);
+
+ while( str.find( "\\\\") != std::string::npos)
+ str.replace( str.find( "\\\\"), 2, "\\");
+
+ while( str.find( "\\") != std::string::npos)
+ str.replace( str.find( "\\"), 1, "/");
+
+ mOutput << str;
+
+}
+
+#endif
+#endif
diff --git a/src/3rdparty/assimp/code/XFileExporter.h b/src/3rdparty/assimp/code/XFileExporter.h
new file mode 100644
index 000000000..c33de3347
--- /dev/null
+++ b/src/3rdparty/assimp/code/XFileExporter.h
@@ -0,0 +1,135 @@
+/*
+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.
+
+@author: Richard Steffen, 2014
+
+----------------------------------------------------------------------
+*/
+
+/** @file XFileExporter.h
+ * Declares the exporter class to write a scene to a Collada file
+ */
+#ifndef AI_XFILEEXPORTER_H_INC
+#define AI_XFILEEXPORTER_H_INC
+
+#include <assimp/ai_assert.h>
+#include <assimp/matrix4x4.h>
+#include <assimp/Exporter.hpp>
+#include <sstream>
+
+struct aiScene;
+struct aiNode;
+struct aiMesh;
+struct aiString;
+
+namespace Assimp {
+
+class IOSystem;
+
+
+/// Helper class to export a given scene to a X-file.
+/// Note: an xFile uses a left hand system. Assimp used a right hand system (OpenGL), therefore we have to transform everything
+class XFileExporter
+{
+public:
+ /// Constructor for a specific scene to export
+ XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties);
+
+ /// Destructor
+ virtual ~XFileExporter();
+
+protected:
+ /// Starts writing the contents
+ void WriteFile();
+
+ /// Writes the asset header
+ void WriteHeader();
+
+ /// write a frame transform
+ void WriteFrameTransform(aiMatrix4x4& m);
+
+ /// Recursively writes the given node
+ void WriteNode( aiNode* pNode );
+
+ /// write a mesh entry of the scene
+ void WriteMesh( aiMesh* mesh);
+
+ /// Enters a new xml element, which increases the indentation
+ void PushTag() { startstr.append( " "); }
+
+ /// Leaves an element, decreasing the indentation
+ void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
+
+public:
+ /// Stringstream to write all output into
+ std::stringstream mOutput;
+
+protected:
+
+ /// normalize the name to be accepted by xfile readers
+ std::string toXFileString(aiString &name);
+
+ /// hold the properties pointer
+ const ExportProperties* mProperties;
+
+ /// write a path
+ void writePath(aiString path);
+
+ /// The IOSystem for output
+ IOSystem* mIOSystem;
+
+ /// Path of the directory where the scene will be exported
+ const std::string mPath;
+
+ /// Name of the file (without extension) where the scene will be exported
+ const std::string mFile;
+
+ /// The scene to be written
+ const aiScene* mScene;
+ bool mSceneOwned;
+
+ /// current line start string, contains the current indentation for simple stream insertion
+ std::string startstr;
+
+ /// current line end string for simple stream insertion
+ std::string endstr;
+
+};
+
+}
+
+#endif // !! AI_XFILEEXPORTER_H_INC
diff --git a/src/3rdparty/assimp/code/XFileHelper.h b/src/3rdparty/assimp/code/XFileHelper.h
index 792055437..484952106 100644
--- a/src/3rdparty/assimp/code/XFileHelper.h
+++ b/src/3rdparty/assimp/code/XFileHelper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,11 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
+#include <stdint.h>
-#include "../include/assimp/types.h"
-#include "../include/assimp/quaternion.h"
-#include "../include/assimp/mesh.h"
-#include "../include/assimp/anim.h"
+#include <assimp/types.h>
+#include <assimp/quaternion.h>
+#include <assimp/mesh.h>
+#include <assimp/anim.h>
+#include "Defines.h"
namespace Assimp
{
@@ -59,141 +61,146 @@ namespace XFile
/** Helper structure representing a XFile mesh face */
struct Face
{
- std::vector<unsigned int> mIndices;
+ std::vector<unsigned int> mIndices;
};
/** Helper structure representing a texture filename inside a material and its potential source */
struct TexEntry
{
- std::string mName;
- bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag
+ std::string mName;
+ bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag
- TexEntry() { mIsNormalMap = false; }
- TexEntry( const std::string& pName, bool pIsNormalMap = false)
- : mName( pName), mIsNormalMap( pIsNormalMap)
- { /* done */ }
+ TexEntry() { mIsNormalMap = false; }
+ TexEntry( const std::string& pName, bool pIsNormalMap = false)
+ : mName( pName), mIsNormalMap( pIsNormalMap)
+ { /* done */ }
};
/** Helper structure representing a XFile material */
struct Material
{
- std::string mName;
- bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list
- aiColor4D mDiffuse;
- float mSpecularExponent;
- aiColor3D mSpecular;
- aiColor3D mEmissive;
- std::vector<TexEntry> mTextures;
-
- size_t sceneIndex; ///< the index under which it was stored in the scene's material list
-
- Material() { mIsReference = false; sceneIndex = SIZE_MAX; }
+ std::string mName;
+ bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list
+ aiColor4D mDiffuse;
+ float mSpecularExponent;
+ aiColor3D mSpecular;
+ aiColor3D mEmissive;
+ std::vector<TexEntry> mTextures;
+
+ size_t sceneIndex; ///< the index under which it was stored in the scene's material list
+
+ Material()
+ : mIsReference(false),
+ mSpecularExponent(),
+ sceneIndex(SIZE_MAX)
+ {}
};
/** Helper structure to represent a bone weight */
struct BoneWeight
{
- unsigned int mVertex;
- float mWeight;
+ unsigned int mVertex;
+ float mWeight;
};
/** Helper structure to represent a bone in a mesh */
struct Bone
{
- std::string mName;
- std::vector<BoneWeight> mWeights;
- aiMatrix4x4 mOffsetMatrix;
+ std::string mName;
+ std::vector<BoneWeight> mWeights;
+ aiMatrix4x4 mOffsetMatrix;
};
/** Helper structure to represent an XFile mesh */
struct Mesh
{
- std::vector<aiVector3D> mPositions;
- std::vector<Face> mPosFaces;
- std::vector<aiVector3D> mNormals;
- std::vector<Face> mNormFaces;
- unsigned int mNumTextures;
- std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
- unsigned int mNumColorSets;
- std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
- std::vector<unsigned int> mFaceMaterials;
- std::vector<Material> mMaterials;
-
- std::vector<Bone> mBones;
-
- Mesh() { mNumTextures = 0; mNumColorSets = 0; }
+ std::string mName;
+ std::vector<aiVector3D> mPositions;
+ std::vector<Face> mPosFaces;
+ std::vector<aiVector3D> mNormals;
+ std::vector<Face> mNormFaces;
+ unsigned int mNumTextures;
+ std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+ unsigned int mNumColorSets;
+ std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+ std::vector<unsigned int> mFaceMaterials;
+ std::vector<Material> mMaterials;
+
+ std::vector<Bone> mBones;
+
+ explicit Mesh(const std::string &pName = "") { mName = pName; mNumTextures = 0; mNumColorSets = 0; }
};
/** Helper structure to represent a XFile frame */
struct Node
{
- std::string mName;
- aiMatrix4x4 mTrafoMatrix;
- Node* mParent;
- std::vector<Node*> mChildren;
- std::vector<Mesh*> mMeshes;
-
- Node() { mParent = NULL; }
- Node( Node* pParent) { mParent = pParent; }
- ~Node()
- {
- for( unsigned int a = 0; a < mChildren.size(); a++)
- delete mChildren[a];
- for( unsigned int a = 0; a < mMeshes.size(); a++)
- delete mMeshes[a];
- }
+ std::string mName;
+ aiMatrix4x4 mTrafoMatrix;
+ Node* mParent;
+ std::vector<Node*> mChildren;
+ std::vector<Mesh*> mMeshes;
+
+ Node() { mParent = NULL; }
+ explicit Node( Node* pParent) { mParent = pParent; }
+ ~Node()
+ {
+ for( unsigned int a = 0; a < mChildren.size(); a++)
+ delete mChildren[a];
+ for( unsigned int a = 0; a < mMeshes.size(); a++)
+ delete mMeshes[a];
+ }
};
struct MatrixKey
{
- double mTime;
- aiMatrix4x4 mMatrix;
+ double mTime;
+ aiMatrix4x4 mMatrix;
};
/** Helper structure representing a single animated bone in a XFile */
struct AnimBone
{
- std::string mBoneName;
- std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling
- std::vector<aiQuatKey> mRotKeys;
- std::vector<aiVectorKey> mScaleKeys;
- std::vector<MatrixKey> mTrafoKeys; // or a combined key sequence of transformation matrices.
+ std::string mBoneName;
+ std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling
+ std::vector<aiQuatKey> mRotKeys;
+ std::vector<aiVectorKey> mScaleKeys;
+ std::vector<MatrixKey> mTrafoKeys; // or a combined key sequence of transformation matrices.
};
/** Helper structure to represent an animation set in a XFile */
struct Animation
{
- std::string mName;
- std::vector<AnimBone*> mAnims;
-
- ~Animation()
- {
- for( unsigned int a = 0; a < mAnims.size(); a++)
- delete mAnims[a];
- }
+ std::string mName;
+ std::vector<AnimBone*> mAnims;
+
+ ~Animation()
+ {
+ for( unsigned int a = 0; a < mAnims.size(); a++)
+ delete mAnims[a];
+ }
};
/** Helper structure analogue to aiScene */
struct Scene
{
- Node* mRootNode;
-
- std::vector<Mesh*> mGlobalMeshes; // global meshes found outside of any frames
- std::vector<Material> mGlobalMaterials; // global materials found outside of any meshes.
-
- std::vector<Animation*> mAnims;
- unsigned int mAnimTicksPerSecond;
-
- Scene() { mRootNode = NULL; mAnimTicksPerSecond = 0; }
- ~Scene()
- {
- delete mRootNode;
- for( unsigned int a = 0; a < mGlobalMeshes.size(); a++)
- delete mGlobalMeshes[a];
- for( unsigned int a = 0; a < mAnims.size(); a++)
- delete mAnims[a];
- }
+ Node* mRootNode;
+
+ std::vector<Mesh*> mGlobalMeshes; // global meshes found outside of any frames
+ std::vector<Material> mGlobalMaterials; // global materials found outside of any meshes.
+
+ std::vector<Animation*> mAnims;
+ unsigned int mAnimTicksPerSecond;
+
+ Scene() { mRootNode = NULL; mAnimTicksPerSecond = 0; }
+ ~Scene()
+ {
+ delete mRootNode;
+ for( unsigned int a = 0; a < mGlobalMeshes.size(); a++)
+ delete mGlobalMeshes[a];
+ for( unsigned int a = 0; a < mAnims.size(); a++)
+ delete mAnims[a];
+ }
};
} // end of namespace XFile
diff --git a/src/3rdparty/assimp/code/XFileImporter.cpp b/src/3rdparty/assimp/code/XFileImporter.cpp
index d100692d3..9510ab3de 100644
--- a/src/3rdparty/assimp/code/XFileImporter.cpp
+++ b/src/3rdparty/assimp/code/XFileImporter.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,43 +25,53 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file XFileImporter.cpp
- * @brief Implementation of the XFile importer class
+ * @brief Implementation of the XFile importer class
*/
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
#include "XFileImporter.h"
#include "XFileParser.h"
+#include "Defines.h"
+#include "TinyFormatter.h"
#include "ConvertToLHProcess.h"
+#include <assimp/IOSystem.hpp>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <cctype>
+#include <memory>
+
+
using namespace Assimp;
+using namespace Assimp::Formatter;
static const aiImporterDesc desc = {
- "Direct3D XFile Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
- 1,
- 3,
- 1,
- 5,
- "x"
+ "Direct3D XFile Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+ 1,
+ 3,
+ 1,
+ 5,
+ "x"
};
// ------------------------------------------------------------------------------------------------
@@ -70,507 +80,514 @@ XFileImporter::XFileImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
XFileImporter::~XFileImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- std::string extension = GetExtension(pFile);
- if(extension == "x") {
- return true;
- }
- if (!extension.length() || checkSig) {
- uint32_t token[1];
- token[0] = AI_MAKE_MAGIC("xof ");
- return CheckMagicToken(pIOHandler,pFile,token,1,0);
- }
- return false;
+ std::string extension = GetExtension(pFile);
+ if(extension == "x") {
+ return true;
+ }
+ if (!extension.length() || checkSig) {
+ uint32_t token[1];
+ token[0] = AI_MAKE_MAGIC("xof ");
+ return CheckMagicToken(pIOHandler,pFile,token,1,0);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get file extension list
const aiImporterDesc* XFileImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
+// Imports the given file into the given scene structure.
void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
- // read file into memory
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
- if( file.get() == NULL)
- throw DeadlyImportError( "Failed to open file " + pFile + ".");
+ // read file into memory
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open file " + pFile + ".");
- size_t fileSize = file->FileSize();
- if( fileSize < 16)
- throw DeadlyImportError( "XFile is too small.");
+ size_t fileSize = file->FileSize();
+ if( fileSize < 16)
+ throw DeadlyImportError( "XFile is too small.");
- // in the hope that binary files will never start with a BOM ...
- mBuffer.resize( fileSize + 1);
- file->Read( &mBuffer.front(), 1, fileSize);
- ConvertToUTF8(mBuffer);
+ // in the hope that binary files will never start with a BOM ...
+ mBuffer.resize( fileSize + 1);
+ file->Read( &mBuffer.front(), 1, fileSize);
+ ConvertToUTF8(mBuffer);
- // parse the file into a temporary representation
- XFileParser parser( mBuffer);
+ // parse the file into a temporary representation
+ XFileParser parser( mBuffer);
- // and create the proper return structures out of it
- CreateDataRepresentationFromImport( pScene, parser.GetImportedData());
+ // and create the proper return structures out of it
+ CreateDataRepresentationFromImport( pScene, parser.GetImportedData());
- // if nothing came from it, report it as error
- if( !pScene->mRootNode)
- throw DeadlyImportError( "XFile is ill-formatted - no content imported.");
+ // if nothing came from it, report it as error
+ if( !pScene->mRootNode)
+ throw DeadlyImportError( "XFile is ill-formatted - no content imported.");
}
// ------------------------------------------------------------------------------------------------
// Constructs the return data structure out of the imported data.
void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData)
{
- // Read the global materials first so that meshes referring to them can find them later
- ConvertMaterials( pScene, pData->mGlobalMaterials);
-
- // copy nodes, extracting meshes and materials on the way
- pScene->mRootNode = CreateNodes( pScene, NULL, pData->mRootNode);
-
- // extract animations
- CreateAnimations( pScene, pData);
-
- // read the global meshes that were stored outside of any node
- if( pData->mGlobalMeshes.size() > 0)
- {
- // create a root node to hold them if there isn't any, yet
- if( pScene->mRootNode == NULL)
- {
- pScene->mRootNode = new aiNode;
- pScene->mRootNode->mName.Set( "$dummy_node");
- }
-
- // convert all global meshes and store them in the root node.
- // If there was one before, the global meshes now suddenly have its transformation matrix...
- // Don't know what to do there, I don't want to insert another node under the present root node
- // just to avoid this.
- CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes);
- }
-
- // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly
- MakeLeftHandedProcess convertProcess;
- convertProcess.Execute( pScene);
-
- FlipWindingOrderProcess flipper;
- flipper.Execute(pScene);
-
- // finally: create a dummy material if not material was imported
- if( pScene->mNumMaterials == 0)
- {
- pScene->mNumMaterials = 1;
- // create the Material
- aiMaterial* mat = new aiMaterial;
- int shadeMode = (int) aiShadingMode_Gouraud;
- mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
- // material colours
- int specExp = 1;
-
- aiColor3D clr = aiColor3D( 0, 0, 0);
- mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE);
- mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR);
-
- clr = aiColor3D( 0.5f, 0.5f, 0.5f);
- mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
-
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = mat;
- }
+ // Read the global materials first so that meshes referring to them can find them later
+ ConvertMaterials( pScene, pData->mGlobalMaterials);
+
+ // copy nodes, extracting meshes and materials on the way
+ pScene->mRootNode = CreateNodes( pScene, NULL, pData->mRootNode);
+
+ // extract animations
+ CreateAnimations( pScene, pData);
+
+ // read the global meshes that were stored outside of any node
+ if( pData->mGlobalMeshes.size() > 0)
+ {
+ // create a root node to hold them if there isn't any, yet
+ if( pScene->mRootNode == NULL)
+ {
+ pScene->mRootNode = new aiNode;
+ pScene->mRootNode->mName.Set( "$dummy_node");
+ }
+
+ // convert all global meshes and store them in the root node.
+ // If there was one before, the global meshes now suddenly have its transformation matrix...
+ // Don't know what to do there, I don't want to insert another node under the present root node
+ // just to avoid this.
+ CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes);
+ }
+
+ if (!pScene->mRootNode) {
+ throw DeadlyImportError( "No root node" );
+ }
+
+ // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly
+ MakeLeftHandedProcess convertProcess;
+ convertProcess.Execute( pScene);
+
+ FlipWindingOrderProcess flipper;
+ flipper.Execute(pScene);
+
+ // finally: create a dummy material if not material was imported
+ if( pScene->mNumMaterials == 0)
+ {
+ pScene->mNumMaterials = 1;
+ // create the Material
+ aiMaterial* mat = new aiMaterial;
+ int shadeMode = (int) aiShadingMode_Gouraud;
+ mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+ // material colours
+ int specExp = 1;
+
+ aiColor3D clr = aiColor3D( 0, 0, 0);
+ mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE);
+ mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR);
+
+ clr = aiColor3D( 0.5f, 0.5f, 0.5f);
+ mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
+
+ pScene->mMaterials = new aiMaterial*[1];
+ pScene->mMaterials[0] = mat;
+ }
}
// ------------------------------------------------------------------------------------------------
-// Recursively creates scene nodes from the imported hierarchy.
+// Recursively creates scene nodes from the imported hierarchy.
aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode)
{
- if( !pNode)
- return NULL;
-
- // create node
- aiNode* node = new aiNode;
- node->mName.length = pNode->mName.length();
- node->mParent = pParent;
- memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length());
- node->mName.data[node->mName.length] = 0;
- node->mTransformation = pNode->mTrafoMatrix;
-
- // convert meshes from the source node
- CreateMeshes( pScene, node, pNode->mMeshes);
-
- // handle childs
- if( pNode->mChildren.size() > 0)
- {
- node->mNumChildren = (unsigned int)pNode->mChildren.size();
- node->mChildren = new aiNode* [node->mNumChildren];
-
- for( unsigned int a = 0; a < pNode->mChildren.size(); a++)
- node->mChildren[a] = CreateNodes( pScene, node, pNode->mChildren[a]);
- }
-
- return node;
+ if( !pNode)
+ return NULL;
+
+ // create node
+ aiNode* node = new aiNode;
+ node->mName.length = pNode->mName.length();
+ node->mParent = pParent;
+ memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length());
+ node->mName.data[node->mName.length] = 0;
+ node->mTransformation = pNode->mTrafoMatrix;
+
+ // convert meshes from the source node
+ CreateMeshes( pScene, node, pNode->mMeshes);
+
+ // handle childs
+ if( pNode->mChildren.size() > 0)
+ {
+ node->mNumChildren = (unsigned int)pNode->mChildren.size();
+ node->mChildren = new aiNode* [node->mNumChildren];
+
+ for( unsigned int a = 0; a < pNode->mChildren.size(); a++)
+ node->mChildren[a] = CreateNodes( pScene, node, pNode->mChildren[a]);
+ }
+
+ return node;
}
// ------------------------------------------------------------------------------------------------
-// Creates the meshes for the given node.
+// Creates the meshes for the given node.
void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes)
{
- if( pMeshes.size() == 0)
- return;
-
- // create a mesh for each mesh-material combination in the source node
- std::vector<aiMesh*> meshes;
- for( unsigned int a = 0; a < pMeshes.size(); a++)
- {
- XFile::Mesh* sourceMesh = pMeshes[a];
- // first convert its materials so that we can find them with their index afterwards
- ConvertMaterials( pScene, sourceMesh->mMaterials);
-
- unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u);
- for( unsigned int b = 0; b < numMaterials; b++)
- {
- // collect the faces belonging to this material
- std::vector<unsigned int> faces;
- unsigned int numVertices = 0;
- if( sourceMesh->mFaceMaterials.size() > 0)
- {
- // if there is a per-face material defined, select the faces with the corresponding material
- for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); c++)
- {
- if( sourceMesh->mFaceMaterials[c] == b)
- {
- faces.push_back( c);
- numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
- }
- }
- } else
- {
- // if there is no per-face material, place everything into one mesh
- for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); c++)
- {
- faces.push_back( c);
- numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
- }
- }
-
- // no faces/vertices using this material? strange...
- if( numVertices == 0)
- continue;
-
- // create a submesh using this material
- aiMesh* mesh = new aiMesh;
- meshes.push_back( mesh);
-
- // find the material in the scene's material list. Either own material
- // or referenced material, it should already have a valid index
- if( sourceMesh->mFaceMaterials.size() > 0)
- {
+ if( pMeshes.size() == 0)
+ return;
+
+ // create a mesh for each mesh-material combination in the source node
+ std::vector<aiMesh*> meshes;
+ for( unsigned int a = 0; a < pMeshes.size(); a++)
+ {
+ XFile::Mesh* sourceMesh = pMeshes[a];
+ // first convert its materials so that we can find them with their index afterwards
+ ConvertMaterials( pScene, sourceMesh->mMaterials);
+
+ unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u);
+ for( unsigned int b = 0; b < numMaterials; b++)
+ {
+ // collect the faces belonging to this material
+ std::vector<unsigned int> faces;
+ unsigned int numVertices = 0;
+ if( sourceMesh->mFaceMaterials.size() > 0)
+ {
+ // if there is a per-face material defined, select the faces with the corresponding material
+ for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); c++)
+ {
+ if( sourceMesh->mFaceMaterials[c] == b)
+ {
+ faces.push_back( c);
+ numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
+ }
+ }
+ } else
+ {
+ // if there is no per-face material, place everything into one mesh
+ for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); c++)
+ {
+ faces.push_back( c);
+ numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
+ }
+ }
+
+ // no faces/vertices using this material? strange...
+ if( numVertices == 0)
+ continue;
+
+ // create a submesh using this material
+ aiMesh* mesh = new aiMesh;
+ meshes.push_back( mesh);
+
+ // find the material in the scene's material list. Either own material
+ // or referenced material, it should already have a valid index
+ if( sourceMesh->mFaceMaterials.size() > 0)
+ {
mesh->mMaterialIndex = sourceMesh->mMaterials[b].sceneIndex;
- } else
- {
- mesh->mMaterialIndex = 0;
- }
-
- // Create properly sized data arrays in the mesh. We store unique vertices per face,
- // as specified
- mesh->mNumVertices = numVertices;
- mesh->mVertices = new aiVector3D[numVertices];
- mesh->mNumFaces = (unsigned int)faces.size();
- mesh->mFaces = new aiFace[mesh->mNumFaces];
-
- // normals?
- if( sourceMesh->mNormals.size() > 0)
- mesh->mNormals = new aiVector3D[numVertices];
- // texture coords
- for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; c++)
- {
- if( sourceMesh->mTexCoords[c].size() > 0)
- mesh->mTextureCoords[c] = new aiVector3D[numVertices];
- }
- // vertex colors
- for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; c++)
- {
- if( sourceMesh->mColors[c].size() > 0)
- mesh->mColors[c] = new aiColor4D[numVertices];
- }
-
- // now collect the vertex data of all data streams present in the imported mesh
- unsigned int newIndex = 0;
- std::vector<unsigned int> orgPoints; // from which original point each new vertex stems
- orgPoints.resize( numVertices, 0);
-
- for( unsigned int c = 0; c < faces.size(); c++)
- {
- unsigned int f = faces[c]; // index of the source face
- const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face
-
- // create face. either triangle or triangle fan depending on the index count
- aiFace& df = mesh->mFaces[c]; // destination face
- df.mNumIndices = (unsigned int)pf.mIndices.size();
- df.mIndices = new unsigned int[ df.mNumIndices];
-
- // collect vertex data for indices of this face
- for( unsigned int d = 0; d < df.mNumIndices; d++)
- {
- df.mIndices[d] = newIndex;
- orgPoints[newIndex] = pf.mIndices[d];
-
- // Position
- mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]];
- // Normal, if present
- if( mesh->HasNormals())
- mesh->mNormals[newIndex] = sourceMesh->mNormals[sourceMesh->mNormFaces[f].mIndices[d]];
-
- // texture coord sets
- for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++)
- {
- if( mesh->HasTextureCoords( e))
- {
- aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]];
- mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f);
- }
- }
- // vertex color sets
- for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; e++)
- if( mesh->HasVertexColors( e))
- mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]];
-
- newIndex++;
- }
- }
-
- // there should be as much new vertices as we calculated before
- ai_assert( newIndex == numVertices);
-
- // convert all bones of the source mesh which influence vertices in this newly created mesh
- const std::vector<XFile::Bone>& bones = sourceMesh->mBones;
- std::vector<aiBone*> newBones;
- for( unsigned int c = 0; c < bones.size(); c++)
- {
- const XFile::Bone& obone = bones[c];
- // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex
- std::vector<float> oldWeights( sourceMesh->mPositions.size(), 0.0f);
- for( unsigned int d = 0; d < obone.mWeights.size(); d++)
- oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight;
-
- // collect all vertex weights that influence a vertex in the new mesh
- std::vector<aiVertexWeight> newWeights;
- newWeights.reserve( numVertices);
- for( unsigned int d = 0; d < orgPoints.size(); d++)
- {
- // does the new vertex stem from an old vertex which was influenced by this bone?
- float w = oldWeights[orgPoints[d]];
- if( w > 0.0f)
- newWeights.push_back( aiVertexWeight( d, w));
- }
-
- // if the bone has no weights in the newly created mesh, ignore it
- if( newWeights.size() == 0)
- continue;
-
- // create
- aiBone* nbone = new aiBone;
- newBones.push_back( nbone);
- // copy name and matrix
- nbone->mName.Set( obone.mName);
- nbone->mOffsetMatrix = obone.mOffsetMatrix;
- nbone->mNumWeights = (unsigned int)newWeights.size();
- nbone->mWeights = new aiVertexWeight[nbone->mNumWeights];
- for( unsigned int d = 0; d < newWeights.size(); d++)
- nbone->mWeights[d] = newWeights[d];
- }
-
- // store the bones in the mesh
- mesh->mNumBones = (unsigned int)newBones.size();
- if( newBones.size() > 0)
- {
- mesh->mBones = new aiBone*[mesh->mNumBones];
- std::copy( newBones.begin(), newBones.end(), mesh->mBones);
- }
- }
- }
-
- // reallocate scene mesh array to be large enough
- aiMesh** prevArray = pScene->mMeshes;
- pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()];
- if( prevArray)
- {
- memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*));
- delete [] prevArray;
- }
-
- // allocate mesh index array in the node
- pNode->mNumMeshes = (unsigned int)meshes.size();
- pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
-
- // store all meshes in the mesh library of the scene and store their indices in the node
- for( unsigned int a = 0; a < meshes.size(); a++)
- {
- pScene->mMeshes[pScene->mNumMeshes] = meshes[a];
- pNode->mMeshes[a] = pScene->mNumMeshes;
- pScene->mNumMeshes++;
- }
+ } else
+ {
+ mesh->mMaterialIndex = 0;
+ }
+
+ // Create properly sized data arrays in the mesh. We store unique vertices per face,
+ // as specified
+ mesh->mNumVertices = numVertices;
+ mesh->mVertices = new aiVector3D[numVertices];
+ mesh->mNumFaces = (unsigned int)faces.size();
+ mesh->mFaces = new aiFace[mesh->mNumFaces];
+
+ // name
+ mesh->mName.Set(sourceMesh->mName);
+
+ // normals?
+ if( sourceMesh->mNormals.size() > 0)
+ mesh->mNormals = new aiVector3D[numVertices];
+ // texture coords
+ for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; c++)
+ {
+ if( sourceMesh->mTexCoords[c].size() > 0)
+ mesh->mTextureCoords[c] = new aiVector3D[numVertices];
+ }
+ // vertex colors
+ for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; c++)
+ {
+ if( sourceMesh->mColors[c].size() > 0)
+ mesh->mColors[c] = new aiColor4D[numVertices];
+ }
+
+ // now collect the vertex data of all data streams present in the imported mesh
+ unsigned int newIndex = 0;
+ std::vector<unsigned int> orgPoints; // from which original point each new vertex stems
+ orgPoints.resize( numVertices, 0);
+
+ for( unsigned int c = 0; c < faces.size(); c++)
+ {
+ unsigned int f = faces[c]; // index of the source face
+ const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face
+
+ // create face. either triangle or triangle fan depending on the index count
+ aiFace& df = mesh->mFaces[c]; // destination face
+ df.mNumIndices = (unsigned int)pf.mIndices.size();
+ df.mIndices = new unsigned int[ df.mNumIndices];
+
+ // collect vertex data for indices of this face
+ for( unsigned int d = 0; d < df.mNumIndices; d++)
+ {
+ df.mIndices[d] = newIndex;
+ orgPoints[newIndex] = pf.mIndices[d];
+
+ // Position
+ mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]];
+ // Normal, if present
+ if( mesh->HasNormals())
+ mesh->mNormals[newIndex] = sourceMesh->mNormals[sourceMesh->mNormFaces[f].mIndices[d]];
+
+ // texture coord sets
+ for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++)
+ {
+ if( mesh->HasTextureCoords( e))
+ {
+ aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]];
+ mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f);
+ }
+ }
+ // vertex color sets
+ for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; e++)
+ if( mesh->HasVertexColors( e))
+ mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]];
+
+ newIndex++;
+ }
+ }
+
+ // there should be as much new vertices as we calculated before
+ ai_assert( newIndex == numVertices);
+
+ // convert all bones of the source mesh which influence vertices in this newly created mesh
+ const std::vector<XFile::Bone>& bones = sourceMesh->mBones;
+ std::vector<aiBone*> newBones;
+ for( unsigned int c = 0; c < bones.size(); c++)
+ {
+ const XFile::Bone& obone = bones[c];
+ // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex
+ std::vector<float> oldWeights( sourceMesh->mPositions.size(), 0.0f);
+ for( unsigned int d = 0; d < obone.mWeights.size(); d++)
+ oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight;
+
+ // collect all vertex weights that influence a vertex in the new mesh
+ std::vector<aiVertexWeight> newWeights;
+ newWeights.reserve( numVertices);
+ for( unsigned int d = 0; d < orgPoints.size(); d++)
+ {
+ // does the new vertex stem from an old vertex which was influenced by this bone?
+ float w = oldWeights[orgPoints[d]];
+ if( w > 0.0f)
+ newWeights.push_back( aiVertexWeight( d, w));
+ }
+
+ // if the bone has no weights in the newly created mesh, ignore it
+ if( newWeights.size() == 0)
+ continue;
+
+ // create
+ aiBone* nbone = new aiBone;
+ newBones.push_back( nbone);
+ // copy name and matrix
+ nbone->mName.Set( obone.mName);
+ nbone->mOffsetMatrix = obone.mOffsetMatrix;
+ nbone->mNumWeights = (unsigned int)newWeights.size();
+ nbone->mWeights = new aiVertexWeight[nbone->mNumWeights];
+ for( unsigned int d = 0; d < newWeights.size(); d++)
+ nbone->mWeights[d] = newWeights[d];
+ }
+
+ // store the bones in the mesh
+ mesh->mNumBones = (unsigned int)newBones.size();
+ if( newBones.size() > 0)
+ {
+ mesh->mBones = new aiBone*[mesh->mNumBones];
+ std::copy( newBones.begin(), newBones.end(), mesh->mBones);
+ }
+ }
+ }
+
+ // reallocate scene mesh array to be large enough
+ aiMesh** prevArray = pScene->mMeshes;
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()];
+ if( prevArray)
+ {
+ memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*));
+ delete [] prevArray;
+ }
+
+ // allocate mesh index array in the node
+ pNode->mNumMeshes = (unsigned int)meshes.size();
+ pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+
+ // store all meshes in the mesh library of the scene and store their indices in the node
+ for( unsigned int a = 0; a < meshes.size(); a++)
+ {
+ pScene->mMeshes[pScene->mNumMeshes] = meshes[a];
+ pNode->mMeshes[a] = pScene->mNumMeshes;
+ pScene->mNumMeshes++;
+ }
}
// ------------------------------------------------------------------------------------------------
// Converts the animations from the given imported data and creates them in the scene.
void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData)
{
- std::vector<aiAnimation*> newAnims;
-
- for( unsigned int a = 0; a < pData->mAnims.size(); a++)
- {
- const XFile::Animation* anim = pData->mAnims[a];
- // some exporters mock me with empty animation tags.
- if( anim->mAnims.size() == 0)
- continue;
-
- // create a new animation to hold the data
- aiAnimation* nanim = new aiAnimation;
- newAnims.push_back( nanim);
- nanim->mName.Set( anim->mName);
- // duration will be determined by the maximum length
- nanim->mDuration = 0;
- nanim->mTicksPerSecond = pData->mAnimTicksPerSecond;
- nanim->mNumChannels = (unsigned int)anim->mAnims.size();
- nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels];
-
- for( unsigned int b = 0; b < anim->mAnims.size(); b++)
- {
- const XFile::AnimBone* bone = anim->mAnims[b];
- aiNodeAnim* nbone = new aiNodeAnim;
- nbone->mNodeName.Set( bone->mBoneName);
- nanim->mChannels[b] = nbone;
-
- // keyframes are given as combined transformation matrix keys
- if( bone->mTrafoKeys.size() > 0)
- {
- nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();
- nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
- nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size();
- nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
- nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size();
- nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
-
- for( unsigned int c = 0; c < bone->mTrafoKeys.size(); c++)
- {
- // deconstruct each matrix into separate position, rotation and scaling
- double time = bone->mTrafoKeys[c].mTime;
- aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix;
-
- // extract position
- aiVector3D pos( trafo.a4, trafo.b4, trafo.c4);
-
- nbone->mPositionKeys[c].mTime = time;
- nbone->mPositionKeys[c].mValue = pos;
-
- // extract scaling
- aiVector3D scale;
- scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length();
- scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length();
- scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length();
- nbone->mScalingKeys[c].mTime = time;
- nbone->mScalingKeys[c].mValue = scale;
-
- // reconstruct rotation matrix without scaling
- aiMatrix3x3 rotmat(
- trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z,
- trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
- trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
-
- // and convert it into a quaternion
- nbone->mRotationKeys[c].mTime = time;
- nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
- }
-
- // longest lasting key sequence determines duration
- nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime);
- } else
- {
- // separate key sequences for position, rotation, scaling
- nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size();
- nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
- for( unsigned int c = 0; c < nbone->mNumPositionKeys; c++)
- {
- aiVector3D pos = bone->mPosKeys[c].mValue;
-
- nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime;
- nbone->mPositionKeys[c].mValue = pos;
- }
-
- // rotation
- nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size();
- nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
- for( unsigned int c = 0; c < nbone->mNumRotationKeys; c++)
- {
- aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix();
-
- nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime;
- nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
- nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion
- }
-
- // scaling
- nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size();
- nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
- for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++)
- nbone->mScalingKeys[c] = bone->mScaleKeys[c];
-
- // longest lasting key sequence determines duration
- if( bone->mPosKeys.size() > 0)
- nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime);
- if( bone->mRotKeys.size() > 0)
- nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime);
- if( bone->mScaleKeys.size() > 0)
- nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime);
- }
- }
- }
-
- // store all converted animations in the scene
- if( newAnims.size() > 0)
- {
- pScene->mNumAnimations = (unsigned int)newAnims.size();
- pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations];
- for( unsigned int a = 0; a < newAnims.size(); a++)
- pScene->mAnimations[a] = newAnims[a];
- }
+ std::vector<aiAnimation*> newAnims;
+
+ for( unsigned int a = 0; a < pData->mAnims.size(); a++)
+ {
+ const XFile::Animation* anim = pData->mAnims[a];
+ // some exporters mock me with empty animation tags.
+ if( anim->mAnims.size() == 0)
+ continue;
+
+ // create a new animation to hold the data
+ aiAnimation* nanim = new aiAnimation;
+ newAnims.push_back( nanim);
+ nanim->mName.Set( anim->mName);
+ // duration will be determined by the maximum length
+ nanim->mDuration = 0;
+ nanim->mTicksPerSecond = pData->mAnimTicksPerSecond;
+ nanim->mNumChannels = (unsigned int)anim->mAnims.size();
+ nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels];
+
+ for( unsigned int b = 0; b < anim->mAnims.size(); b++)
+ {
+ const XFile::AnimBone* bone = anim->mAnims[b];
+ aiNodeAnim* nbone = new aiNodeAnim;
+ nbone->mNodeName.Set( bone->mBoneName);
+ nanim->mChannels[b] = nbone;
+
+ // keyframes are given as combined transformation matrix keys
+ if( bone->mTrafoKeys.size() > 0)
+ {
+ nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();
+ nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
+ nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size();
+ nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
+ nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size();
+ nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
+
+ for( unsigned int c = 0; c < bone->mTrafoKeys.size(); c++)
+ {
+ // deconstruct each matrix into separate position, rotation and scaling
+ double time = bone->mTrafoKeys[c].mTime;
+ aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix;
+
+ // extract position
+ aiVector3D pos( trafo.a4, trafo.b4, trafo.c4);
+
+ nbone->mPositionKeys[c].mTime = time;
+ nbone->mPositionKeys[c].mValue = pos;
+
+ // extract scaling
+ aiVector3D scale;
+ scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length();
+ scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length();
+ scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length();
+ nbone->mScalingKeys[c].mTime = time;
+ nbone->mScalingKeys[c].mValue = scale;
+
+ // reconstruct rotation matrix without scaling
+ aiMatrix3x3 rotmat(
+ trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z,
+ trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
+ trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
+
+ // and convert it into a quaternion
+ nbone->mRotationKeys[c].mTime = time;
+ nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
+ }
+
+ // longest lasting key sequence determines duration
+ nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime);
+ } else
+ {
+ // separate key sequences for position, rotation, scaling
+ nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size();
+ nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
+ for( unsigned int c = 0; c < nbone->mNumPositionKeys; c++)
+ {
+ aiVector3D pos = bone->mPosKeys[c].mValue;
+
+ nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime;
+ nbone->mPositionKeys[c].mValue = pos;
+ }
+
+ // rotation
+ nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size();
+ nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
+ for( unsigned int c = 0; c < nbone->mNumRotationKeys; c++)
+ {
+ aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix();
+
+ nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime;
+ nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
+ nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion
+ }
+
+ // scaling
+ nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size();
+ nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
+ for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++)
+ nbone->mScalingKeys[c] = bone->mScaleKeys[c];
+
+ // longest lasting key sequence determines duration
+ if( bone->mPosKeys.size() > 0)
+ nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime);
+ if( bone->mRotKeys.size() > 0)
+ nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime);
+ if( bone->mScaleKeys.size() > 0)
+ nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime);
+ }
+ }
+ }
+
+ // store all converted animations in the scene
+ if( newAnims.size() > 0)
+ {
+ pScene->mNumAnimations = (unsigned int)newAnims.size();
+ pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations];
+ for( unsigned int a = 0; a < newAnims.size(); a++)
+ pScene->mAnimations[a] = newAnims[a];
+ }
}
// ------------------------------------------------------------------------------------------------
// Converts all materials in the given array and stores them in the scene's material list.
void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials)
{
- // count the non-referrer materials in the array
- unsigned int numNewMaterials = 0;
- for( unsigned int a = 0; a < pMaterials.size(); a++)
- if( !pMaterials[a].mIsReference)
- numNewMaterials++;
+ // count the non-referrer materials in the array
+ unsigned int numNewMaterials = 0;
+ for( unsigned int a = 0; a < pMaterials.size(); a++)
+ if( !pMaterials[a].mIsReference)
+ numNewMaterials++;
- // resize the scene's material list to offer enough space for the new materials
+ // resize the scene's material list to offer enough space for the new materials
if( numNewMaterials > 0 )
{
- aiMaterial** prevMats = pScene->mMaterials;
- pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials];
- if( prevMats)
- {
- memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
- delete [] prevMats;
- }
+ aiMaterial** prevMats = pScene->mMaterials;
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials];
+ if( prevMats)
+ {
+ memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
+ delete [] prevMats;
+ }
}
- // convert all the materials given in the array
- for( unsigned int a = 0; a < pMaterials.size(); a++)
- {
- XFile::Material& oldMat = pMaterials[a];
- if( oldMat.mIsReference)
+ // convert all the materials given in the array
+ for( unsigned int a = 0; a < pMaterials.size(); a++)
+ {
+ XFile::Material& oldMat = pMaterials[a];
+ if( oldMat.mIsReference)
{
// find the material it refers to by name, and store its index
for( size_t a = 0; a < pScene->mNumMaterials; ++a )
@@ -586,113 +603,113 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
if( oldMat.sceneIndex == SIZE_MAX )
{
- DefaultLogger::get()->warn( boost::str( boost::format( "Could not resolve global material reference \"%s\"") % oldMat.mName));
+ DefaultLogger::get()->warn( format() << "Could not resolve global material reference \"" << oldMat.mName << "\"" );
oldMat.sceneIndex = 0;
}
continue;
}
- aiMaterial* mat = new aiMaterial;
- aiString name;
- name.Set( oldMat.mName);
- mat->AddProperty( &name, AI_MATKEY_NAME);
+ aiMaterial* mat = new aiMaterial;
+ aiString name;
+ name.Set( oldMat.mName);
+ mat->AddProperty( &name, AI_MATKEY_NAME);
- // Shading model: hardcoded to PHONG, there is no such information in an XFile
- // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
- // for some models in the SDK (e.g. good old tiny.x)
- int shadeMode = (int)oldMat.mSpecularExponent == 0.0f
- ? aiShadingMode_Gouraud : aiShadingMode_Phong;
+ // Shading model: hardcoded to PHONG, there is no such information in an XFile
+ // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
+ // for some models in the SDK (e.g. good old tiny.x)
+ int shadeMode = (int)oldMat.mSpecularExponent == 0.0f
+ ? aiShadingMode_Gouraud : aiShadingMode_Phong;
- mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
- // material colours
+ mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+ // material colours
// Unclear: there's no ambient colour, but emissive. What to put for ambient?
// Probably nothing at all, let the user select a suitable default.
- mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
- mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
- mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
- mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
-
-
- // texture, if there is one
- if (1 == oldMat.mTextures.size())
- {
- const XFile::TexEntry& otex = oldMat.mTextures.back();
- if (otex.mName.length())
- {
- // if there is only one texture assume it contains the diffuse color
- aiString tex( otex.mName);
- if( otex.mIsNormalMap)
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(0));
- else
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- }
- else
- {
- // Otherwise ... try to search for typical strings in the
- // texture's file name like 'bump' or 'diffuse'
- unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
- for( unsigned int b = 0; b < oldMat.mTextures.size(); b++)
- {
- const XFile::TexEntry& otex = oldMat.mTextures[b];
- std::string sz = otex.mName;
- if (!sz.length())continue;
-
-
- // find the file name
- //const size_t iLen = sz.length();
- std::string::size_type s = sz.find_last_of("\\/");
- if (std::string::npos == s)
- s = 0;
-
- // cut off the file extension
- std::string::size_type sExt = sz.find_last_of('.');
- if (std::string::npos != sExt){
- sz[sExt] = '\0';
- }
-
- // convert to lower case for easier comparision
- for( unsigned int c = 0; c < sz.length(); c++)
- if( isalpha( sz[c]))
- sz[c] = tolower( sz[c]);
-
-
- // Place texture filename property under the corresponding name
- aiString tex( oldMat.mTextures[b].mName);
-
- // bump map
- if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s))
- {
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
- } else
- if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s))
- {
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
- } else
- if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s))
- {
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
- } else
- if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s))
- {
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
- } else
- if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s))
- {
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
- } else
- {
- // Assume it is a diffuse texture
- mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
- }
- }
- }
-
- pScene->mMaterials[pScene->mNumMaterials] = mat;
- oldMat.sceneIndex = pScene->mNumMaterials;
- pScene->mNumMaterials++;
- }
+ mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+ mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+ mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+ mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+
+
+ // texture, if there is one
+ if (1 == oldMat.mTextures.size())
+ {
+ const XFile::TexEntry& otex = oldMat.mTextures.back();
+ if (otex.mName.length())
+ {
+ // if there is only one texture assume it contains the diffuse color
+ aiString tex( otex.mName);
+ if( otex.mIsNormalMap)
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(0));
+ else
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
+ }
+ }
+ else
+ {
+ // Otherwise ... try to search for typical strings in the
+ // texture's file name like 'bump' or 'diffuse'
+ unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
+ for( unsigned int b = 0; b < oldMat.mTextures.size(); b++)
+ {
+ const XFile::TexEntry& otex = oldMat.mTextures[b];
+ std::string sz = otex.mName;
+ if (!sz.length())continue;
+
+
+ // find the file name
+ //const size_t iLen = sz.length();
+ std::string::size_type s = sz.find_last_of("\\/");
+ if (std::string::npos == s)
+ s = 0;
+
+ // cut off the file extension
+ std::string::size_type sExt = sz.find_last_of('.');
+ if (std::string::npos != sExt){
+ sz[sExt] = '\0';
+ }
+
+ // convert to lower case for easier comparison
+ for( unsigned int c = 0; c < sz.length(); c++)
+ if( isalpha( sz[c]))
+ sz[c] = tolower( sz[c]);
+
+
+ // Place texture filename property under the corresponding name
+ aiString tex( oldMat.mTextures[b].mName);
+
+ // bump map
+ if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s))
+ {
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
+ } else
+ if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s))
+ {
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
+ } else
+ if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s))
+ {
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
+ } else
+ if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s))
+ {
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
+ } else
+ if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s))
+ {
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
+ } else
+ {
+ // Assume it is a diffuse texture
+ mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
+ }
+ }
+ }
+
+ pScene->mMaterials[pScene->mNumMaterials] = mat;
+ oldMat.sceneIndex = pScene->mNumMaterials;
+ pScene->mNumMaterials++;
+ }
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
diff --git a/src/3rdparty/assimp/code/XFileImporter.h b/src/3rdparty/assimp/code/XFileImporter.h
index 39f3d827a..1de56cbc5 100644
--- a/src/3rdparty/assimp/code/XFileImporter.h
+++ b/src/3rdparty/assimp/code/XFileImporter.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,23 +23,23 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file XFileImporter.h
- * @brief Definition of the XFile importer class.
+/** @file XFileImporter.h
+ * @brief Definition of the XFile importer class.
*/
#ifndef AI_XFILEIMPORTER_H_INC
#define AI_XFILEIMPORTER_H_INC
@@ -49,11 +49,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XFileHelper.h"
#include "BaseImporter.h"
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
struct aiNode;
-namespace Assimp {
+namespace Assimp {
namespace XFile {
struct Scene;
@@ -67,82 +67,82 @@ struct Node;
class XFileImporter : public BaseImporter
{
public:
- XFileImporter();
- ~XFileImporter();
+ XFileImporter();
+ ~XFileImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool CheckSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool CheckSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details
- */
- const aiImporterDesc* GetInfo () const;
-
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details
- */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
-
- // -------------------------------------------------------------------
- /** Constructs the return data structure out of the imported data.
- * @param pScene The scene to construct the return data in.
- * @param pData The imported data in the internal temporary
- * representation.
- */
- void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData);
-
- // -------------------------------------------------------------------
- /** Recursively creates scene nodes from the imported hierarchy.
- * The meshes and materials of the nodes will be extracted on the way.
- * @param pScene The scene to construct the return data in.
- * @param pParent The parent node where to create new child nodes
- * @param pNode The temporary node to copy.
- * @return The created node
- */
- aiNode* CreateNodes( aiScene* pScene, aiNode* pParent,
- const XFile::Node* pNode);
-
- // -------------------------------------------------------------------
- /** Converts all meshes in the given mesh array. Each mesh is split
- * up per material, the indices of the generated meshes are stored in
- * the node structure.
- * @param pScene The scene to construct the return data in.
- * @param pNode The target node structure that references the
- * constructed meshes.
- * @param pMeshes The array of meshes to convert
- */
- void CreateMeshes( aiScene* pScene, aiNode* pNode,
- const std::vector<XFile::Mesh*>& pMeshes);
-
- // -------------------------------------------------------------------
- /** Converts the animations from the given imported data and creates
- * them in the scene.
- * @param pScene The scene to hold to converted animations
- * @param pData The data to read the animations from
- */
- void CreateAnimations( aiScene* pScene, const XFile::Scene* pData);
-
- // -------------------------------------------------------------------
- /** Converts all materials in the given array and stores them in the
- * scene's material list.
- * @param pScene The scene to hold the converted materials.
- * @param pMaterials The material array to convert.
- */
- void ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials);
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details
+ */
+ const aiImporterDesc* GetInfo () const;
+
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details
+ */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
+
+ // -------------------------------------------------------------------
+ /** Constructs the return data structure out of the imported data.
+ * @param pScene The scene to construct the return data in.
+ * @param pData The imported data in the internal temporary
+ * representation.
+ */
+ void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData);
+
+ // -------------------------------------------------------------------
+ /** Recursively creates scene nodes from the imported hierarchy.
+ * The meshes and materials of the nodes will be extracted on the way.
+ * @param pScene The scene to construct the return data in.
+ * @param pParent The parent node where to create new child nodes
+ * @param pNode The temporary node to copy.
+ * @return The created node
+ */
+ aiNode* CreateNodes( aiScene* pScene, aiNode* pParent,
+ const XFile::Node* pNode);
+
+ // -------------------------------------------------------------------
+ /** Converts all meshes in the given mesh array. Each mesh is split
+ * up per material, the indices of the generated meshes are stored in
+ * the node structure.
+ * @param pScene The scene to construct the return data in.
+ * @param pNode The target node structure that references the
+ * constructed meshes.
+ * @param pMeshes The array of meshes to convert
+ */
+ void CreateMeshes( aiScene* pScene, aiNode* pNode,
+ const std::vector<XFile::Mesh*>& pMeshes);
+
+ // -------------------------------------------------------------------
+ /** Converts the animations from the given imported data and creates
+ * them in the scene.
+ * @param pScene The scene to hold to converted animations
+ * @param pData The data to read the animations from
+ */
+ void CreateAnimations( aiScene* pScene, const XFile::Scene* pData);
+
+ // -------------------------------------------------------------------
+ /** Converts all materials in the given array and stores them in the
+ * scene's material list.
+ * @param pScene The scene to hold the converted materials.
+ * @param pMaterials The material array to convert.
+ */
+ void ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials);
protected:
- /** Buffer to hold the loaded file */
- std::vector<char> mBuffer;
+ /** Buffer to hold the loaded file */
+ std::vector<char> mBuffer;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/XFileParser.cpp b/src/3rdparty/assimp/code/XFileParser.cpp
index a89b12d95..a820955a8 100644
--- a/src/3rdparty/assimp/code/XFileParser.cpp
+++ b/src/3rdparty/assimp/code/XFileParser.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,39 +25,46 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the XFile parser helper class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_X_IMPORTER
#include "XFileParser.h"
#include "XFileHelper.h"
#include "fast_atof.h"
+#include "Exceptional.h"
+#include "TinyFormatter.h"
+#include "ByteSwapper.h"
+#include "StringUtils.h"
+#include <assimp/DefaultLogger.hpp>
+
using namespace Assimp;
using namespace Assimp::XFile;
+using namespace Assimp::Formatter;
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X
-# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
-# else
-# include "../contrib/zlib/zlib.h"
-# endif
+# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+# else
+# include "../contrib/zlib/zlib.h"
+# endif
// Magic identifier for MSZIP compressed data
#define MSZIP_MAGIC 0x4B43
@@ -65,950 +72,954 @@ using namespace Assimp::XFile;
// ------------------------------------------------------------------------------------------------
// Dummy memory wrappers for use with zlib
-static void* dummy_alloc (void* /*opaque*/, unsigned int items, unsigned int size) {
- return ::operator new(items*size);
+static void* dummy_alloc (void* /*opaque*/, unsigned int items, unsigned int size) {
+ return ::operator new(items*size);
}
-static void dummy_free (void* /*opaque*/, void* address) {
- return ::operator delete(address);
+static void dummy_free (void* /*opaque*/, void* address) {
+ return ::operator delete(address);
}
#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
// ------------------------------------------------------------------------------------------------
-// Constructor. Creates a data structure out of the XFile given in the memory block.
+// Constructor. Creates a data structure out of the XFile given in the memory block.
XFileParser::XFileParser( const std::vector<char>& pBuffer)
{
- mMajorVersion = mMinorVersion = 0;
- mIsBinaryFormat = false;
- mBinaryNumCount = 0;
- P = End = NULL;
- mLineNumber = 0;
- mScene = NULL;
-
- // vector to store uncompressed file for INFLATE'd X files
- std::vector<char> uncompressed;
-
- // set up memory pointers
- P = &pBuffer.front();
- End = P + pBuffer.size() - 1;
-
- // check header
- if( strncmp( P, "xof ", 4) != 0)
- throw DeadlyImportError( "Header mismatch, file is not an XFile.");
-
- // read version. It comes in a four byte format such as "0302"
- mMajorVersion = (unsigned int)(P[4] - 48) * 10 + (unsigned int)(P[5] - 48);
- mMinorVersion = (unsigned int)(P[6] - 48) * 10 + (unsigned int)(P[7] - 48);
-
- bool compressed = false;
-
- // txt - pure ASCII text format
- if( strncmp( P + 8, "txt ", 4) == 0)
- mIsBinaryFormat = false;
-
- // bin - Binary format
- else if( strncmp( P + 8, "bin ", 4) == 0)
- mIsBinaryFormat = true;
-
- // tzip - Inflate compressed text format
- else if( strncmp( P + 8, "tzip", 4) == 0)
- {
- mIsBinaryFormat = false;
- compressed = true;
- }
- // bzip - Inflate compressed binary format
- else if( strncmp( P + 8, "bzip", 4) == 0)
- {
- mIsBinaryFormat = true;
- compressed = true;
- }
- else ThrowException( boost::str(boost::format("Unsupported xfile format '%c%c%c%c'")
- % P[8] % P[9] % P[10] % P[11]));
-
- // float size
- mBinaryFloatSize = (unsigned int)(P[12] - 48) * 1000
- + (unsigned int)(P[13] - 48) * 100
- + (unsigned int)(P[14] - 48) * 10
- + (unsigned int)(P[15] - 48);
-
- if( mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
- ThrowException( boost::str( boost::format( "Unknown float size %1% specified in xfile header.")
- % mBinaryFloatSize));
-
- // The x format specifies size in bits, but we work in bytes
- mBinaryFloatSize /= 8;
-
- P += 16;
-
- // If this is a compressed X file, apply the inflate algorithm to it
- if (compressed)
- {
+ mMajorVersion = mMinorVersion = 0;
+ mIsBinaryFormat = false;
+ mBinaryNumCount = 0;
+ P = End = NULL;
+ mLineNumber = 0;
+ mScene = NULL;
+
+ // vector to store uncompressed file for INFLATE'd X files
+ std::vector<char> uncompressed;
+
+ // set up memory pointers
+ P = &pBuffer.front();
+ End = P + pBuffer.size() - 1;
+
+ // check header
+ if( strncmp( P, "xof ", 4) != 0)
+ throw DeadlyImportError( "Header mismatch, file is not an XFile.");
+
+ // read version. It comes in a four byte format such as "0302"
+ mMajorVersion = (unsigned int)(P[4] - 48) * 10 + (unsigned int)(P[5] - 48);
+ mMinorVersion = (unsigned int)(P[6] - 48) * 10 + (unsigned int)(P[7] - 48);
+
+ bool compressed = false;
+
+ // txt - pure ASCII text format
+ if( strncmp( P + 8, "txt ", 4) == 0)
+ mIsBinaryFormat = false;
+
+ // bin - Binary format
+ else if( strncmp( P + 8, "bin ", 4) == 0)
+ mIsBinaryFormat = true;
+
+ // tzip - Inflate compressed text format
+ else if( strncmp( P + 8, "tzip", 4) == 0)
+ {
+ mIsBinaryFormat = false;
+ compressed = true;
+ }
+ // bzip - Inflate compressed binary format
+ else if( strncmp( P + 8, "bzip", 4) == 0)
+ {
+ mIsBinaryFormat = true;
+ compressed = true;
+ }
+ else ThrowException( format() << "Unsupported xfile format '" <<
+ P[8] << P[9] << P[10] << P[11] << "'");
+
+ // float size
+ mBinaryFloatSize = (unsigned int)(P[12] - 48) * 1000
+ + (unsigned int)(P[13] - 48) * 100
+ + (unsigned int)(P[14] - 48) * 10
+ + (unsigned int)(P[15] - 48);
+
+ if( mBinaryFloatSize != 32 && mBinaryFloatSize != 64)
+ ThrowException( format() << "Unknown float size " << mBinaryFloatSize << " specified in xfile header." );
+
+ // The x format specifies size in bits, but we work in bytes
+ mBinaryFloatSize /= 8;
+
+ P += 16;
+
+ // If this is a compressed X file, apply the inflate algorithm to it
+ if (compressed)
+ {
#ifdef ASSIMP_BUILD_NO_COMPRESSED_X
- throw DeadlyImportError("Assimp was built without compressed X support");
+ throw DeadlyImportError("Assimp was built without compressed X support");
#else
- /* ///////////////////////////////////////////////////////////////////////
- * COMPRESSED X FILE FORMAT
- * ///////////////////////////////////////////////////////////////////////
- * [xhead]
- * 2 major
- * 2 minor
- * 4 type // bzip,tzip
- * [mszip_master_head]
- * 4 unkn // checksum?
- * 2 unkn // flags? (seems to be constant)
- * [mszip_head]
- * 2 ofs // offset to next section
- * 2 magic // 'CK'
- * ... ofs bytes of data
- * ... next mszip_head
- *
- * http://www.kdedevelopers.org/node/3181 has been very helpful.
- * ///////////////////////////////////////////////////////////////////////
- */
-
- // build a zlib stream
- z_stream stream;
- stream.opaque = NULL;
- stream.zalloc = &dummy_alloc;
- stream.zfree = &dummy_free;
- stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII);
-
- // initialize the inflation algorithm
- ::inflateInit2(&stream, -MAX_WBITS);
-
- // skip unknown data (checksum, flags?)
- P += 6;
-
- // First find out how much storage we'll need. Count sections.
- const char* P1 = P;
- unsigned int est_out = 0;
-
- while (P1 + 3 < End)
- {
- // read next offset
- uint16_t ofs = *((uint16_t*)P1);
- AI_SWAP2(ofs); P1 += 2;
-
- if (ofs >= MSZIP_BLOCK)
- throw DeadlyImportError("X: Invalid offset to next MSZIP compressed block");
-
- // check magic word
- uint16_t magic = *((uint16_t*)P1);
- AI_SWAP2(magic); P1 += 2;
-
- if (magic != MSZIP_MAGIC)
- throw DeadlyImportError("X: Unsupported compressed format, expected MSZIP header");
-
- // and advance to the next offset
- P1 += ofs;
- est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
- }
-
- // Allocate storage and terminating zero and do the actual uncompressing
- uncompressed.resize(est_out + 1);
- char* out = &uncompressed.front();
- while (P + 3 < End)
- {
- uint16_t ofs = *((uint16_t*)P);
- AI_SWAP2(ofs);
- P += 4;
-
- // push data to the stream
- stream.next_in = (Bytef*)P;
- stream.avail_in = ofs;
- stream.next_out = (Bytef*)out;
- stream.avail_out = MSZIP_BLOCK;
-
- // and decompress the data ....
- int ret = ::inflate( &stream, Z_SYNC_FLUSH );
- if (ret != Z_OK && ret != Z_STREAM_END)
- throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
-
- ::inflateReset( &stream );
- ::inflateSetDictionary( &stream, (const Bytef*)out , MSZIP_BLOCK - stream.avail_out );
-
- // and advance to the next offset
- out += MSZIP_BLOCK - stream.avail_out;
- P += ofs;
- }
-
- // terminate zlib
- ::inflateEnd(&stream);
-
- // ok, update pointers to point to the uncompressed file data
- P = &uncompressed[0];
- End = out;
-
- // FIXME: we don't need the compressed data anymore, could release
- // it already for better memory usage. Consider breaking const-co.
- DefaultLogger::get()->info("Successfully decompressed MSZIP-compressed file");
+ /* ///////////////////////////////////////////////////////////////////////
+ * COMPRESSED X FILE FORMAT
+ * ///////////////////////////////////////////////////////////////////////
+ * [xhead]
+ * 2 major
+ * 2 minor
+ * 4 type // bzip,tzip
+ * [mszip_master_head]
+ * 4 unkn // checksum?
+ * 2 unkn // flags? (seems to be constant)
+ * [mszip_head]
+ * 2 ofs // offset to next section
+ * 2 magic // 'CK'
+ * ... ofs bytes of data
+ * ... next mszip_head
+ *
+ * http://www.kdedevelopers.org/node/3181 has been very helpful.
+ * ///////////////////////////////////////////////////////////////////////
+ */
+
+ // build a zlib stream
+ z_stream stream;
+ stream.opaque = NULL;
+ stream.zalloc = &dummy_alloc;
+ stream.zfree = &dummy_free;
+ stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII);
+
+ // initialize the inflation algorithm
+ ::inflateInit2(&stream, -MAX_WBITS);
+
+ // skip unknown data (checksum, flags?)
+ P += 6;
+
+ // First find out how much storage we'll need. Count sections.
+ const char* P1 = P;
+ unsigned int est_out = 0;
+
+ while (P1 + 3 < End)
+ {
+ // read next offset
+ uint16_t ofs = *((uint16_t*)P1);
+ AI_SWAP2(ofs); P1 += 2;
+
+ if (ofs >= MSZIP_BLOCK)
+ throw DeadlyImportError("X: Invalid offset to next MSZIP compressed block");
+
+ // check magic word
+ uint16_t magic = *((uint16_t*)P1);
+ AI_SWAP2(magic); P1 += 2;
+
+ if (magic != MSZIP_MAGIC)
+ throw DeadlyImportError("X: Unsupported compressed format, expected MSZIP header");
+
+ // and advance to the next offset
+ P1 += ofs;
+ est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
+ }
+
+ // Allocate storage and terminating zero and do the actual uncompressing
+ uncompressed.resize(est_out + 1);
+ char* out = &uncompressed.front();
+ while (P + 3 < End)
+ {
+ uint16_t ofs = *((uint16_t*)P);
+ AI_SWAP2(ofs);
+ P += 4;
+
+ if (P + ofs > End + 2) {
+ throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
+ }
+
+ // push data to the stream
+ stream.next_in = (Bytef*)P;
+ stream.avail_in = ofs;
+ stream.next_out = (Bytef*)out;
+ stream.avail_out = MSZIP_BLOCK;
+
+ // and decompress the data ....
+ int ret = ::inflate( &stream, Z_SYNC_FLUSH );
+ if (ret != Z_OK && ret != Z_STREAM_END)
+ throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
+
+ ::inflateReset( &stream );
+ ::inflateSetDictionary( &stream, (const Bytef*)out , MSZIP_BLOCK - stream.avail_out );
+
+ // and advance to the next offset
+ out += MSZIP_BLOCK - stream.avail_out;
+ P += ofs;
+ }
+
+ // terminate zlib
+ ::inflateEnd(&stream);
+
+ // ok, update pointers to point to the uncompressed file data
+ P = &uncompressed[0];
+ End = out;
+
+ // FIXME: we don't need the compressed data anymore, could release
+ // it already for better memory usage. Consider breaking const-co.
+ DefaultLogger::get()->info("Successfully decompressed MSZIP-compressed file");
#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
- }
- else
- {
- // start reading here
- ReadUntilEndOfLine();
- }
-
- mScene = new Scene;
- ParseFile();
-
- // filter the imported hierarchy for some degenerated cases
- if( mScene->mRootNode) {
- FilterHierarchy( mScene->mRootNode);
- }
+ }
+ else
+ {
+ // start reading here
+ ReadUntilEndOfLine();
+ }
+
+ mScene = new Scene;
+ ParseFile();
+
+ // filter the imported hierarchy for some degenerated cases
+ if( mScene->mRootNode) {
+ FilterHierarchy( mScene->mRootNode);
+ }
}
// ------------------------------------------------------------------------------------------------
-// Destructor. Destroys all imported data along with it
+// Destructor. Destroys all imported data along with it
XFileParser::~XFileParser()
{
- // kill everything we created
- delete mScene;
+ // kill everything we created
+ delete mScene;
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseFile()
{
- bool running = true;
- while( running )
- {
- // read name of next object
- std::string objectName = GetNextToken();
- if (objectName.length() == 0)
- break;
-
- // parse specific object
- if( objectName == "template")
- ParseDataObjectTemplate();
- else
- if( objectName == "Frame")
- ParseDataObjectFrame( NULL);
- else
- if( objectName == "Mesh")
- {
- // some meshes have no frames at all
- Mesh* mesh = new Mesh;
- ParseDataObjectMesh( mesh);
- mScene->mGlobalMeshes.push_back( mesh);
- } else
- if( objectName == "AnimTicksPerSecond")
- ParseDataObjectAnimTicksPerSecond();
- else
- if( objectName == "AnimationSet")
- ParseDataObjectAnimationSet();
- else
- if( objectName == "Material")
- {
- // Material outside of a mesh or node
- Material material;
- ParseDataObjectMaterial( &material);
- mScene->mGlobalMaterials.push_back( material);
- } else
- if( objectName == "}")
- {
- // whatever?
- DefaultLogger::get()->warn("} found in dataObject");
- } else
- {
- // unknown format
- DefaultLogger::get()->warn("Unknown data object in animation of .x file");
- ParseUnknownDataObject();
- }
- }
+ bool running = true;
+ while( running )
+ {
+ // read name of next object
+ std::string objectName = GetNextToken();
+ if (objectName.length() == 0)
+ break;
+
+ // parse specific object
+ if( objectName == "template")
+ ParseDataObjectTemplate();
+ else
+ if( objectName == "Frame")
+ ParseDataObjectFrame( NULL);
+ else
+ if( objectName == "Mesh")
+ {
+ // some meshes have no frames at all
+ Mesh* mesh = new Mesh;
+ ParseDataObjectMesh( mesh);
+ mScene->mGlobalMeshes.push_back( mesh);
+ } else
+ if( objectName == "AnimTicksPerSecond")
+ ParseDataObjectAnimTicksPerSecond();
+ else
+ if( objectName == "AnimationSet")
+ ParseDataObjectAnimationSet();
+ else
+ if( objectName == "Material")
+ {
+ // Material outside of a mesh or node
+ Material material;
+ ParseDataObjectMaterial( &material);
+ mScene->mGlobalMaterials.push_back( material);
+ } else
+ if( objectName == "}")
+ {
+ // whatever?
+ DefaultLogger::get()->warn("} found in dataObject");
+ } else
+ {
+ // unknown format
+ DefaultLogger::get()->warn("Unknown data object in animation of .x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectTemplate()
{
- // parse a template data object. Currently not stored.
- std::string name;
- readHeadOfDataObject( &name);
+ // parse a template data object. Currently not stored.
+ std::string name;
+ readHeadOfDataObject( &name);
- // read GUID
- std::string guid = GetNextToken();
+ // read GUID
+ std::string guid = GetNextToken();
- // read and ignore data members
- bool running = true;
- while ( running )
- {
- std::string s = GetNextToken();
+ // read and ignore data members
+ bool running = true;
+ while ( running )
+ {
+ std::string s = GetNextToken();
- if( s == "}")
- break;
+ if( s == "}")
+ break;
- if( s.length() == 0)
- ThrowException( "Unexpected end of file reached while parsing template definition");
- }
+ if( s.length() == 0)
+ ThrowException( "Unexpected end of file reached while parsing template definition");
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectFrame( Node* pParent)
{
- // A coordinate frame, or "frame of reference." The Frame template
- // is open and can contain any object. The Direct3D extensions (D3DX)
- // mesh-loading functions recognize Mesh, FrameTransformMatrix, and
- // Frame template instances as child objects when loading a Frame
- // instance.
- std::string name;
- readHeadOfDataObject(&name);
-
- // create a named node and place it at its parent, if given
- Node* node = new Node( pParent);
- node->mName = name;
- if( pParent)
- {
- pParent->mChildren.push_back( node);
- } else
- {
- // there might be multiple root nodes
- if( mScene->mRootNode != NULL)
- {
- // place a dummy root if not there
- if( mScene->mRootNode->mName != "$dummy_root")
- {
- Node* exroot = mScene->mRootNode;
- mScene->mRootNode = new Node( NULL);
- mScene->mRootNode->mName = "$dummy_root";
- mScene->mRootNode->mChildren.push_back( exroot);
- exroot->mParent = mScene->mRootNode;
- }
- // put the new node as its child instead
- mScene->mRootNode->mChildren.push_back( node);
- node->mParent = mScene->mRootNode;
- } else
- {
- // it's the first node imported. place it as root
- mScene->mRootNode = node;
- }
- }
-
- // Now inside a frame.
- // read tokens until closing brace is reached.
- bool running = true;
- while ( running )
- {
- std::string objectName = GetNextToken();
- if (objectName.size() == 0)
- ThrowException( "Unexpected end of file reached while parsing frame");
-
- if( objectName == "}")
- break; // frame finished
- else
- if( objectName == "Frame")
- ParseDataObjectFrame( node); // child frame
- else
- if( objectName == "FrameTransformMatrix")
- ParseDataObjectTransformationMatrix( node->mTrafoMatrix);
- else
- if( objectName == "Mesh")
- {
- Mesh* mesh = new Mesh;
- node->mMeshes.push_back( mesh);
- ParseDataObjectMesh( mesh);
- } else
- {
- DefaultLogger::get()->warn("Unknown data object in frame in x file");
- ParseUnknownDataObject();
- }
- }
+ // A coordinate frame, or "frame of reference." The Frame template
+ // is open and can contain any object. The Direct3D extensions (D3DX)
+ // mesh-loading functions recognize Mesh, FrameTransformMatrix, and
+ // Frame template instances as child objects when loading a Frame
+ // instance.
+ std::string name;
+ readHeadOfDataObject(&name);
+
+ // create a named node and place it at its parent, if given
+ Node* node = new Node( pParent);
+ node->mName = name;
+ if( pParent)
+ {
+ pParent->mChildren.push_back( node);
+ } else
+ {
+ // there might be multiple root nodes
+ if( mScene->mRootNode != NULL)
+ {
+ // place a dummy root if not there
+ if( mScene->mRootNode->mName != "$dummy_root")
+ {
+ Node* exroot = mScene->mRootNode;
+ mScene->mRootNode = new Node( NULL);
+ mScene->mRootNode->mName = "$dummy_root";
+ mScene->mRootNode->mChildren.push_back( exroot);
+ exroot->mParent = mScene->mRootNode;
+ }
+ // put the new node as its child instead
+ mScene->mRootNode->mChildren.push_back( node);
+ node->mParent = mScene->mRootNode;
+ } else
+ {
+ // it's the first node imported. place it as root
+ mScene->mRootNode = node;
+ }
+ }
+
+ // Now inside a frame.
+ // read tokens until closing brace is reached.
+ bool running = true;
+ while ( running )
+ {
+ std::string objectName = GetNextToken();
+ if (objectName.size() == 0)
+ ThrowException( "Unexpected end of file reached while parsing frame");
+
+ if( objectName == "}")
+ break; // frame finished
+ else
+ if( objectName == "Frame")
+ ParseDataObjectFrame( node); // child frame
+ else
+ if( objectName == "FrameTransformMatrix")
+ ParseDataObjectTransformationMatrix( node->mTrafoMatrix);
+ else
+ if( objectName == "Mesh")
+ {
+ Mesh* mesh = new Mesh(name);
+ node->mMeshes.push_back( mesh);
+ ParseDataObjectMesh( mesh);
+ } else
+ {
+ DefaultLogger::get()->warn("Unknown data object in frame in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix)
{
- // read header, we're not interested if it has a name
- readHeadOfDataObject();
-
- // read its components
- pMatrix.a1 = ReadFloat(); pMatrix.b1 = ReadFloat();
- pMatrix.c1 = ReadFloat(); pMatrix.d1 = ReadFloat();
- pMatrix.a2 = ReadFloat(); pMatrix.b2 = ReadFloat();
- pMatrix.c2 = ReadFloat(); pMatrix.d2 = ReadFloat();
- pMatrix.a3 = ReadFloat(); pMatrix.b3 = ReadFloat();
- pMatrix.c3 = ReadFloat(); pMatrix.d3 = ReadFloat();
- pMatrix.a4 = ReadFloat(); pMatrix.b4 = ReadFloat();
- pMatrix.c4 = ReadFloat(); pMatrix.d4 = ReadFloat();
-
- // trailing symbols
- CheckForSemicolon();
- CheckForClosingBrace();
+ // read header, we're not interested if it has a name
+ readHeadOfDataObject();
+
+ // read its components
+ pMatrix.a1 = ReadFloat(); pMatrix.b1 = ReadFloat();
+ pMatrix.c1 = ReadFloat(); pMatrix.d1 = ReadFloat();
+ pMatrix.a2 = ReadFloat(); pMatrix.b2 = ReadFloat();
+ pMatrix.c2 = ReadFloat(); pMatrix.d2 = ReadFloat();
+ pMatrix.a3 = ReadFloat(); pMatrix.b3 = ReadFloat();
+ pMatrix.c3 = ReadFloat(); pMatrix.d3 = ReadFloat();
+ pMatrix.a4 = ReadFloat(); pMatrix.b4 = ReadFloat();
+ pMatrix.c4 = ReadFloat(); pMatrix.d4 = ReadFloat();
+
+ // trailing symbols
+ CheckForSemicolon();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMesh( Mesh* pMesh)
{
- std::string name;
- readHeadOfDataObject( &name);
-
- // read vertex count
- unsigned int numVertices = ReadInt();
- pMesh->mPositions.resize( numVertices);
-
- // read vertices
- for( unsigned int a = 0; a < numVertices; a++)
- pMesh->mPositions[a] = ReadVector3();
-
- // read position faces
- unsigned int numPosFaces = ReadInt();
- pMesh->mPosFaces.resize( numPosFaces);
- for( unsigned int a = 0; a < numPosFaces; a++)
- {
- unsigned int numIndices = ReadInt();
- if( numIndices < 3)
- ThrowException( boost::str( boost::format( "Invalid index count %1% for face %2%.") % numIndices % a));
-
- // read indices
- Face& face = pMesh->mPosFaces[a];
- for( unsigned int b = 0; b < numIndices; b++)
- face.mIndices.push_back( ReadInt());
- TestForSeparator();
- }
-
- // here, other data objects may follow
- bool running = true;
- while ( running )
- {
- std::string objectName = GetNextToken();
-
- if( objectName.size() == 0)
- ThrowException( "Unexpected end of file while parsing mesh structure");
- else
- if( objectName == "}")
- break; // mesh finished
- else
- if( objectName == "MeshNormals")
- ParseDataObjectMeshNormals( pMesh);
- else
- if( objectName == "MeshTextureCoords")
- ParseDataObjectMeshTextureCoords( pMesh);
- else
- if( objectName == "MeshVertexColors")
- ParseDataObjectMeshVertexColors( pMesh);
- else
- if( objectName == "MeshMaterialList")
- ParseDataObjectMeshMaterialList( pMesh);
- else
- if( objectName == "VertexDuplicationIndices")
- ParseUnknownDataObject(); // we'll ignore vertex duplication indices
- else
- if( objectName == "XSkinMeshHeader")
- ParseDataObjectSkinMeshHeader( pMesh);
- else
- if( objectName == "SkinWeights")
- ParseDataObjectSkinWeights( pMesh);
- else
- {
- DefaultLogger::get()->warn("Unknown data object in mesh in x file");
- ParseUnknownDataObject();
- }
- }
+ std::string name;
+ readHeadOfDataObject( &name);
+
+ // read vertex count
+ unsigned int numVertices = ReadInt();
+ pMesh->mPositions.resize( numVertices);
+
+ // read vertices
+ for( unsigned int a = 0; a < numVertices; a++)
+ pMesh->mPositions[a] = ReadVector3();
+
+ // read position faces
+ unsigned int numPosFaces = ReadInt();
+ pMesh->mPosFaces.resize( numPosFaces);
+ for( unsigned int a = 0; a < numPosFaces; a++)
+ {
+ unsigned int numIndices = ReadInt();
+ if( numIndices < 3) {
+ ThrowException( format() << "Invalid index count " << numIndices << " for face " << a << "." );
+ }
+
+ // read indices
+ Face& face = pMesh->mPosFaces[a];
+ for( unsigned int b = 0; b < numIndices; b++)
+ face.mIndices.push_back( ReadInt());
+ TestForSeparator();
+ }
+
+ // here, other data objects may follow
+ bool running = true;
+ while ( running )
+ {
+ std::string objectName = GetNextToken();
+
+ if( objectName.size() == 0)
+ ThrowException( "Unexpected end of file while parsing mesh structure");
+ else
+ if( objectName == "}")
+ break; // mesh finished
+ else
+ if( objectName == "MeshNormals")
+ ParseDataObjectMeshNormals( pMesh);
+ else
+ if( objectName == "MeshTextureCoords")
+ ParseDataObjectMeshTextureCoords( pMesh);
+ else
+ if( objectName == "MeshVertexColors")
+ ParseDataObjectMeshVertexColors( pMesh);
+ else
+ if( objectName == "MeshMaterialList")
+ ParseDataObjectMeshMaterialList( pMesh);
+ else
+ if( objectName == "VertexDuplicationIndices")
+ ParseUnknownDataObject(); // we'll ignore vertex duplication indices
+ else
+ if( objectName == "XSkinMeshHeader")
+ ParseDataObjectSkinMeshHeader( pMesh);
+ else
+ if( objectName == "SkinWeights")
+ ParseDataObjectSkinWeights( pMesh);
+ else
+ {
+ DefaultLogger::get()->warn("Unknown data object in mesh in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectSkinWeights( Mesh *pMesh)
{
- readHeadOfDataObject();
-
- std::string transformNodeName;
- GetNextTokenAsString( transformNodeName);
-
- pMesh->mBones.push_back( Bone());
- Bone& bone = pMesh->mBones.back();
- bone.mName = transformNodeName;
-
- // read vertex weights
- unsigned int numWeights = ReadInt();
- bone.mWeights.reserve( numWeights);
-
- for( unsigned int a = 0; a < numWeights; a++)
- {
- BoneWeight weight;
- weight.mVertex = ReadInt();
- bone.mWeights.push_back( weight);
- }
-
- // read vertex weights
- for( unsigned int a = 0; a < numWeights; a++)
- bone.mWeights[a].mWeight = ReadFloat();
-
- // read matrix offset
- bone.mOffsetMatrix.a1 = ReadFloat(); bone.mOffsetMatrix.b1 = ReadFloat();
- bone.mOffsetMatrix.c1 = ReadFloat(); bone.mOffsetMatrix.d1 = ReadFloat();
- bone.mOffsetMatrix.a2 = ReadFloat(); bone.mOffsetMatrix.b2 = ReadFloat();
- bone.mOffsetMatrix.c2 = ReadFloat(); bone.mOffsetMatrix.d2 = ReadFloat();
- bone.mOffsetMatrix.a3 = ReadFloat(); bone.mOffsetMatrix.b3 = ReadFloat();
- bone.mOffsetMatrix.c3 = ReadFloat(); bone.mOffsetMatrix.d3 = ReadFloat();
- bone.mOffsetMatrix.a4 = ReadFloat(); bone.mOffsetMatrix.b4 = ReadFloat();
- bone.mOffsetMatrix.c4 = ReadFloat(); bone.mOffsetMatrix.d4 = ReadFloat();
-
- CheckForSemicolon();
- CheckForClosingBrace();
+ readHeadOfDataObject();
+
+ std::string transformNodeName;
+ GetNextTokenAsString( transformNodeName);
+
+ pMesh->mBones.push_back( Bone());
+ Bone& bone = pMesh->mBones.back();
+ bone.mName = transformNodeName;
+
+ // read vertex weights
+ unsigned int numWeights = ReadInt();
+ bone.mWeights.reserve( numWeights);
+
+ for( unsigned int a = 0; a < numWeights; a++)
+ {
+ BoneWeight weight;
+ weight.mVertex = ReadInt();
+ bone.mWeights.push_back( weight);
+ }
+
+ // read vertex weights
+ for( unsigned int a = 0; a < numWeights; a++)
+ bone.mWeights[a].mWeight = ReadFloat();
+
+ // read matrix offset
+ bone.mOffsetMatrix.a1 = ReadFloat(); bone.mOffsetMatrix.b1 = ReadFloat();
+ bone.mOffsetMatrix.c1 = ReadFloat(); bone.mOffsetMatrix.d1 = ReadFloat();
+ bone.mOffsetMatrix.a2 = ReadFloat(); bone.mOffsetMatrix.b2 = ReadFloat();
+ bone.mOffsetMatrix.c2 = ReadFloat(); bone.mOffsetMatrix.d2 = ReadFloat();
+ bone.mOffsetMatrix.a3 = ReadFloat(); bone.mOffsetMatrix.b3 = ReadFloat();
+ bone.mOffsetMatrix.c3 = ReadFloat(); bone.mOffsetMatrix.d3 = ReadFloat();
+ bone.mOffsetMatrix.a4 = ReadFloat(); bone.mOffsetMatrix.b4 = ReadFloat();
+ bone.mOffsetMatrix.c4 = ReadFloat(); bone.mOffsetMatrix.d4 = ReadFloat();
+
+ CheckForSemicolon();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectSkinMeshHeader( Mesh* /*pMesh*/ )
{
- readHeadOfDataObject();
+ readHeadOfDataObject();
- /*unsigned int maxSkinWeightsPerVertex =*/ ReadInt();
- /*unsigned int maxSkinWeightsPerFace =*/ ReadInt();
- /*unsigned int numBonesInMesh = */ReadInt();
+ /*unsigned int maxSkinWeightsPerVertex =*/ ReadInt();
+ /*unsigned int maxSkinWeightsPerFace =*/ ReadInt();
+ /*unsigned int numBonesInMesh = */ReadInt();
- CheckForClosingBrace();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh)
{
- readHeadOfDataObject();
+ readHeadOfDataObject();
- // read count
- unsigned int numNormals = ReadInt();
- pMesh->mNormals.resize( numNormals);
+ // read count
+ unsigned int numNormals = ReadInt();
+ pMesh->mNormals.resize( numNormals);
- // read normal vectors
- for( unsigned int a = 0; a < numNormals; a++)
- pMesh->mNormals[a] = ReadVector3();
+ // read normal vectors
+ for( unsigned int a = 0; a < numNormals; a++)
+ pMesh->mNormals[a] = ReadVector3();
- // read normal indices
- unsigned int numFaces = ReadInt();
- if( numFaces != pMesh->mPosFaces.size())
- ThrowException( "Normal face count does not match vertex face count.");
+ // read normal indices
+ unsigned int numFaces = ReadInt();
+ if( numFaces != pMesh->mPosFaces.size())
+ ThrowException( "Normal face count does not match vertex face count.");
- for( unsigned int a = 0; a < numFaces; a++)
- {
- unsigned int numIndices = ReadInt();
- pMesh->mNormFaces.push_back( Face());
- Face& face = pMesh->mNormFaces.back();
+ for( unsigned int a = 0; a < numFaces; a++)
+ {
+ unsigned int numIndices = ReadInt();
+ pMesh->mNormFaces.push_back( Face());
+ Face& face = pMesh->mNormFaces.back();
- for( unsigned int b = 0; b < numIndices; b++)
- face.mIndices.push_back( ReadInt());
+ for( unsigned int b = 0; b < numIndices; b++)
+ face.mIndices.push_back( ReadInt());
- TestForSeparator();
- }
+ TestForSeparator();
+ }
- CheckForClosingBrace();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh)
{
- readHeadOfDataObject();
- if( pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS)
- ThrowException( "Too many sets of texture coordinates");
+ readHeadOfDataObject();
+ if( pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS)
+ ThrowException( "Too many sets of texture coordinates");
- std::vector<aiVector2D>& coords = pMesh->mTexCoords[pMesh->mNumTextures++];
+ std::vector<aiVector2D>& coords = pMesh->mTexCoords[pMesh->mNumTextures++];
- unsigned int numCoords = ReadInt();
- if( numCoords != pMesh->mPositions.size())
- ThrowException( "Texture coord count does not match vertex count");
+ unsigned int numCoords = ReadInt();
+ if( numCoords != pMesh->mPositions.size())
+ ThrowException( "Texture coord count does not match vertex count");
- coords.resize( numCoords);
- for( unsigned int a = 0; a < numCoords; a++)
- coords[a] = ReadVector2();
+ coords.resize( numCoords);
+ for( unsigned int a = 0; a < numCoords; a++)
+ coords[a] = ReadVector2();
- CheckForClosingBrace();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh)
{
- readHeadOfDataObject();
- if( pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS)
- ThrowException( "Too many colorsets");
- std::vector<aiColor4D>& colors = pMesh->mColors[pMesh->mNumColorSets++];
-
- unsigned int numColors = ReadInt();
- if( numColors != pMesh->mPositions.size())
- ThrowException( "Vertex color count does not match vertex count");
-
- colors.resize( numColors, aiColor4D( 0, 0, 0, 1));
- for( unsigned int a = 0; a < numColors; a++)
- {
- unsigned int index = ReadInt();
- if( index >= pMesh->mPositions.size())
- ThrowException( "Vertex color index out of bounds");
-
- colors[index] = ReadRGBA();
- // HACK: (thom) Maxon Cinema XPort plugin puts a third separator here, kwxPort puts a comma.
- // Ignore gracefully.
- if( !mIsBinaryFormat)
- {
- FindNextNoneWhiteSpace();
- if( *P == ';' || *P == ',')
- P++;
- }
- }
-
- CheckForClosingBrace();
+ readHeadOfDataObject();
+ if( pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS)
+ ThrowException( "Too many colorsets");
+ std::vector<aiColor4D>& colors = pMesh->mColors[pMesh->mNumColorSets++];
+
+ unsigned int numColors = ReadInt();
+ if( numColors != pMesh->mPositions.size())
+ ThrowException( "Vertex color count does not match vertex count");
+
+ colors.resize( numColors, aiColor4D( 0, 0, 0, 1));
+ for( unsigned int a = 0; a < numColors; a++)
+ {
+ unsigned int index = ReadInt();
+ if( index >= pMesh->mPositions.size())
+ ThrowException( "Vertex color index out of bounds");
+
+ colors[index] = ReadRGBA();
+ // HACK: (thom) Maxon Cinema XPort plugin puts a third separator here, kwxPort puts a comma.
+ // Ignore gracefully.
+ if( !mIsBinaryFormat)
+ {
+ FindNextNoneWhiteSpace();
+ if( *P == ';' || *P == ',')
+ P++;
+ }
+ }
+
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh)
{
- readHeadOfDataObject();
-
- // read material count
- /*unsigned int numMaterials =*/ ReadInt();
- // read non triangulated face material index count
- unsigned int numMatIndices = ReadInt();
-
- // some models have a material index count of 1... to be able to read them we
- // replicate this single material index on every face
- if( numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1)
- ThrowException( "Per-Face material index count does not match face count.");
-
- // read per-face material indices
- for( unsigned int a = 0; a < numMatIndices; a++)
- pMesh->mFaceMaterials.push_back( ReadInt());
-
- // in version 03.02, the face indices end with two semicolons.
- // commented out version check, as version 03.03 exported from blender also has 2 semicolons
- if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
- {
- if(P < End && *P == ';')
- ++P;
- }
-
- // if there was only a single material index, replicate it on all faces
- while( pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size())
- pMesh->mFaceMaterials.push_back( pMesh->mFaceMaterials.front());
-
- // read following data objects
- bool running = true;
- while ( running )
- {
- std::string objectName = GetNextToken();
- if( objectName.size() == 0)
- ThrowException( "Unexpected end of file while parsing mesh material list.");
- else
- if( objectName == "}")
- break; // material list finished
- else
- if( objectName == "{")
- {
- // template materials
- std::string matName = GetNextToken();
- Material material;
- material.mIsReference = true;
- material.mName = matName;
- pMesh->mMaterials.push_back( material);
-
- CheckForClosingBrace(); // skip }
- } else
- if( objectName == "Material")
- {
- pMesh->mMaterials.push_back( Material());
- ParseDataObjectMaterial( &pMesh->mMaterials.back());
- } else
- if( objectName == ";")
- {
- // ignore
- } else
- {
- DefaultLogger::get()->warn("Unknown data object in material list in x file");
- ParseUnknownDataObject();
- }
- }
+ readHeadOfDataObject();
+
+ // read material count
+ /*unsigned int numMaterials =*/ ReadInt();
+ // read non triangulated face material index count
+ unsigned int numMatIndices = ReadInt();
+
+ // some models have a material index count of 1... to be able to read them we
+ // replicate this single material index on every face
+ if( numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1)
+ ThrowException( "Per-Face material index count does not match face count.");
+
+ // read per-face material indices
+ for( unsigned int a = 0; a < numMatIndices; a++)
+ pMesh->mFaceMaterials.push_back( ReadInt());
+
+ // in version 03.02, the face indices end with two semicolons.
+ // commented out version check, as version 03.03 exported from blender also has 2 semicolons
+ if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
+ {
+ if(P < End && *P == ';')
+ ++P;
+ }
+
+ // if there was only a single material index, replicate it on all faces
+ while( pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size())
+ pMesh->mFaceMaterials.push_back( pMesh->mFaceMaterials.front());
+
+ // read following data objects
+ bool running = true;
+ while ( running )
+ {
+ std::string objectName = GetNextToken();
+ if( objectName.size() == 0)
+ ThrowException( "Unexpected end of file while parsing mesh material list.");
+ else
+ if( objectName == "}")
+ break; // material list finished
+ else
+ if( objectName == "{")
+ {
+ // template materials
+ std::string matName = GetNextToken();
+ Material material;
+ material.mIsReference = true;
+ material.mName = matName;
+ pMesh->mMaterials.push_back( material);
+
+ CheckForClosingBrace(); // skip }
+ } else
+ if( objectName == "Material")
+ {
+ pMesh->mMaterials.push_back( Material());
+ ParseDataObjectMaterial( &pMesh->mMaterials.back());
+ } else
+ if( objectName == ";")
+ {
+ // ignore
+ } else
+ {
+ DefaultLogger::get()->warn("Unknown data object in material list in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectMaterial( Material* pMaterial)
{
- std::string matName;
- readHeadOfDataObject( &matName);
- if( matName.empty())
- matName = std::string( "material") + boost::lexical_cast<std::string>( mLineNumber);
- pMaterial->mName = matName;
- pMaterial->mIsReference = false;
-
- // read material values
- pMaterial->mDiffuse = ReadRGBA();
- pMaterial->mSpecularExponent = ReadFloat();
- pMaterial->mSpecular = ReadRGB();
- pMaterial->mEmissive = ReadRGB();
-
- // read other data objects
- bool running = true;
- while ( running )
- {
- std::string objectName = GetNextToken();
- if( objectName.size() == 0)
- ThrowException( "Unexpected end of file while parsing mesh material");
- else
- if( objectName == "}")
- break; // material finished
- else
- if( objectName == "TextureFilename" || objectName == "TextureFileName")
- {
- // some exporters write "TextureFileName" instead.
- std::string texname;
- ParseDataObjectTextureFilename( texname);
- pMaterial->mTextures.push_back( TexEntry( texname));
- } else
- if( objectName == "NormalmapFilename" || objectName == "NormalmapFileName")
- {
- // one exporter writes out the normal map in a separate filename tag
- std::string texname;
- ParseDataObjectTextureFilename( texname);
- pMaterial->mTextures.push_back( TexEntry( texname, true));
- } else
- {
- DefaultLogger::get()->warn("Unknown data object in material in x file");
- ParseUnknownDataObject();
- }
- }
+ std::string matName;
+ readHeadOfDataObject( &matName);
+ if( matName.empty())
+ matName = std::string( "material") + std::to_string( mLineNumber );
+ pMaterial->mName = matName;
+ pMaterial->mIsReference = false;
+
+ // read material values
+ pMaterial->mDiffuse = ReadRGBA();
+ pMaterial->mSpecularExponent = ReadFloat();
+ pMaterial->mSpecular = ReadRGB();
+ pMaterial->mEmissive = ReadRGB();
+
+ // read other data objects
+ bool running = true;
+ while ( running )
+ {
+ std::string objectName = GetNextToken();
+ if( objectName.size() == 0)
+ ThrowException( "Unexpected end of file while parsing mesh material");
+ else
+ if( objectName == "}")
+ break; // material finished
+ else
+ if( objectName == "TextureFilename" || objectName == "TextureFileName")
+ {
+ // some exporters write "TextureFileName" instead.
+ std::string texname;
+ ParseDataObjectTextureFilename( texname);
+ pMaterial->mTextures.push_back( TexEntry( texname));
+ } else
+ if( objectName == "NormalmapFilename" || objectName == "NormalmapFileName")
+ {
+ // one exporter writes out the normal map in a separate filename tag
+ std::string texname;
+ ParseDataObjectTextureFilename( texname);
+ pMaterial->mTextures.push_back( TexEntry( texname, true));
+ } else
+ {
+ DefaultLogger::get()->warn("Unknown data object in material in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectAnimTicksPerSecond()
{
- readHeadOfDataObject();
- mScene->mAnimTicksPerSecond = ReadInt();
- CheckForClosingBrace();
+ readHeadOfDataObject();
+ mScene->mAnimTicksPerSecond = ReadInt();
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectAnimationSet()
{
- std::string animName;
- readHeadOfDataObject( &animName);
-
- Animation* anim = new Animation;
- mScene->mAnims.push_back( anim);
- anim->mName = animName;
-
- bool running = true;
- while ( running )
- {
- std::string objectName = GetNextToken();
- if( objectName.length() == 0)
- ThrowException( "Unexpected end of file while parsing animation set.");
- else
- if( objectName == "}")
- break; // animation set finished
- else
- if( objectName == "Animation")
- ParseDataObjectAnimation( anim);
- else
- {
- DefaultLogger::get()->warn("Unknown data object in animation set in x file");
- ParseUnknownDataObject();
- }
- }
+ std::string animName;
+ readHeadOfDataObject( &animName);
+
+ Animation* anim = new Animation;
+ mScene->mAnims.push_back( anim);
+ anim->mName = animName;
+
+ bool running = true;
+ while ( running )
+ {
+ std::string objectName = GetNextToken();
+ if( objectName.length() == 0)
+ ThrowException( "Unexpected end of file while parsing animation set.");
+ else
+ if( objectName == "}")
+ break; // animation set finished
+ else
+ if( objectName == "Animation")
+ ParseDataObjectAnimation( anim);
+ else
+ {
+ DefaultLogger::get()->warn("Unknown data object in animation set in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectAnimation( Animation* pAnim)
{
- readHeadOfDataObject();
- AnimBone* banim = new AnimBone;
- pAnim->mAnims.push_back( banim);
-
- bool running = true;
- while( running )
- {
- std::string objectName = GetNextToken();
-
- if( objectName.length() == 0)
- ThrowException( "Unexpected end of file while parsing animation.");
- else
- if( objectName == "}")
- break; // animation finished
- else
- if( objectName == "AnimationKey")
- ParseDataObjectAnimationKey( banim);
- else
- if( objectName == "AnimationOptions")
- ParseUnknownDataObject(); // not interested
- else
- if( objectName == "{")
- {
- // read frame name
- banim->mBoneName = GetNextToken();
- CheckForClosingBrace();
- } else
- {
- DefaultLogger::get()->warn("Unknown data object in animation in x file");
- ParseUnknownDataObject();
- }
- }
+ readHeadOfDataObject();
+ AnimBone* banim = new AnimBone;
+ pAnim->mAnims.push_back( banim);
+
+ bool running = true;
+ while( running )
+ {
+ std::string objectName = GetNextToken();
+
+ if( objectName.length() == 0)
+ ThrowException( "Unexpected end of file while parsing animation.");
+ else
+ if( objectName == "}")
+ break; // animation finished
+ else
+ if( objectName == "AnimationKey")
+ ParseDataObjectAnimationKey( banim);
+ else
+ if( objectName == "AnimationOptions")
+ ParseUnknownDataObject(); // not interested
+ else
+ if( objectName == "{")
+ {
+ // read frame name
+ banim->mBoneName = GetNextToken();
+ CheckForClosingBrace();
+ } else
+ {
+ DefaultLogger::get()->warn("Unknown data object in animation in x file");
+ ParseUnknownDataObject();
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectAnimationKey( AnimBone* pAnimBone)
{
- readHeadOfDataObject();
-
- // read key type
- unsigned int keyType = ReadInt();
-
- // read number of keys
- unsigned int numKeys = ReadInt();
-
- for( unsigned int a = 0; a < numKeys; a++)
- {
- // read time
- unsigned int time = ReadInt();
-
- // read keys
- switch( keyType)
- {
- case 0: // rotation quaternion
- {
- // read count
- if( ReadInt() != 4)
- ThrowException( "Invalid number of arguments for quaternion key in animation");
-
- aiQuatKey key;
- key.mTime = double( time);
- key.mValue.w = ReadFloat();
- key.mValue.x = ReadFloat();
- key.mValue.y = ReadFloat();
- key.mValue.z = ReadFloat();
- pAnimBone->mRotKeys.push_back( key);
-
- CheckForSemicolon();
- break;
- }
-
- case 1: // scale vector
- case 2: // position vector
- {
- // read count
- if( ReadInt() != 3)
- ThrowException( "Invalid number of arguments for vector key in animation");
-
- aiVectorKey key;
- key.mTime = double( time);
- key.mValue = ReadVector3();
-
- if( keyType == 2)
- pAnimBone->mPosKeys.push_back( key);
- else
- pAnimBone->mScaleKeys.push_back( key);
-
- break;
- }
-
- case 3: // combined transformation matrix
- case 4: // denoted both as 3 or as 4
- {
- // read count
- if( ReadInt() != 16)
- ThrowException( "Invalid number of arguments for matrix key in animation");
-
- // read matrix
- MatrixKey key;
- key.mTime = double( time);
- key.mMatrix.a1 = ReadFloat(); key.mMatrix.b1 = ReadFloat();
- key.mMatrix.c1 = ReadFloat(); key.mMatrix.d1 = ReadFloat();
- key.mMatrix.a2 = ReadFloat(); key.mMatrix.b2 = ReadFloat();
- key.mMatrix.c2 = ReadFloat(); key.mMatrix.d2 = ReadFloat();
- key.mMatrix.a3 = ReadFloat(); key.mMatrix.b3 = ReadFloat();
- key.mMatrix.c3 = ReadFloat(); key.mMatrix.d3 = ReadFloat();
- key.mMatrix.a4 = ReadFloat(); key.mMatrix.b4 = ReadFloat();
- key.mMatrix.c4 = ReadFloat(); key.mMatrix.d4 = ReadFloat();
- pAnimBone->mTrafoKeys.push_back( key);
-
- CheckForSemicolon();
- break;
- }
-
- default:
- ThrowException( boost::str( boost::format( "Unknown key type %1% in animation.") % keyType));
- break;
- } // end switch
-
- // key separator
- CheckForSeparator();
- }
-
- CheckForClosingBrace();
+ readHeadOfDataObject();
+
+ // read key type
+ unsigned int keyType = ReadInt();
+
+ // read number of keys
+ unsigned int numKeys = ReadInt();
+
+ for( unsigned int a = 0; a < numKeys; a++)
+ {
+ // read time
+ unsigned int time = ReadInt();
+
+ // read keys
+ switch( keyType)
+ {
+ case 0: // rotation quaternion
+ {
+ // read count
+ if( ReadInt() != 4)
+ ThrowException( "Invalid number of arguments for quaternion key in animation");
+
+ aiQuatKey key;
+ key.mTime = double( time);
+ key.mValue.w = ReadFloat();
+ key.mValue.x = ReadFloat();
+ key.mValue.y = ReadFloat();
+ key.mValue.z = ReadFloat();
+ pAnimBone->mRotKeys.push_back( key);
+
+ CheckForSemicolon();
+ break;
+ }
+
+ case 1: // scale vector
+ case 2: // position vector
+ {
+ // read count
+ if( ReadInt() != 3)
+ ThrowException( "Invalid number of arguments for vector key in animation");
+
+ aiVectorKey key;
+ key.mTime = double( time);
+ key.mValue = ReadVector3();
+
+ if( keyType == 2)
+ pAnimBone->mPosKeys.push_back( key);
+ else
+ pAnimBone->mScaleKeys.push_back( key);
+
+ break;
+ }
+
+ case 3: // combined transformation matrix
+ case 4: // denoted both as 3 or as 4
+ {
+ // read count
+ if( ReadInt() != 16)
+ ThrowException( "Invalid number of arguments for matrix key in animation");
+
+ // read matrix
+ MatrixKey key;
+ key.mTime = double( time);
+ key.mMatrix.a1 = ReadFloat(); key.mMatrix.b1 = ReadFloat();
+ key.mMatrix.c1 = ReadFloat(); key.mMatrix.d1 = ReadFloat();
+ key.mMatrix.a2 = ReadFloat(); key.mMatrix.b2 = ReadFloat();
+ key.mMatrix.c2 = ReadFloat(); key.mMatrix.d2 = ReadFloat();
+ key.mMatrix.a3 = ReadFloat(); key.mMatrix.b3 = ReadFloat();
+ key.mMatrix.c3 = ReadFloat(); key.mMatrix.d3 = ReadFloat();
+ key.mMatrix.a4 = ReadFloat(); key.mMatrix.b4 = ReadFloat();
+ key.mMatrix.c4 = ReadFloat(); key.mMatrix.d4 = ReadFloat();
+ pAnimBone->mTrafoKeys.push_back( key);
+
+ CheckForSemicolon();
+ break;
+ }
+
+ default:
+ ThrowException( format() << "Unknown key type " << keyType << " in animation." );
+ break;
+ } // end switch
+
+ // key separator
+ CheckForSeparator();
+ }
+
+ CheckForClosingBrace();
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseDataObjectTextureFilename( std::string& pName)
{
- readHeadOfDataObject();
- GetNextTokenAsString( pName);
- CheckForClosingBrace();
-
- // FIX: some files (e.g. AnimationTest.x) have "" as texture file name
- if (!pName.length())
- {
- DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture.");
- }
-
- // some exporters write double backslash paths out. We simply replace them if we find them
- while( pName.find( "\\\\") != std::string::npos)
- pName.replace( pName.find( "\\\\"), 2, "\\");
+ readHeadOfDataObject();
+ GetNextTokenAsString( pName);
+ CheckForClosingBrace();
+
+ // FIX: some files (e.g. AnimationTest.x) have "" as texture file name
+ if (!pName.length())
+ {
+ DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture.");
+ }
+
+ // some exporters write double backslash paths out. We simply replace them if we find them
+ while( pName.find( "\\\\") != std::string::npos)
+ pName.replace( pName.find( "\\\\"), 2, "\\");
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ParseUnknownDataObject()
{
- // find opening delimiter
- bool running = true;
- while( running )
- {
- std::string t = GetNextToken();
- if( t.length() == 0)
- ThrowException( "Unexpected end of file while parsing unknown segment.");
-
- if( t == "{")
- break;
- }
-
- unsigned int counter = 1;
-
- // parse until closing delimiter
- while( counter > 0)
- {
- std::string t = GetNextToken();
-
- if( t.length() == 0)
- ThrowException( "Unexpected end of file while parsing unknown segment.");
-
- if( t == "{")
- ++counter;
- else
- if( t == "}")
- --counter;
- }
+ // find opening delimiter
+ bool running = true;
+ while( running )
+ {
+ std::string t = GetNextToken();
+ if( t.length() == 0)
+ ThrowException( "Unexpected end of file while parsing unknown segment.");
+
+ if( t == "{")
+ break;
+ }
+
+ unsigned int counter = 1;
+
+ // parse until closing delimiter
+ while( counter > 0)
+ {
+ std::string t = GetNextToken();
+
+ if( t.length() == 0)
+ ThrowException( "Unexpected end of file while parsing unknown segment.");
+
+ if( t == "{")
+ ++counter;
+ else
+ if( t == "}")
+ --counter;
+ }
}
// ------------------------------------------------------------------------------------------------
//! checks for closing curly brace
void XFileParser::CheckForClosingBrace()
{
- if( GetNextToken() != "}")
- ThrowException( "Closing brace expected.");
+ if( GetNextToken() != "}")
+ ThrowException( "Closing brace expected.");
}
// ------------------------------------------------------------------------------------------------
//! checks for one following semicolon
void XFileParser::CheckForSemicolon()
{
- if( mIsBinaryFormat)
- return;
+ if( mIsBinaryFormat)
+ return;
- if( GetNextToken() != ";")
- ThrowException( "Semicolon expected.");
+ if( GetNextToken() != ";")
+ ThrowException( "Semicolon expected.");
}
// ------------------------------------------------------------------------------------------------
//! checks for a separator char, either a ',' or a ';'
void XFileParser::CheckForSeparator()
{
- if( mIsBinaryFormat)
- return;
+ if( mIsBinaryFormat)
+ return;
- std::string token = GetNextToken();
- if( token != "," && token != ";")
- ThrowException( "Separator character (';' or ',') expected.");
+ std::string token = GetNextToken();
+ if( token != "," && token != ";")
+ ThrowException( "Separator character (';' or ',') expected.");
}
// ------------------------------------------------------------------------------------------------
@@ -1030,410 +1041,410 @@ void XFileParser::TestForSeparator()
// ------------------------------------------------------------------------------------------------
void XFileParser::readHeadOfDataObject( std::string* poName)
{
- std::string nameOrBrace = GetNextToken();
- if( nameOrBrace != "{")
- {
- if( poName)
- *poName = nameOrBrace;
-
- if( GetNextToken() != "{")
- ThrowException( "Opening brace expected.");
- }
+ std::string nameOrBrace = GetNextToken();
+ if( nameOrBrace != "{")
+ {
+ if( poName)
+ *poName = nameOrBrace;
+
+ if( GetNextToken() != "{")
+ ThrowException( "Opening brace expected.");
+ }
}
// ------------------------------------------------------------------------------------------------
std::string XFileParser::GetNextToken()
{
- std::string s;
-
- // process binary-formatted file
- if( mIsBinaryFormat)
- {
- // in binary mode it will only return NAME and STRING token
- // and (correctly) skip over other tokens.
-
- if( End - P < 2) return s;
- unsigned int tok = ReadBinWord();
- unsigned int len;
-
- // standalone tokens
- switch( tok)
- {
- case 1:
- // name token
- if( End - P < 4) return s;
- len = ReadBinDWord();
- if( End - P < int(len)) return s;
- s = std::string(P, len);
- P += len;
- return s;
- case 2:
- // string token
- if( End - P < 4) return s;
- len = ReadBinDWord();
- if( End - P < int(len)) return s;
- s = std::string(P, len);
- P += (len + 2);
- return s;
- case 3:
- // integer token
- P += 4;
- return "<integer>";
- case 5:
- // GUID token
- P += 16;
- return "<guid>";
- case 6:
- if( End - P < 4) return s;
- len = ReadBinDWord();
- P += (len * 4);
- return "<int_list>";
- case 7:
- if( End - P < 4) return s;
- len = ReadBinDWord();
- P += (len * mBinaryFloatSize);
- return "<flt_list>";
- case 0x0a:
- return "{";
- case 0x0b:
- return "}";
- case 0x0c:
- return "(";
- case 0x0d:
- return ")";
- case 0x0e:
- return "[";
- case 0x0f:
- return "]";
- case 0x10:
- return "<";
- case 0x11:
- return ">";
- case 0x12:
- return ".";
- case 0x13:
- return ",";
- case 0x14:
- return ";";
- case 0x1f:
- return "template";
- case 0x28:
- return "WORD";
- case 0x29:
- return "DWORD";
- case 0x2a:
- return "FLOAT";
- case 0x2b:
- return "DOUBLE";
- case 0x2c:
- return "CHAR";
- case 0x2d:
- return "UCHAR";
- case 0x2e:
- return "SWORD";
- case 0x2f:
- return "SDWORD";
- case 0x30:
- return "void";
- case 0x31:
- return "string";
- case 0x32:
- return "unicode";
- case 0x33:
- return "cstring";
- case 0x34:
- return "array";
- }
- }
- // process text-formatted file
- else
- {
- FindNextNoneWhiteSpace();
- if( P >= End)
- return s;
-
- while( (P < End) && !isspace( (unsigned char) *P))
- {
- // either keep token delimiters when already holding a token, or return if first valid char
- if( *P == ';' || *P == '}' || *P == '{' || *P == ',')
- {
- if( !s.size())
- s.append( P++, 1);
- break; // stop for delimiter
- }
- s.append( P++, 1);
- }
- }
- return s;
+ std::string s;
+
+ // process binary-formatted file
+ if( mIsBinaryFormat)
+ {
+ // in binary mode it will only return NAME and STRING token
+ // and (correctly) skip over other tokens.
+
+ if( End - P < 2) return s;
+ unsigned int tok = ReadBinWord();
+ unsigned int len;
+
+ // standalone tokens
+ switch( tok)
+ {
+ case 1:
+ // name token
+ if( End - P < 4) return s;
+ len = ReadBinDWord();
+ if( End - P < int(len)) return s;
+ s = std::string(P, len);
+ P += len;
+ return s;
+ case 2:
+ // string token
+ if( End - P < 4) return s;
+ len = ReadBinDWord();
+ if( End - P < int(len)) return s;
+ s = std::string(P, len);
+ P += (len + 2);
+ return s;
+ case 3:
+ // integer token
+ P += 4;
+ return "<integer>";
+ case 5:
+ // GUID token
+ P += 16;
+ return "<guid>";
+ case 6:
+ if( End - P < 4) return s;
+ len = ReadBinDWord();
+ P += (len * 4);
+ return "<int_list>";
+ case 7:
+ if( End - P < 4) return s;
+ len = ReadBinDWord();
+ P += (len * mBinaryFloatSize);
+ return "<flt_list>";
+ case 0x0a:
+ return "{";
+ case 0x0b:
+ return "}";
+ case 0x0c:
+ return "(";
+ case 0x0d:
+ return ")";
+ case 0x0e:
+ return "[";
+ case 0x0f:
+ return "]";
+ case 0x10:
+ return "<";
+ case 0x11:
+ return ">";
+ case 0x12:
+ return ".";
+ case 0x13:
+ return ",";
+ case 0x14:
+ return ";";
+ case 0x1f:
+ return "template";
+ case 0x28:
+ return "WORD";
+ case 0x29:
+ return "DWORD";
+ case 0x2a:
+ return "FLOAT";
+ case 0x2b:
+ return "DOUBLE";
+ case 0x2c:
+ return "CHAR";
+ case 0x2d:
+ return "UCHAR";
+ case 0x2e:
+ return "SWORD";
+ case 0x2f:
+ return "SDWORD";
+ case 0x30:
+ return "void";
+ case 0x31:
+ return "string";
+ case 0x32:
+ return "unicode";
+ case 0x33:
+ return "cstring";
+ case 0x34:
+ return "array";
+ }
+ }
+ // process text-formatted file
+ else
+ {
+ FindNextNoneWhiteSpace();
+ if( P >= End)
+ return s;
+
+ while( (P < End) && !isspace( (unsigned char) *P))
+ {
+ // either keep token delimiters when already holding a token, or return if first valid char
+ if( *P == ';' || *P == '}' || *P == '{' || *P == ',')
+ {
+ if( !s.size())
+ s.append( P++, 1);
+ break; // stop for delimiter
+ }
+ s.append( P++, 1);
+ }
+ }
+ return s;
}
// ------------------------------------------------------------------------------------------------
void XFileParser::FindNextNoneWhiteSpace()
{
- if( mIsBinaryFormat)
- return;
-
- bool running = true;
- while( running )
- {
- while( P < End && isspace( (unsigned char) *P))
- {
- if( *P == '\n')
- mLineNumber++;
- ++P;
- }
-
- if( P >= End)
- return;
-
- // check if this is a comment
- if( (P[0] == '/' && P[1] == '/') || P[0] == '#')
- ReadUntilEndOfLine();
- else
- break;
- }
+ if( mIsBinaryFormat)
+ return;
+
+ bool running = true;
+ while( running )
+ {
+ while( P < End && isspace( (unsigned char) *P))
+ {
+ if( *P == '\n')
+ mLineNumber++;
+ ++P;
+ }
+
+ if( P >= End)
+ return;
+
+ // check if this is a comment
+ if( (P[0] == '/' && P[1] == '/') || P[0] == '#')
+ ReadUntilEndOfLine();
+ else
+ break;
+ }
}
// ------------------------------------------------------------------------------------------------
void XFileParser::GetNextTokenAsString( std::string& poString)
{
- if( mIsBinaryFormat)
- {
- poString = GetNextToken();
- return;
- }
+ if( mIsBinaryFormat)
+ {
+ poString = GetNextToken();
+ return;
+ }
- FindNextNoneWhiteSpace();
- if( P >= End)
- ThrowException( "Unexpected end of file while parsing string");
+ FindNextNoneWhiteSpace();
+ if( P >= End)
+ ThrowException( "Unexpected end of file while parsing string");
- if( *P != '"')
- ThrowException( "Expected quotation mark.");
- ++P;
+ if( *P != '"')
+ ThrowException( "Expected quotation mark.");
+ ++P;
- while( P < End && *P != '"')
- poString.append( P++, 1);
+ while( P < End && *P != '"')
+ poString.append( P++, 1);
- if( P >= End-1)
- ThrowException( "Unexpected end of file while parsing string");
+ if( P >= End-1)
+ ThrowException( "Unexpected end of file while parsing string");
- if( P[1] != ';' || P[0] != '"')
- ThrowException( "Expected quotation mark and semicolon at the end of a string.");
- P+=2;
+ if( P[1] != ';' || P[0] != '"')
+ ThrowException( "Expected quotation mark and semicolon at the end of a string.");
+ P+=2;
}
// ------------------------------------------------------------------------------------------------
void XFileParser::ReadUntilEndOfLine()
{
- if( mIsBinaryFormat)
- return;
-
- while( P < End)
- {
- if( *P == '\n' || *P == '\r')
- {
- ++P; mLineNumber++;
- return;
- }
-
- ++P;
- }
+ if( mIsBinaryFormat)
+ return;
+
+ while( P < End)
+ {
+ if( *P == '\n' || *P == '\r')
+ {
+ ++P; mLineNumber++;
+ return;
+ }
+
+ ++P;
+ }
}
// ------------------------------------------------------------------------------------------------
unsigned short XFileParser::ReadBinWord()
{
- ai_assert(End - P >= 2);
- const unsigned char* q = (const unsigned char*) P;
- unsigned short tmp = q[0] | (q[1] << 8);
- P += 2;
- return tmp;
+ ai_assert(End - P >= 2);
+ const unsigned char* q = (const unsigned char*) P;
+ unsigned short tmp = q[0] | (q[1] << 8);
+ P += 2;
+ return tmp;
}
// ------------------------------------------------------------------------------------------------
unsigned int XFileParser::ReadBinDWord()
{
- ai_assert(End - P >= 4);
- const unsigned char* q = (const unsigned char*) P;
- unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
- P += 4;
- return tmp;
+ ai_assert(End - P >= 4);
+ const unsigned char* q = (const unsigned char*) P;
+ unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
+ P += 4;
+ return tmp;
}
// ------------------------------------------------------------------------------------------------
unsigned int XFileParser::ReadInt()
{
- if( mIsBinaryFormat)
- {
- if( mBinaryNumCount == 0 && End - P >= 2)
- {
- unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
- if( tmp == 0x06 && End - P >= 4) // array of ints follows
- mBinaryNumCount = ReadBinDWord();
- else // single int follows
- mBinaryNumCount = 1;
- }
-
- --mBinaryNumCount;
- if ( End - P >= 4) {
- return ReadBinDWord();
- } else {
- P = End;
- return 0;
- }
- } else
- {
- FindNextNoneWhiteSpace();
-
- // TODO: consider using strtol10 instead???
-
- // check preceeding minus sign
- bool isNegative = false;
- if( *P == '-')
- {
- isNegative = true;
- P++;
- }
-
- // at least one digit expected
- if( !isdigit( *P))
- ThrowException( "Number expected.");
-
- // read digits
- unsigned int number = 0;
- while( P < End)
- {
- if( !isdigit( *P))
- break;
- number = number * 10 + (*P - 48);
- P++;
- }
-
- CheckForSeparator();
- return isNegative ? ((unsigned int) -int( number)) : number;
- }
+ if( mIsBinaryFormat)
+ {
+ if( mBinaryNumCount == 0 && End - P >= 2)
+ {
+ unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
+ if( tmp == 0x06 && End - P >= 4) // array of ints follows
+ mBinaryNumCount = ReadBinDWord();
+ else // single int follows
+ mBinaryNumCount = 1;
+ }
+
+ --mBinaryNumCount;
+ if ( End - P >= 4) {
+ return ReadBinDWord();
+ } else {
+ P = End;
+ return 0;
+ }
+ } else
+ {
+ FindNextNoneWhiteSpace();
+
+ // TODO: consider using strtol10 instead???
+
+ // check preceding minus sign
+ bool isNegative = false;
+ if( *P == '-')
+ {
+ isNegative = true;
+ P++;
+ }
+
+ // at least one digit expected
+ if( !isdigit( *P))
+ ThrowException( "Number expected.");
+
+ // read digits
+ unsigned int number = 0;
+ while( P < End)
+ {
+ if( !isdigit( *P))
+ break;
+ number = number * 10 + (*P - 48);
+ P++;
+ }
+
+ CheckForSeparator();
+ return isNegative ? ((unsigned int) -int( number)) : number;
+ }
}
// ------------------------------------------------------------------------------------------------
float XFileParser::ReadFloat()
{
- if( mIsBinaryFormat)
- {
- if( mBinaryNumCount == 0 && End - P >= 2)
- {
- unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
- if( tmp == 0x07 && End - P >= 4) // array of floats following
- mBinaryNumCount = ReadBinDWord();
- else // single float following
- mBinaryNumCount = 1;
- }
-
- --mBinaryNumCount;
- if( mBinaryFloatSize == 8)
- {
- if( End - P >= 8) {
- float result = (float) (*(double*) P);
- P += 8;
- return result;
- } else {
- P = End;
- return 0;
- }
- } else
- {
- if( End - P >= 4) {
- float result = *(float*) P;
- P += 4;
- return result;
- } else {
- P = End;
- return 0;
- }
- }
- }
-
- // text version
- FindNextNoneWhiteSpace();
- // check for various special strings to allow reading files from faulty exporters
- // I mean you, Blender!
- // Reading is safe because of the terminating zero
- if( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0)
- {
- P += 9;
- CheckForSeparator();
- return 0.0f;
- } else
- if( strncmp( P, "1.#QNAN0", 8) == 0)
- {
- P += 8;
- CheckForSeparator();
- return 0.0f;
- }
-
- float result = 0.0f;
- P = fast_atoreal_move<float>( P, result);
-
- CheckForSeparator();
-
- return result;
+ if( mIsBinaryFormat)
+ {
+ if( mBinaryNumCount == 0 && End - P >= 2)
+ {
+ unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
+ if( tmp == 0x07 && End - P >= 4) // array of floats following
+ mBinaryNumCount = ReadBinDWord();
+ else // single float following
+ mBinaryNumCount = 1;
+ }
+
+ --mBinaryNumCount;
+ if( mBinaryFloatSize == 8)
+ {
+ if( End - P >= 8) {
+ float result = (float) (*(double*) P);
+ P += 8;
+ return result;
+ } else {
+ P = End;
+ return 0;
+ }
+ } else
+ {
+ if( End - P >= 4) {
+ float result = *(float*) P;
+ P += 4;
+ return result;
+ } else {
+ P = End;
+ return 0;
+ }
+ }
+ }
+
+ // text version
+ FindNextNoneWhiteSpace();
+ // check for various special strings to allow reading files from faulty exporters
+ // I mean you, Blender!
+ // Reading is safe because of the terminating zero
+ if( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0)
+ {
+ P += 9;
+ CheckForSeparator();
+ return 0.0f;
+ } else
+ if( strncmp( P, "1.#QNAN0", 8) == 0)
+ {
+ P += 8;
+ CheckForSeparator();
+ return 0.0f;
+ }
+
+ float result = 0.0f;
+ P = fast_atoreal_move<float>( P, result);
+
+ CheckForSeparator();
+
+ return result;
}
// ------------------------------------------------------------------------------------------------
aiVector2D XFileParser::ReadVector2()
{
- aiVector2D vector;
- vector.x = ReadFloat();
- vector.y = ReadFloat();
- TestForSeparator();
+ aiVector2D vector;
+ vector.x = ReadFloat();
+ vector.y = ReadFloat();
+ TestForSeparator();
- return vector;
+ return vector;
}
// ------------------------------------------------------------------------------------------------
aiVector3D XFileParser::ReadVector3()
{
- aiVector3D vector;
- vector.x = ReadFloat();
- vector.y = ReadFloat();
- vector.z = ReadFloat();
- TestForSeparator();
+ aiVector3D vector;
+ vector.x = ReadFloat();
+ vector.y = ReadFloat();
+ vector.z = ReadFloat();
+ TestForSeparator();
- return vector;
+ return vector;
}
// ------------------------------------------------------------------------------------------------
aiColor4D XFileParser::ReadRGBA()
{
- aiColor4D color;
- color.r = ReadFloat();
- color.g = ReadFloat();
- color.b = ReadFloat();
- color.a = ReadFloat();
- TestForSeparator();
-
- return color;
+ aiColor4D color;
+ color.r = ReadFloat();
+ color.g = ReadFloat();
+ color.b = ReadFloat();
+ color.a = ReadFloat();
+ TestForSeparator();
+
+ return color;
}
// ------------------------------------------------------------------------------------------------
aiColor3D XFileParser::ReadRGB()
{
- aiColor3D color;
- color.r = ReadFloat();
- color.g = ReadFloat();
- color.b = ReadFloat();
- TestForSeparator();
+ aiColor3D color;
+ color.r = ReadFloat();
+ color.g = ReadFloat();
+ color.b = ReadFloat();
+ TestForSeparator();
- return color;
+ return color;
}
// ------------------------------------------------------------------------------------------------
// Throws an exception with a line number and the given text.
-void XFileParser::ThrowException( const std::string& pText)
+AI_WONT_RETURN void XFileParser::ThrowException( const std::string& pText)
{
- if( mIsBinaryFormat)
- throw DeadlyImportError( pText);
- else
- throw DeadlyImportError( boost::str( boost::format( "Line %d: %s") % mLineNumber % pText));
+ if( mIsBinaryFormat)
+ throw DeadlyImportError( pText);
+ else
+ throw DeadlyImportError( format() << "Line " << mLineNumber << ": " << pText );
}
@@ -1441,31 +1452,31 @@ void XFileParser::ThrowException( const std::string& pText)
// Filters the imported hierarchy for some degenerated cases that some exporters produce.
void XFileParser::FilterHierarchy( XFile::Node* pNode)
{
- // if the node has just a single unnamed child containing a mesh, remove
- // the anonymous node inbetween. The 3DSMax kwXport plugin seems to produce this
- // mess in some cases
- if( pNode->mChildren.size() == 1 && pNode->mMeshes.empty() )
- {
- XFile::Node* child = pNode->mChildren.front();
- if( child->mName.length() == 0 && child->mMeshes.size() > 0)
- {
- // transfer its meshes to us
- for( unsigned int a = 0; a < child->mMeshes.size(); a++)
- pNode->mMeshes.push_back( child->mMeshes[a]);
- child->mMeshes.clear();
-
- // transfer the transform as well
- pNode->mTrafoMatrix = pNode->mTrafoMatrix * child->mTrafoMatrix;
-
- // then kill it
- delete child;
- pNode->mChildren.clear();
- }
- }
-
- // recurse
- for( unsigned int a = 0; a < pNode->mChildren.size(); a++)
- FilterHierarchy( pNode->mChildren[a]);
+ // if the node has just a single unnamed child containing a mesh, remove
+ // the anonymous node between. The 3DSMax kwXport plugin seems to produce this
+ // mess in some cases
+ if( pNode->mChildren.size() == 1 && pNode->mMeshes.empty() )
+ {
+ XFile::Node* child = pNode->mChildren.front();
+ if( child->mName.length() == 0 && child->mMeshes.size() > 0)
+ {
+ // transfer its meshes to us
+ for( unsigned int a = 0; a < child->mMeshes.size(); a++)
+ pNode->mMeshes.push_back( child->mMeshes[a]);
+ child->mMeshes.clear();
+
+ // transfer the transform as well
+ pNode->mTrafoMatrix = pNode->mTrafoMatrix * child->mTrafoMatrix;
+
+ // then kill it
+ delete child;
+ pNode->mChildren.clear();
+ }
+ }
+
+ // recurse
+ for( unsigned int a = 0; a < pNode->mChildren.size(); a++)
+ FilterHierarchy( pNode->mChildren[a]);
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER
diff --git a/src/3rdparty/assimp/code/XFileParser.h b/src/3rdparty/assimp/code/XFileParser.h
index 6ab292787..14c5ef1cf 100644
--- a/src/3rdparty/assimp/code/XFileParser.h
+++ b/src/3rdparty/assimp/code/XFileParser.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -45,117 +45,117 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
-#include "../include/assimp/types.h"
+#include <assimp/types.h>
namespace Assimp
{
- namespace XFile
- {
- struct Node;
- struct Mesh;
- struct Scene;
- struct Material;
- struct Animation;
- struct AnimBone;
- }
-
-/** The XFileParser reads a XFile either in text or binary form and builds a temporary
- * data structure out of it.
+ namespace XFile
+ {
+ struct Node;
+ struct Mesh;
+ struct Scene;
+ struct Material;
+ struct Animation;
+ struct AnimBone;
+ }
+
+/** The XFileParser reads a XFile either in text or binary form and builds a temporary
+ * data structure out of it.
*/
class XFileParser
{
public:
- /** Constructor. Creates a data structure out of the XFile given in the memory block.
- * @param pBuffer Null-terminated memory buffer containing the XFile
- */
- XFileParser( const std::vector<char>& pBuffer);
+ /** Constructor. Creates a data structure out of the XFile given in the memory block.
+ * @param pBuffer Null-terminated memory buffer containing the XFile
+ */
+ explicit XFileParser( const std::vector<char>& pBuffer);
- /** Destructor. Destroys all imported data along with it */
- ~XFileParser();
+ /** Destructor. Destroys all imported data along with it */
+ ~XFileParser();
- /** Returns the temporary representation of the imported data */
- XFile::Scene* GetImportedData() const { return mScene; }
+ /** Returns the temporary representation of the imported data */
+ XFile::Scene* GetImportedData() const { return mScene; }
protected:
- void ParseFile();
- void ParseDataObjectTemplate();
- void ParseDataObjectFrame( XFile::Node *pParent);
- void ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix);
- void ParseDataObjectMesh( XFile::Mesh* pMesh);
- void ParseDataObjectSkinWeights( XFile::Mesh* pMesh);
- void ParseDataObjectSkinMeshHeader( XFile::Mesh* pMesh);
- void ParseDataObjectMeshNormals( XFile::Mesh* pMesh);
- void ParseDataObjectMeshTextureCoords( XFile::Mesh* pMesh);
- void ParseDataObjectMeshVertexColors( XFile::Mesh* pMesh);
- void ParseDataObjectMeshMaterialList( XFile::Mesh* pMesh);
- void ParseDataObjectMaterial( XFile::Material* pMaterial);
- void ParseDataObjectAnimTicksPerSecond();
- void ParseDataObjectAnimationSet();
- void ParseDataObjectAnimation( XFile::Animation* pAnim);
- void ParseDataObjectAnimationKey( XFile::AnimBone *pAnimBone);
- void ParseDataObjectTextureFilename( std::string& pName);
- void ParseUnknownDataObject();
-
- //! places pointer to next begin of a token, and ignores comments
- void FindNextNoneWhiteSpace();
-
- //! returns next parseable token. Returns empty string if no token there
- std::string GetNextToken();
-
- //! reads header of dataobject including the opening brace.
- //! returns false if error happened, and writes name of object
- //! if there is one
- void readHeadOfDataObject( std::string* poName = NULL);
-
- //! checks for closing curly brace, throws exception if not there
- void CheckForClosingBrace();
-
- //! checks for one following semicolon, throws exception if not there
- void CheckForSemicolon();
-
- //! checks for a separator char, either a ',' or a ';'
- void CheckForSeparator();
+ void ParseFile();
+ void ParseDataObjectTemplate();
+ void ParseDataObjectFrame( XFile::Node *pParent);
+ void ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix);
+ void ParseDataObjectMesh( XFile::Mesh* pMesh);
+ void ParseDataObjectSkinWeights( XFile::Mesh* pMesh);
+ void ParseDataObjectSkinMeshHeader( XFile::Mesh* pMesh);
+ void ParseDataObjectMeshNormals( XFile::Mesh* pMesh);
+ void ParseDataObjectMeshTextureCoords( XFile::Mesh* pMesh);
+ void ParseDataObjectMeshVertexColors( XFile::Mesh* pMesh);
+ void ParseDataObjectMeshMaterialList( XFile::Mesh* pMesh);
+ void ParseDataObjectMaterial( XFile::Material* pMaterial);
+ void ParseDataObjectAnimTicksPerSecond();
+ void ParseDataObjectAnimationSet();
+ void ParseDataObjectAnimation( XFile::Animation* pAnim);
+ void ParseDataObjectAnimationKey( XFile::AnimBone *pAnimBone);
+ void ParseDataObjectTextureFilename( std::string& pName);
+ void ParseUnknownDataObject();
+
+ //! places pointer to next begin of a token, and ignores comments
+ void FindNextNoneWhiteSpace();
+
+ //! returns next parseable token. Returns empty string if no token there
+ std::string GetNextToken();
+
+ //! reads header of dataobject including the opening brace.
+ //! returns false if error happened, and writes name of object
+ //! if there is one
+ void readHeadOfDataObject( std::string* poName = NULL);
+
+ //! checks for closing curly brace, throws exception if not there
+ void CheckForClosingBrace();
+
+ //! checks for one following semicolon, throws exception if not there
+ void CheckForSemicolon();
+
+ //! checks for a separator char, either a ',' or a ';'
+ void CheckForSeparator();
/// tests and possibly consumes a separator char, but does nothing if there was no separator
void TestForSeparator();
- //! reads a x file style string
- void GetNextTokenAsString( std::string& poString);
+ //! reads a x file style string
+ void GetNextTokenAsString( std::string& poString);
- void ReadUntilEndOfLine();
+ void ReadUntilEndOfLine();
- unsigned short ReadBinWord();
- unsigned int ReadBinDWord();
- unsigned int ReadInt();
- float ReadFloat();
- aiVector2D ReadVector2();
- aiVector3D ReadVector3();
- aiColor3D ReadRGB();
- aiColor4D ReadRGBA();
+ unsigned short ReadBinWord();
+ unsigned int ReadBinDWord();
+ unsigned int ReadInt();
+ float ReadFloat();
+ aiVector2D ReadVector2();
+ aiVector3D ReadVector3();
+ aiColor3D ReadRGB();
+ aiColor4D ReadRGBA();
- /** Throws an exception with a line number and the given text. */
- void ThrowException( const std::string& pText);
+ /** Throws an exception with a line number and the given text. */
+ AI_WONT_RETURN void ThrowException( const std::string& pText) AI_WONT_RETURN_SUFFIX;
- /** Filters the imported hierarchy for some degenerated cases that some exporters produce.
- * @param pData The sub-hierarchy to filter
- */
- void FilterHierarchy( XFile::Node* pNode);
+ /** Filters the imported hierarchy for some degenerated cases that some exporters produce.
+ * @param pData The sub-hierarchy to filter
+ */
+ void FilterHierarchy( XFile::Node* pNode);
protected:
- unsigned int mMajorVersion, mMinorVersion; ///< version numbers
- bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form
- unsigned int mBinaryFloatSize; ///< float size in bytes, either 4 or 8
- // counter for number arrays in binary format
- unsigned int mBinaryNumCount;
+ unsigned int mMajorVersion, mMinorVersion; ///< version numbers
+ bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form
+ unsigned int mBinaryFloatSize; ///< float size in bytes, either 4 or 8
+ // counter for number arrays in binary format
+ unsigned int mBinaryNumCount;
- const char* P;
- const char* End;
+ const char* P;
+ const char* End;
- /// Line number when reading in text format
- unsigned int mLineNumber;
+ /// Line number when reading in text format
+ unsigned int mLineNumber;
- /// Imported data
- XFile::Scene* mScene;
+ /// Imported data
+ XFile::Scene* mScene;
};
}
diff --git a/src/3rdparty/assimp/code/XGLLoader.cpp b/src/3rdparty/assimp/code/XGLLoader.cpp
index 963407b9e..fafad2f66 100644
--- a/src/3rdparty/assimp/code/XGLLoader.cpp
+++ b/src/3rdparty/assimp/code/XGLLoader.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,23 +25,23 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the XGL/ZGL importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
#include "XGLLoader.h"
@@ -50,31 +50,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StreamReader.h"
#include "MemoryIOWrapper.h"
+#include <assimp/mesh.h>
+#include <assimp/scene.h>
+#include <cctype>
+#include <memory>
using namespace Assimp;
using namespace irr;
using namespace irr::io;
-
-// zlib is needed for compressed XGL files
+// zlib is needed for compressed XGL files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
-# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-# include <zlib.h>
-# else
-# include "../contrib/zlib/zlib.h"
-# endif
+# ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+# include <zlib.h>
+# else
+# include <contrib/zlib/zlib.h>
+# endif
#endif
// scopeguard for a malloc'ed buffer
struct free_it
{
- free_it(void* free) : free(free) {}
- ~free_it() {
- ::free(this->free);
- }
+ free_it(void* free) : free(free) {}
+ ~free_it() {
+ ::free(this->free);
+ }
- void* free;
+ void* free;
};
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
@@ -83,16 +86,16 @@ template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: ";
}
static const aiImporterDesc desc = {
- "XGL Importer",
- "",
- "",
- "",
- aiImporterFlags_SupportTextFlavour,
- 0,
- 0,
- 0,
- 0,
- "xgl zgl"
+ "XGL Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "xgl zgl"
};
@@ -102,846 +105,852 @@ XGLImporter::XGLImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
+// Destructor, private as well
XGLImporter::~XGLImporter()
{}
// ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
+// Returns whether the class can handle the format of the given file.
bool XGLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
- /* NOTE: A simple check for the file extension is not enough
- * here. XGL and ZGL are ok, but xml is too generic
- * and might be collada as well. So open the file and
- * look for typical signal tokens.
- */
- const std::string extension = GetExtension(pFile);
-
- if (extension == "xgl" || extension == "zgl") {
- return true;
- }
- else if (extension == "xml" || checkSig) {
- ai_assert(pIOHandler != NULL);
-
- const char* tokens[] = {"<world>","<World>","<WORLD>"};
- return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3);
- }
- return false;
+ /* NOTE: A simple check for the file extension is not enough
+ * here. XGL and ZGL are ok, but xml is too generic
+ * and might be collada as well. So open the file and
+ * look for typical signal tokens.
+ */
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "xgl" || extension == "zgl") {
+ return true;
+ }
+ else if (extension == "xml" || checkSig) {
+ ai_assert(pIOHandler != NULL);
+
+ const char* tokens[] = {"<world>","<World>","<WORLD>"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,3);
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
// Get a list of all file extensions which are handled by this class
const aiImporterDesc* XGLImporter::GetInfo () const
{
- return &desc;
+ return &desc;
}
// ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
-void XGLImporter::InternReadFile( const std::string& pFile,
- aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void XGLImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
{
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
- Bytef* dest = NULL;
- free_it free_it_really(dest);
+ Bytef* dest = NULL;
+ free_it free_it_really(dest);
#endif
- scene = pScene;
- boost::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
+ scene = pScene;
+ std::shared_ptr<IOStream> stream( pIOHandler->Open( pFile, "rb"));
- // check whether we can read from the file
- if( stream.get() == NULL) {
- throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + "");
- }
+ // check whether we can read from the file
+ if( stream.get() == NULL) {
+ throw DeadlyImportError( "Failed to open XGL/ZGL file " + pFile + "");
+ }
- // see if its compressed, if so uncompress it
- if (GetExtension(pFile) == "zgl") {
+ // see if its compressed, if so uncompress it
+ if (GetExtension(pFile) == "zgl") {
#ifdef ASSIMP_BUILD_NO_COMPRESSED_XGL
- ThrowException("Cannot read ZGL file since Assimp was built without compression support");
+ ThrowException("Cannot read ZGL file since Assimp was built without compression support");
#else
- boost::scoped_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
-
- // build a zlib stream
- z_stream zstream;
- zstream.opaque = Z_NULL;
- zstream.zalloc = Z_NULL;
- zstream.zfree = Z_NULL;
- zstream.data_type = Z_BINARY;
-
- // raw decompression without a zlib or gzip header
- inflateInit2(&zstream, -MAX_WBITS);
-
- // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
- raw_reader->IncPtr(2);
-
- zstream.next_in = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
- zstream.avail_in = raw_reader->GetRemainingSize();
-
- size_t total = 0l;
-
- // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
- #define MYBLOCK 1024
- Bytef block[MYBLOCK];
- int ret;
- do {
- zstream.avail_out = MYBLOCK;
- zstream.next_out = block;
- ret = inflate(&zstream, Z_NO_FLUSH);
-
- if (ret != Z_STREAM_END && ret != Z_OK) {
- ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
- }
- const size_t have = MYBLOCK - zstream.avail_out;
- total += have;
- dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
- memcpy(dest + total - have,block,have);
- }
- while (ret != Z_STREAM_END);
-
- // terminate zlib
- inflateEnd(&zstream);
-
- // replace the input stream with a memory stream
- stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
+ std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
+
+ // build a zlib stream
+ z_stream zstream;
+ zstream.opaque = Z_NULL;
+ zstream.zalloc = Z_NULL;
+ zstream.zfree = Z_NULL;
+ zstream.data_type = Z_BINARY;
+
+ // raw decompression without a zlib or gzip header
+ inflateInit2(&zstream, -MAX_WBITS);
+
+ // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
+ raw_reader->IncPtr(2);
+
+ zstream.next_in = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
+ zstream.avail_in = raw_reader->GetRemainingSize();
+
+ size_t total = 0l;
+
+ // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
+ #define MYBLOCK 1024
+ Bytef block[MYBLOCK];
+ int ret;
+ do {
+ zstream.avail_out = MYBLOCK;
+ zstream.next_out = block;
+ ret = inflate(&zstream, Z_NO_FLUSH);
+
+ if (ret != Z_STREAM_END && ret != Z_OK) {
+ ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
+ }
+ const size_t have = MYBLOCK - zstream.avail_out;
+ total += have;
+ dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
+ memcpy(dest + total - have,block,have);
+ }
+ while (ret != Z_STREAM_END);
+
+ // terminate zlib
+ inflateEnd(&zstream);
+
+ // replace the input stream with a memory stream
+ stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
#endif
- }
-
- // construct the irrXML parser
- CIrrXML_IOStreamReader st(stream.get());
- boost::scoped_ptr<IrrXMLReader> read( createIrrXMLReader((IFileReadCallBack*) &st) );
- reader = read.get();
-
- // parse the XML file
- TempScope scope;
-
- while (ReadElement()) {
- if (!ASSIMP_stricmp(reader->getNodeName(),"world")) {
- ReadWorld(scope);
- }
- }
-
-
- std::vector<aiMesh*>& meshes = scope.meshes_linear;
- std::vector<aiMaterial*>& materials = scope.materials_linear;
- if(!meshes.size() || !materials.size()) {
- ThrowException("failed to extract data from XGL file, no meshes loaded");
- }
-
- // copy meshes
- scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
- scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
- std::copy(meshes.begin(),meshes.end(),scene->mMeshes);
-
- // copy materials
- scene->mNumMaterials = static_cast<unsigned int>(materials.size());
- scene->mMaterials = new aiMaterial*[scene->mNumMaterials]();
- std::copy(materials.begin(),materials.end(),scene->mMaterials);
-
- if (scope.light) {
- scene->mNumLights = 1;
- scene->mLights = new aiLight*[1];
- scene->mLights[0] = scope.light;
-
- scope.light->mName = scene->mRootNode->mName;
- }
-
- scope.dismiss();
+ }
+
+ // construct the irrXML parser
+ CIrrXML_IOStreamReader st(stream.get());
+ std::unique_ptr<IrrXMLReader> read( createIrrXMLReader((IFileReadCallBack*) &st) );
+ reader = read.get();
+
+ // parse the XML file
+ TempScope scope;
+
+ while (ReadElement()) {
+ if (!ASSIMP_stricmp(reader->getNodeName(),"world")) {
+ ReadWorld(scope);
+ }
+ }
+
+
+ std::vector<aiMesh*>& meshes = scope.meshes_linear;
+ std::vector<aiMaterial*>& materials = scope.materials_linear;
+ if(!meshes.size() || !materials.size()) {
+ ThrowException("failed to extract data from XGL file, no meshes loaded");
+ }
+
+ // copy meshes
+ scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
+ std::copy(meshes.begin(),meshes.end(),scene->mMeshes);
+
+ // copy materials
+ scene->mNumMaterials = static_cast<unsigned int>(materials.size());
+ scene->mMaterials = new aiMaterial*[scene->mNumMaterials]();
+ std::copy(materials.begin(),materials.end(),scene->mMaterials);
+
+ if (scope.light) {
+ scene->mNumLights = 1;
+ scene->mLights = new aiLight*[1];
+ scene->mLights[0] = scope.light;
+
+ scope.light->mName = scene->mRootNode->mName;
+ }
+
+ scope.dismiss();
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElement()
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_ELEMENT) {
- return true;
- }
- }
- return false;
+ while(reader->read()) {
+ if (reader->getNodeType() == EXN_ELEMENT) {
+ return true;
+ }
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadElementUpToClosing(const char* closetag)
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_ELEMENT) {
- return true;
- }
- else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),closetag)) {
- return false;
- }
- }
- LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag");
- return false;
+ while(reader->read()) {
+ if (reader->getNodeType() == EXN_ELEMENT) {
+ return true;
+ }
+ else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),closetag)) {
+ return false;
+ }
+ }
+ LogError("unexpected EOF, expected closing <" + std::string(closetag) + "> tag");
+ return false;
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::SkipToText()
{
- while(reader->read()) {
- if (reader->getNodeType() == EXN_TEXT) {
- return true;
- }
- else if (reader->getNodeType() == EXN_ELEMENT || reader->getNodeType() == EXN_ELEMENT_END) {
- ThrowException("expected text contents but found another element (or element end)");
- }
- }
- return false;
+ while(reader->read()) {
+ if (reader->getNodeType() == EXN_TEXT) {
+ return true;
+ }
+ else if (reader->getNodeType() == EXN_ELEMENT || reader->getNodeType() == EXN_ELEMENT_END) {
+ ThrowException("expected text contents but found another element (or element end)");
+ }
+ }
+ return false;
}
// ------------------------------------------------------------------------------------------------
std::string XGLImporter::GetElementName()
{
- const char* s = reader->getNodeName();
- size_t len = strlen(s);
+ const char* s = reader->getNodeName();
+ size_t len = strlen(s);
- std::string ret;
- ret.resize(len);
+ std::string ret;
+ ret.resize(len);
- std::transform(s,s+len,ret.begin(),::tolower);
- return ret;
+ std::transform(s,s+len,ret.begin(),::tolower);
+ return ret;
}
// ------------------------------------------------------------------------------------------------
void XGLImporter::ReadWorld(TempScope& scope)
{
- while (ReadElementUpToClosing("world")) {
- const std::string& s = GetElementName();
- // XXX right now we'd skip <lighting> if it comes after
- // <object> or <mesh>
- if (s == "lighting") {
- ReadLighting(scope);
- }
- else if (s == "object" || s == "mesh" || s == "mat") {
- break;
- }
- }
-
-
- aiNode* const nd = ReadObject(scope,true,"world");
- if(!nd) {
- ThrowException("failure reading <world>");
- }
- if(!nd->mName.length) {
- nd->mName.Set("WORLD");
- }
-
- scene->mRootNode = nd;
+ while (ReadElementUpToClosing("world")) {
+ const std::string& s = GetElementName();
+ // XXX right now we'd skip <lighting> if it comes after
+ // <object> or <mesh>
+ if (s == "lighting") {
+ ReadLighting(scope);
+ }
+ else if (s == "object" || s == "mesh" || s == "mat") {
+ break;
+ }
+ }
+
+
+ aiNode* const nd = ReadObject(scope,true,"world");
+ if(!nd) {
+ ThrowException("failure reading <world>");
+ }
+ if(!nd->mName.length) {
+ nd->mName.Set("WORLD");
+ }
+
+ scene->mRootNode = nd;
}
// ------------------------------------------------------------------------------------------------
void XGLImporter::ReadLighting(TempScope& scope)
{
- while (ReadElementUpToClosing("lighting")) {
- const std::string& s = GetElementName();
- if (s == "directionallight") {
- scope.light = ReadDirectionalLight();
- }
- else if (s == "ambient") {
- LogWarn("ignoring <ambient> tag");
- }
- else if (s == "spheremap") {
- LogWarn("ignoring <spheremap> tag");
- }
- }
+ while (ReadElementUpToClosing("lighting")) {
+ const std::string& s = GetElementName();
+ if (s == "directionallight") {
+ scope.light = ReadDirectionalLight();
+ }
+ else if (s == "ambient") {
+ LogWarn("ignoring <ambient> tag");
+ }
+ else if (s == "spheremap") {
+ LogWarn("ignoring <spheremap> tag");
+ }
+ }
}
// ------------------------------------------------------------------------------------------------
aiLight* XGLImporter::ReadDirectionalLight()
{
- ScopeGuard<aiLight> l(new aiLight());
- l->mType = aiLightSource_DIRECTIONAL;
-
- while (ReadElementUpToClosing("directionallight")) {
- const std::string& s = GetElementName();
- if (s == "direction") {
- l->mDirection = ReadVec3();
- }
- else if (s == "diffuse") {
- l->mColorDiffuse = ReadCol3();
- }
- else if (s == "specular") {
- l->mColorSpecular = ReadCol3();
- }
- }
- return l.dismiss();
+ ScopeGuard<aiLight> l(new aiLight());
+ l->mType = aiLightSource_DIRECTIONAL;
+
+ while (ReadElementUpToClosing("directionallight")) {
+ const std::string& s = GetElementName();
+ if (s == "direction") {
+ l->mDirection = ReadVec3();
+ }
+ else if (s == "diffuse") {
+ l->mColorDiffuse = ReadCol3();
+ }
+ else if (s == "specular") {
+ l->mColorSpecular = ReadCol3();
+ }
+ }
+ return l.dismiss();
}
// ------------------------------------------------------------------------------------------------
aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag)
{
- ScopeGuard<aiNode> nd(new aiNode());
- std::vector<aiNode*> children;
- std::vector<unsigned int> meshes;
-
- try {
- while (skipFirst || ReadElementUpToClosing(closetag)) {
- skipFirst = false;
-
- const std::string& s = GetElementName();
- if (s == "mesh") {
- const size_t prev = scope.meshes_linear.size();
- if(ReadMesh(scope)) {
- const size_t newc = scope.meshes_linear.size();
- for(size_t i = 0; i < newc-prev; ++i) {
- meshes.push_back(static_cast<unsigned int>(i+prev));
- }
- }
- }
- else if (s == "mat") {
- ReadMaterial(scope);
- }
- else if (s == "object") {
- children.push_back(ReadObject(scope));
- }
- else if (s == "objectref") {
- // XXX
- }
- else if (s == "meshref") {
- const unsigned int id = static_cast<unsigned int>( ReadIndexFromText() );
-
- std::multimap<unsigned int, aiMesh*>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
- if (it == end) {
- ThrowException("<meshref> index out of range");
- }
-
- for(; it != end && (*it).first == id; ++it) {
- // ok, this is n^2 and should get optimized one day
- aiMesh* const m = (*it).second;
-
- unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
- for(; i < mcount; ++i) {
- if (scope.meshes_linear[i] == m) {
- meshes.push_back(i);
- break;
- }
- }
-
- ai_assert(i < mcount);
- }
- }
- else if (s == "transform") {
- nd->mTransformation = ReadTrafo();
- }
- }
-
- } catch(...) {
- BOOST_FOREACH(aiNode* ch, children) {
- delete ch;
- }
- throw;
- }
-
- // link meshes to node
- nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
- if (nd->mNumMeshes) {
- nd->mMeshes = new unsigned int[nd->mNumMeshes]();
- for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
- nd->mMeshes[i] = meshes[i];
- }
- }
-
- // link children to parent
- nd->mNumChildren = static_cast<unsigned int>(children.size());
- if (nd->mNumChildren) {
- nd->mChildren = new aiNode*[nd->mNumChildren]();
- for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
- nd->mChildren[i] = children[i];
- children[i]->mParent = nd;
- }
- }
-
- return nd.dismiss();
+ ScopeGuard<aiNode> nd(new aiNode());
+ std::vector<aiNode*> children;
+ std::vector<unsigned int> meshes;
+
+ try {
+ while (skipFirst || ReadElementUpToClosing(closetag)) {
+ skipFirst = false;
+
+ const std::string& s = GetElementName();
+ if (s == "mesh") {
+ const size_t prev = scope.meshes_linear.size();
+ if(ReadMesh(scope)) {
+ const size_t newc = scope.meshes_linear.size();
+ for(size_t i = 0; i < newc-prev; ++i) {
+ meshes.push_back(static_cast<unsigned int>(i+prev));
+ }
+ }
+ }
+ else if (s == "mat") {
+ ReadMaterial(scope);
+ }
+ else if (s == "object") {
+ children.push_back(ReadObject(scope));
+ }
+ else if (s == "objectref") {
+ // XXX
+ }
+ else if (s == "meshref") {
+ const unsigned int id = static_cast<unsigned int>( ReadIndexFromText() );
+
+ std::multimap<unsigned int, aiMesh*>::iterator it = scope.meshes.find(id), end = scope.meshes.end();
+ if (it == end) {
+ ThrowException("<meshref> index out of range");
+ }
+
+ for(; it != end && (*it).first == id; ++it) {
+ // ok, this is n^2 and should get optimized one day
+ aiMesh* const m = (*it).second;
+
+ unsigned int i = 0, mcount = static_cast<unsigned int>(scope.meshes_linear.size());
+ for(; i < mcount; ++i) {
+ if (scope.meshes_linear[i] == m) {
+ meshes.push_back(i);
+ break;
+ }
+ }
+
+ ai_assert(i < mcount);
+ }
+ }
+ else if (s == "transform") {
+ nd->mTransformation = ReadTrafo();
+ }
+ }
+
+ } catch(...) {
+ for(aiNode* ch : children) {
+ delete ch;
+ }
+ throw;
+ }
+
+ // FIX: since we used std::multimap<> to keep meshes by id, mesh order now depends on the behaviour
+ // of the multimap implementation with respect to the ordering of entries with same values.
+ // C++11 gives the guarantee that it uses insertion order, before it is implementation-specific.
+ // Sort by material id to always guarantee a deterministic result.
+ std::sort(meshes.begin(), meshes.end(), SortMeshByMaterialId(scope));
+
+ // link meshes to node
+ nd->mNumMeshes = static_cast<unsigned int>(meshes.size());
+ if (nd->mNumMeshes) {
+ nd->mMeshes = new unsigned int[nd->mNumMeshes]();
+ for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
+ nd->mMeshes[i] = meshes[i];
+ }
+ }
+
+ // link children to parent
+ nd->mNumChildren = static_cast<unsigned int>(children.size());
+ if (nd->mNumChildren) {
+ nd->mChildren = new aiNode*[nd->mNumChildren]();
+ for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
+ nd->mChildren[i] = children[i];
+ children[i]->mParent = nd;
+ }
+ }
+
+ return nd.dismiss();
}
// ------------------------------------------------------------------------------------------------
aiMatrix4x4 XGLImporter::ReadTrafo()
{
- aiVector3D forward, up, right, position;
- float scale = 1.0f;
-
- while (ReadElementUpToClosing("transform")) {
- const std::string& s = GetElementName();
- if (s == "forward") {
- forward = ReadVec3();
- }
- else if (s == "up") {
- up = ReadVec3();
- }
- else if (s == "position") {
- position = ReadVec3();
- }
- if (s == "scale") {
- scale = ReadFloat();
- if(scale < 0.f) {
- // this is wrong, but we can leave the value and pass it to the caller
- LogError("found negative scaling in <transform>, ignoring");
- }
- }
- }
-
- aiMatrix4x4 m;
- if(forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
- LogError("A direction vector in <transform> is zero, ignoring trafo");
- return m;
- }
-
- forward.Normalize();
- up.Normalize();
-
- right = forward ^ up;
- if (std::fabs(up * forward) > 1e-4) {
- // this is definitely wrong - a degenerate coordinate space ruins everything
- // so subtitute identity transform.
- LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
- return m;
- }
-
- right *= scale;
- up *= scale;
- forward *= scale;
-
- m.a1 = right.x;
- m.b1 = right.y;
- m.c1 = right.z;
-
- m.a2 = up.x;
- m.b2 = up.y;
- m.c2 = up.z;
-
- m.a3 = forward.x;
- m.b3 = forward.y;
- m.c3 = forward.z;
-
- m.a4 = position.x;
- m.b4 = position.y;
- m.c4 = position.z;
-
- return m;
+ aiVector3D forward, up, right, position;
+ float scale = 1.0f;
+
+ while (ReadElementUpToClosing("transform")) {
+ const std::string& s = GetElementName();
+ if (s == "forward") {
+ forward = ReadVec3();
+ }
+ else if (s == "up") {
+ up = ReadVec3();
+ }
+ else if (s == "position") {
+ position = ReadVec3();
+ }
+ if (s == "scale") {
+ scale = ReadFloat();
+ if(scale < 0.f) {
+ // this is wrong, but we can leave the value and pass it to the caller
+ LogError("found negative scaling in <transform>, ignoring");
+ }
+ }
+ }
+
+ aiMatrix4x4 m;
+ if(forward.SquareLength() < 1e-4 || up.SquareLength() < 1e-4) {
+ LogError("A direction vector in <transform> is zero, ignoring trafo");
+ return m;
+ }
+
+ forward.Normalize();
+ up.Normalize();
+
+ right = forward ^ up;
+ if (fabs(up * forward) > 1e-4) {
+ // this is definitely wrong - a degenerate coordinate space ruins everything
+ // so substitute identity transform.
+ LogError("<forward> and <up> vectors in <transform> are skewing, ignoring trafo");
+ return m;
+ }
+
+ right *= scale;
+ up *= scale;
+ forward *= scale;
+
+ m.a1 = right.x;
+ m.b1 = right.y;
+ m.c1 = right.z;
+
+ m.a2 = up.x;
+ m.b2 = up.y;
+ m.c2 = up.z;
+
+ m.a3 = forward.x;
+ m.b3 = forward.y;
+ m.c3 = forward.z;
+
+ m.a4 = position.x;
+ m.b4 = position.y;
+ m.c4 = position.z;
+
+ return m;
}
// ------------------------------------------------------------------------------------------------
aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m)
{
- ScopeGuard<aiMesh> mesh(new aiMesh());
-
- mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
- mesh->mVertices = new aiVector3D[mesh->mNumVertices];
- std::copy(m.positions.begin(),m.positions.end(),mesh->mVertices);
-
- if(m.normals.size()) {
- mesh->mNormals = new aiVector3D[mesh->mNumVertices];
- std::copy(m.normals.begin(),m.normals.end(),mesh->mNormals);
- }
-
- if(m.uvs.size()) {
- mesh->mNumUVComponents[0] = 2;
- mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
-
- for(unsigned int i = 0; i < mesh->mNumVertices; ++i) {
- mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x,m.uvs[i].y,0.f);
- }
- }
-
- mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
- mesh->mFaces = new aiFace[m.vcounts.size()];
-
- unsigned int idx = 0;
- for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
- aiFace& f = mesh->mFaces[i];
- f.mNumIndices = m.vcounts[i];
- f.mIndices = new unsigned int[f.mNumIndices];
- for(unsigned int c = 0; c < f.mNumIndices; ++c) {
- f.mIndices[c] = idx++;
- }
- }
-
- ai_assert(idx == mesh->mNumVertices);
-
- mesh->mPrimitiveTypes = m.pflags;
- mesh->mMaterialIndex = m.matid;
- return mesh.dismiss();
+ ScopeGuard<aiMesh> mesh(new aiMesh());
+
+ mesh->mNumVertices = static_cast<unsigned int>(m.positions.size());
+ mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+ std::copy(m.positions.begin(),m.positions.end(),mesh->mVertices);
+
+ if(m.normals.size()) {
+ mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+ std::copy(m.normals.begin(),m.normals.end(),mesh->mNormals);
+ }
+
+ if(m.uvs.size()) {
+ mesh->mNumUVComponents[0] = 2;
+ mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+
+ for(unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+ mesh->mTextureCoords[0][i] = aiVector3D(m.uvs[i].x,m.uvs[i].y,0.f);
+ }
+ }
+
+ mesh->mNumFaces = static_cast<unsigned int>(m.vcounts.size());
+ mesh->mFaces = new aiFace[m.vcounts.size()];
+
+ unsigned int idx = 0;
+ for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+ aiFace& f = mesh->mFaces[i];
+ f.mNumIndices = m.vcounts[i];
+ f.mIndices = new unsigned int[f.mNumIndices];
+ for(unsigned int c = 0; c < f.mNumIndices; ++c) {
+ f.mIndices[c] = idx++;
+ }
+ }
+
+ ai_assert(idx == mesh->mNumVertices);
+
+ mesh->mPrimitiveTypes = m.pflags;
+ mesh->mMaterialIndex = m.matid;
+ return mesh.dismiss();
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadMesh(TempScope& scope)
{
- TempMesh t;
-
- std::map<unsigned int, TempMaterialMesh> bymat;
- const unsigned int mesh_id = ReadIDAttr();
-
- while (ReadElementUpToClosing("mesh")) {
- const std::string& s = GetElementName();
-
- if (s == "mat") {
- ReadMaterial(scope);
- }
- else if (s == "p") {
- if (!reader->getAttributeValue("ID")) {
- LogWarn("no ID attribute on <p>, ignoring");
- }
- else {
- int id = reader->getAttributeValueAsInt("ID");
- t.points[id] = ReadVec3();
- }
- }
- else if (s == "n") {
- if (!reader->getAttributeValue("ID")) {
- LogWarn("no ID attribute on <n>, ignoring");
- }
- else {
- int id = reader->getAttributeValueAsInt("ID");
- t.normals[id] = ReadVec3();
- }
- }
- else if (s == "tc") {
- if (!reader->getAttributeValue("ID")) {
- LogWarn("no ID attribute on <tc>, ignoring");
- }
- else {
- int id = reader->getAttributeValueAsInt("ID");
- t.uvs[id] = ReadVec2();
- }
- }
- else if (s == "f" || s == "l" || s == "p") {
- const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
-
- unsigned int mid = ~0u;
- TempFace tf[3];
- bool has[3] = {0};
-
- while (ReadElementUpToClosing(s.c_str())) {
- const std::string& s = GetElementName();
- if (s == "fv1" || s == "lv1" || s == "pv1") {
- ReadFaceVertex(t,tf[0]);
- has[0] = true;
- }
- else if (s == "fv2" || s == "lv2") {
- ReadFaceVertex(t,tf[1]);
- has[1] = true;
- }
- else if (s == "fv3") {
- ReadFaceVertex(t,tf[2]);
- has[2] = true;
- }
- else if (s == "mat") {
- if (mid != ~0u) {
- LogWarn("only one material tag allowed per <f>");
- }
- mid = ResolveMaterialRef(scope);
- }
- else if (s == "matref") {
- if (mid != ~0u) {
- LogWarn("only one material tag allowed per <f>");
- }
- mid = ResolveMaterialRef(scope);
- }
- }
-
- if (mid == ~0u) {
- ThrowException("missing material index");
- }
-
- bool nor = false;
- bool uv = false;
- for(unsigned int i = 0; i < vcount; ++i) {
- if (!has[i]) {
- ThrowException("missing face vertex data");
- }
-
- nor = nor || tf[i].has_normal;
- uv = uv || tf[i].has_uv;
- }
-
- if (mid >= (1<<30)) {
- LogWarn("material indices exhausted, this may cause errors in the output");
- }
- unsigned int meshId = mid | ((nor?1:0)<<31) | ((uv?1:0)<<30);
-
- TempMaterialMesh& mesh = bymat[meshId];
- mesh.matid = mid;
-
- for(unsigned int i = 0; i < vcount; ++i) {
- mesh.positions.push_back(tf[i].pos);
- if(nor) {
- mesh.normals.push_back(tf[i].normal);
- }
- if(uv) {
- mesh.uvs.push_back(tf[i].uv);
- }
-
- mesh.pflags |= 1 << (vcount-1);
- }
-
- mesh.vcounts.push_back(vcount);
- }
- }
-
- // finally extract output meshes and add them to the scope
- typedef std::pair<unsigned int, TempMaterialMesh> pairt;
- BOOST_FOREACH(const pairt& p, bymat) {
- aiMesh* const m = ToOutputMesh(p.second);
- scope.meshes_linear.push_back(m);
-
- // if this is a definition, keep it on the stack
- if(mesh_id != ~0u) {
- scope.meshes.insert(std::pair<unsigned int, aiMesh*>(mesh_id,m));
- }
- }
-
- // no id == not a reference, insert this mesh right *here*
- return mesh_id == ~0u;
+ TempMesh t;
+
+ std::map<unsigned int, TempMaterialMesh> bymat;
+ const unsigned int mesh_id = ReadIDAttr();
+
+ while (ReadElementUpToClosing("mesh")) {
+ const std::string& s = GetElementName();
+
+ if (s == "mat") {
+ ReadMaterial(scope);
+ }
+ else if (s == "p") {
+ if (!reader->getAttributeValue("ID")) {
+ LogWarn("no ID attribute on <p>, ignoring");
+ }
+ else {
+ int id = reader->getAttributeValueAsInt("ID");
+ t.points[id] = ReadVec3();
+ }
+ }
+ else if (s == "n") {
+ if (!reader->getAttributeValue("ID")) {
+ LogWarn("no ID attribute on <n>, ignoring");
+ }
+ else {
+ int id = reader->getAttributeValueAsInt("ID");
+ t.normals[id] = ReadVec3();
+ }
+ }
+ else if (s == "tc") {
+ if (!reader->getAttributeValue("ID")) {
+ LogWarn("no ID attribute on <tc>, ignoring");
+ }
+ else {
+ int id = reader->getAttributeValueAsInt("ID");
+ t.uvs[id] = ReadVec2();
+ }
+ }
+ else if (s == "f" || s == "l" || s == "p") {
+ const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
+
+ unsigned int mid = ~0u;
+ TempFace tf[3];
+ bool has[3] = {0};
+
+ while (ReadElementUpToClosing(s.c_str())) {
+ const std::string& s = GetElementName();
+ if (s == "fv1" || s == "lv1" || s == "pv1") {
+ ReadFaceVertex(t,tf[0]);
+ has[0] = true;
+ }
+ else if (s == "fv2" || s == "lv2") {
+ ReadFaceVertex(t,tf[1]);
+ has[1] = true;
+ }
+ else if (s == "fv3") {
+ ReadFaceVertex(t,tf[2]);
+ has[2] = true;
+ }
+ else if (s == "mat") {
+ if (mid != ~0u) {
+ LogWarn("only one material tag allowed per <f>");
+ }
+ mid = ResolveMaterialRef(scope);
+ }
+ else if (s == "matref") {
+ if (mid != ~0u) {
+ LogWarn("only one material tag allowed per <f>");
+ }
+ mid = ResolveMaterialRef(scope);
+ }
+ }
+
+ if (mid == ~0u) {
+ ThrowException("missing material index");
+ }
+
+ bool nor = false;
+ bool uv = false;
+ for(unsigned int i = 0; i < vcount; ++i) {
+ if (!has[i]) {
+ ThrowException("missing face vertex data");
+ }
+
+ nor = nor || tf[i].has_normal;
+ uv = uv || tf[i].has_uv;
+ }
+
+ if (mid >= (1<<30)) {
+ LogWarn("material indices exhausted, this may cause errors in the output");
+ }
+ unsigned int meshId = mid | ((nor?1:0)<<31) | ((uv?1:0)<<30);
+
+ TempMaterialMesh& mesh = bymat[meshId];
+ mesh.matid = mid;
+
+ for(unsigned int i = 0; i < vcount; ++i) {
+ mesh.positions.push_back(tf[i].pos);
+ if(nor) {
+ mesh.normals.push_back(tf[i].normal);
+ }
+ if(uv) {
+ mesh.uvs.push_back(tf[i].uv);
+ }
+
+ mesh.pflags |= 1 << (vcount-1);
+ }
+
+ mesh.vcounts.push_back(vcount);
+ }
+ }
+
+ // finally extract output meshes and add them to the scope
+ typedef std::pair<unsigned int, TempMaterialMesh> pairt;
+ for(const pairt& p : bymat) {
+ aiMesh* const m = ToOutputMesh(p.second);
+ scope.meshes_linear.push_back(m);
+
+ // if this is a definition, keep it on the stack
+ if(mesh_id != ~0u) {
+ scope.meshes.insert(std::pair<unsigned int, aiMesh*>(mesh_id,m));
+ }
+ }
+
+ // no id == not a reference, insert this mesh right *here*
+ return mesh_id == ~0u;
}
// ----------------------------------------------------------------------------------------------
unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope)
{
- const std::string& s = GetElementName();
- if (s == "mat") {
- ReadMaterial(scope);
- return scope.materials_linear.size()-1;
- }
-
- const int id = ReadIndexFromText();
-
- std::map<unsigned int, aiMaterial*>::iterator it = scope.materials.find(id), end = scope.materials.end();
- if (it == end) {
- ThrowException("<matref> index out of range");
- }
-
- // ok, this is n^2 and should get optimized one day
- aiMaterial* const m = (*it).second;
-
- unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
- for(; i < mcount; ++i) {
- if (scope.materials_linear[i] == m) {
- return i;
- }
- }
-
- ai_assert(false);
- return 0;
+ const std::string& s = GetElementName();
+ if (s == "mat") {
+ ReadMaterial(scope);
+ return scope.materials_linear.size()-1;
+ }
+
+ const int id = ReadIndexFromText();
+
+ std::map<unsigned int, aiMaterial*>::iterator it = scope.materials.find(id), end = scope.materials.end();
+ if (it == end) {
+ ThrowException("<matref> index out of range");
+ }
+
+ // ok, this is n^2 and should get optimized one day
+ aiMaterial* const m = (*it).second;
+
+ unsigned int i = 0, mcount = static_cast<unsigned int>(scope.materials_linear.size());
+ for(; i < mcount; ++i) {
+ if (scope.materials_linear[i] == m) {
+ return i;
+ }
+ }
+
+ ai_assert(false);
+ return 0;
}
// ------------------------------------------------------------------------------------------------
void XGLImporter::ReadMaterial(TempScope& scope)
{
- const unsigned int mat_id = ReadIDAttr();
-
- ScopeGuard<aiMaterial> mat(new aiMaterial());
- while (ReadElementUpToClosing("mat")) {
- const std::string& s = GetElementName();
- if (s == "amb") {
- const aiColor3D c = ReadCol3();
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
- }
- else if (s == "diff") {
- const aiColor3D c = ReadCol3();
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
- }
- else if (s == "spec") {
- const aiColor3D c = ReadCol3();
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
- }
- else if (s == "emiss") {
- const aiColor3D c = ReadCol3();
- mat->AddProperty(&c,1,AI_MATKEY_COLOR_EMISSIVE);
- }
- else if (s == "alpha") {
- const float f = ReadFloat();
- mat->AddProperty(&f,1,AI_MATKEY_OPACITY);
- }
- else if (s == "shine") {
- const float f = ReadFloat();
- mat->AddProperty(&f,1,AI_MATKEY_SHININESS);
- }
- }
-
- scope.materials[mat_id] = mat;
- scope.materials_linear.push_back(mat.dismiss());
+ const unsigned int mat_id = ReadIDAttr();
+
+ ScopeGuard<aiMaterial> mat(new aiMaterial());
+ while (ReadElementUpToClosing("mat")) {
+ const std::string& s = GetElementName();
+ if (s == "amb") {
+ const aiColor3D c = ReadCol3();
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
+ }
+ else if (s == "diff") {
+ const aiColor3D c = ReadCol3();
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
+ }
+ else if (s == "spec") {
+ const aiColor3D c = ReadCol3();
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
+ }
+ else if (s == "emiss") {
+ const aiColor3D c = ReadCol3();
+ mat->AddProperty(&c,1,AI_MATKEY_COLOR_EMISSIVE);
+ }
+ else if (s == "alpha") {
+ const float f = ReadFloat();
+ mat->AddProperty(&f,1,AI_MATKEY_OPACITY);
+ }
+ else if (s == "shine") {
+ const float f = ReadFloat();
+ mat->AddProperty(&f,1,AI_MATKEY_SHININESS);
+ }
+ }
+
+ scope.materials[mat_id] = mat;
+ scope.materials_linear.push_back(mat.dismiss());
}
// ----------------------------------------------------------------------------------------------
void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out)
{
- const std::string& end = GetElementName();
-
- bool havep = false;
- while (ReadElementUpToClosing(end.c_str())) {
- const std::string& s = GetElementName();
- if (s == "pref") {
- const unsigned int id = ReadIndexFromText();
- std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
- if (it == t.points.end()) {
- ThrowException("point index out of range");
- }
-
- out.pos = (*it).second;
- havep = true;
- }
- else if (s == "nref") {
- const unsigned int id = ReadIndexFromText();
- std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
- if (it == t.normals.end()) {
- ThrowException("normal index out of range");
- }
-
- out.normal = (*it).second;
- out.has_normal = true;
- }
- else if (s == "tcref") {
- const unsigned int id = ReadIndexFromText();
- std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
- if (it == t.uvs.end()) {
- ThrowException("uv index out of range");
- }
-
- out.uv = (*it).second;
- out.has_uv = true;
- }
- else if (s == "p") {
- out.pos = ReadVec3();
- }
- else if (s == "n") {
- out.normal = ReadVec3();
- }
- else if (s == "tc") {
- out.uv = ReadVec2();
- }
- }
-
- if (!havep) {
- ThrowException("missing <pref> in <fvN> element");
- }
+ const std::string& end = GetElementName();
+
+ bool havep = false;
+ while (ReadElementUpToClosing(end.c_str())) {
+ const std::string& s = GetElementName();
+ if (s == "pref") {
+ const unsigned int id = ReadIndexFromText();
+ std::map<unsigned int, aiVector3D>::const_iterator it = t.points.find(id);
+ if (it == t.points.end()) {
+ ThrowException("point index out of range");
+ }
+
+ out.pos = (*it).second;
+ havep = true;
+ }
+ else if (s == "nref") {
+ const unsigned int id = ReadIndexFromText();
+ std::map<unsigned int, aiVector3D>::const_iterator it = t.normals.find(id);
+ if (it == t.normals.end()) {
+ ThrowException("normal index out of range");
+ }
+
+ out.normal = (*it).second;
+ out.has_normal = true;
+ }
+ else if (s == "tcref") {
+ const unsigned int id = ReadIndexFromText();
+ std::map<unsigned int, aiVector2D>::const_iterator it = t.uvs.find(id);
+ if (it == t.uvs.end()) {
+ ThrowException("uv index out of range");
+ }
+
+ out.uv = (*it).second;
+ out.has_uv = true;
+ }
+ else if (s == "p") {
+ out.pos = ReadVec3();
+ }
+ else if (s == "n") {
+ out.normal = ReadVec3();
+ }
+ else if (s == "tc") {
+ out.uv = ReadVec2();
+ }
+ }
+
+ if (!havep) {
+ ThrowException("missing <pref> in <fvN> element");
+ }
}
// ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIDAttr()
{
- for(int i = 0, e = reader->getAttributeCount(); i < e; ++i) {
-
- if(!ASSIMP_stricmp(reader->getAttributeName(i),"id")) {
- return reader->getAttributeValueAsInt(i);
- }
- }
- return ~0u;
+ for(int i = 0, e = reader->getAttributeCount(); i < e; ++i) {
+
+ if(!ASSIMP_stricmp(reader->getAttributeName(i),"id")) {
+ return reader->getAttributeValueAsInt(i);
+ }
+ }
+ return ~0u;
}
// ------------------------------------------------------------------------------------------------
float XGLImporter::ReadFloat()
{
- if(!SkipToText()) {
- LogError("unexpected EOF reading float element contents");
- return 0.f;
- }
- const char* s = reader->getNodeData(), *se;
-
- if(!SkipSpaces(&s)) {
- LogError("unexpected EOL, failed to parse float");
- return 0.f;
- }
-
- float t;
- se = fast_atoreal_move(s,t);
-
- if (se == s) {
- LogError("failed to read float text");
- return 0.f;
- }
-
- return t;
+ if(!SkipToText()) {
+ LogError("unexpected EOF reading float element contents");
+ return 0.f;
+ }
+ const char* s = reader->getNodeData(), *se;
+
+ if(!SkipSpaces(&s)) {
+ LogError("unexpected EOL, failed to parse float");
+ return 0.f;
+ }
+
+ float t;
+ se = fast_atoreal_move(s,t);
+
+ if (se == s) {
+ LogError("failed to read float text");
+ return 0.f;
+ }
+
+ return t;
}
// ------------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadIndexFromText()
{
- if(!SkipToText()) {
- LogError("unexpected EOF reading index element contents");
- return ~0u;
- }
- const char* s = reader->getNodeData(), *se;
- if(!SkipSpaces(&s)) {
- LogError("unexpected EOL, failed to parse index element");
- return ~0u;
- }
-
- const unsigned int t = strtoul10(s,&se);
-
- if (se == s) {
- LogError("failed to read index");
- return ~0u;
- }
-
- return t;
+ if(!SkipToText()) {
+ LogError("unexpected EOF reading index element contents");
+ return ~0u;
+ }
+ const char* s = reader->getNodeData(), *se;
+ if(!SkipSpaces(&s)) {
+ LogError("unexpected EOL, failed to parse index element");
+ return ~0u;
+ }
+
+ const unsigned int t = strtoul10(s,&se);
+
+ if (se == s) {
+ LogError("failed to read index");
+ return ~0u;
+ }
+
+ return t;
}
// ------------------------------------------------------------------------------------------------
aiVector2D XGLImporter::ReadVec2()
{
- aiVector2D vec;
-
- if(!SkipToText()) {
- LogError("unexpected EOF reading vec2 contents");
- return vec;
- }
- const char* s = reader->getNodeData();
-
- for(int i = 0; i < 2; ++i) {
- if(!SkipSpaces(&s)) {
- LogError("unexpected EOL, failed to parse vec2");
- return vec;
- }
- vec[i] = fast_atof(&s);
-
- SkipSpaces(&s);
- if (i != 1 && *s != ',') {
- LogError("expected comma, failed to parse vec2");
- return vec;
- }
- ++s;
- }
-
- return vec;
+ aiVector2D vec;
+
+ if(!SkipToText()) {
+ LogError("unexpected EOF reading vec2 contents");
+ return vec;
+ }
+ const char* s = reader->getNodeData();
+
+ for(int i = 0; i < 2; ++i) {
+ if(!SkipSpaces(&s)) {
+ LogError("unexpected EOL, failed to parse vec2");
+ return vec;
+ }
+ vec[i] = fast_atof(&s);
+
+ SkipSpaces(&s);
+ if (i != 1 && *s != ',') {
+ LogError("expected comma, failed to parse vec2");
+ return vec;
+ }
+ ++s;
+ }
+
+ return vec;
}
// ------------------------------------------------------------------------------------------------
aiVector3D XGLImporter::ReadVec3()
{
- aiVector3D vec;
-
- if(!SkipToText()) {
- LogError("unexpected EOF reading vec3 contents");
- return vec;
- }
- const char* s = reader->getNodeData();
-
- for(int i = 0; i < 3; ++i) {
- if(!SkipSpaces(&s)) {
- LogError("unexpected EOL, failed to parse vec3");
- return vec;
- }
- vec[i] = fast_atof(&s);
-
- SkipSpaces(&s);
- if (i != 2 && *s != ',') {
- LogError("expected comma, failed to parse vec3");
- return vec;
- }
- ++s;
- }
-
- return vec;
+ aiVector3D vec;
+
+ if(!SkipToText()) {
+ LogError("unexpected EOF reading vec3 contents");
+ return vec;
+ }
+ const char* s = reader->getNodeData();
+
+ for(int i = 0; i < 3; ++i) {
+ if(!SkipSpaces(&s)) {
+ LogError("unexpected EOL, failed to parse vec3");
+ return vec;
+ }
+ vec[i] = fast_atof(&s);
+
+ SkipSpaces(&s);
+ if (i != 2 && *s != ',') {
+ LogError("expected comma, failed to parse vec3");
+ return vec;
+ }
+ ++s;
+ }
+
+ return vec;
}
// ------------------------------------------------------------------------------------------------
aiColor3D XGLImporter::ReadCol3()
{
- const aiVector3D& v = ReadVec3();
- if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
- LogWarn("color values out of range, ignoring");
- }
- return aiColor3D(v.x,v.y,v.z);
+ const aiVector3D& v = ReadVec3();
+ if (v.x < 0.f || v.x > 1.0f || v.y < 0.f || v.y > 1.0f || v.z < 0.f || v.z > 1.0f) {
+ LogWarn("color values out of range, ignoring");
+ }
+ return aiColor3D(v.x,v.y,v.z);
}
-#endif
+#endif
diff --git a/src/3rdparty/assimp/code/XGLLoader.h b/src/3rdparty/assimp/code/XGLLoader.h
index c7d18d43b..757f9d564 100644
--- a/src/3rdparty/assimp/code/XGLLoader.h
+++ b/src/3rdparty/assimp/code/XGLLoader.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ following conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -47,8 +47,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h"
#include "irrXMLWrapper.h"
#include "LogAux.h"
+#include <assimp/material.h>
+#include <assimp/Importer.hpp>
+#include <assimp/mesh.h>
+#include <assimp/light.h>
-namespace Assimp {
+struct aiNode;
+
+namespace Assimp {
// ---------------------------------------------------------------------------
/** XGL/ZGL importer.
@@ -59,139 +65,150 @@ class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter>
{
public:
- XGLImporter();
- ~XGLImporter();
+ XGLImporter();
+ ~XGLImporter();
public:
- // -------------------------------------------------------------------
- /** Returns whether the class can handle the format of the given file.
- * See BaseImporter::CanRead() for details. */
- bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
- bool checkSig) const;
+ // -------------------------------------------------------------------
+ /** Returns whether the class can handle the format of the given file.
+ * See BaseImporter::CanRead() for details. */
+ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+ bool checkSig) const;
protected:
- // -------------------------------------------------------------------
- /** Return importer meta information.
- * See #BaseImporter::GetInfo for the details */
- const aiImporterDesc* GetInfo () const;
+ // -------------------------------------------------------------------
+ /** Return importer meta information.
+ * See #BaseImporter::GetInfo for the details */
+ const aiImporterDesc* GetInfo () const;
- // -------------------------------------------------------------------
- /** Imports the given file into the given scene structure.
- * See BaseImporter::InternReadFile() for details */
- void InternReadFile( const std::string& pFile, aiScene* pScene,
- IOSystem* pIOHandler);
+ // -------------------------------------------------------------------
+ /** Imports the given file into the given scene structure.
+ * See BaseImporter::InternReadFile() for details */
+ void InternReadFile( const std::string& pFile, aiScene* pScene,
+ IOSystem* pIOHandler);
private:
- struct TempScope
- {
- TempScope()
- : light()
- {}
-
- ~TempScope()
- {
- BOOST_FOREACH(aiMesh* m, meshes_linear) {
- delete m;
- }
-
- BOOST_FOREACH(aiMaterial* m, materials_linear) {
- delete m;
- }
-
- delete light;
- }
-
- void dismiss() {
- light = NULL;
- meshes_linear.clear();
- materials_linear.clear();
- meshes.clear();
- materials.clear();
- }
-
- std::multimap<unsigned int, aiMesh*> meshes;
- std::map<unsigned int, aiMaterial*> materials;
-
- std::vector<aiMesh*> meshes_linear;
- std::vector<aiMaterial*> materials_linear;
-
- aiLight* light;
- };
-
- struct TempMesh
- {
- std::map<unsigned int, aiVector3D> points;
- std::map<unsigned int, aiVector3D> normals;
- std::map<unsigned int, aiVector2D> uvs;
- };
-
- struct TempMaterialMesh
- {
- TempMaterialMesh()
- : pflags()
- , matid()
- {}
-
- std::vector<aiVector3D> positions, normals;
- std::vector<aiVector2D> uvs;
-
- std::vector<unsigned int> vcounts;
- unsigned int pflags;
- unsigned int matid;
- };
-
- struct TempFace
- {
- TempFace()
- : has_uv()
- , has_normal()
- {}
-
- aiVector3D pos;
- aiVector3D normal;
- aiVector2D uv;
- bool has_uv;
- bool has_normal;
- };
+
+ struct TempScope
+ {
+ TempScope()
+ : light()
+ {}
+
+ ~TempScope()
+ {
+ for(aiMesh* m : meshes_linear) {
+ delete m;
+ }
+
+ for(aiMaterial* m : materials_linear) {
+ delete m;
+ }
+
+ delete light;
+ }
+
+ void dismiss() {
+ light = NULL;
+ meshes_linear.clear();
+ materials_linear.clear();
+ meshes.clear();
+ materials.clear();
+ }
+
+ std::multimap<unsigned int, aiMesh*> meshes;
+ std::map<unsigned int, aiMaterial*> materials;
+
+ std::vector<aiMesh*> meshes_linear;
+ std::vector<aiMaterial*> materials_linear;
+
+ aiLight* light;
+ };
+
+
+ struct SortMeshByMaterialId {
+ SortMeshByMaterialId(const TempScope& scope) : scope(scope) {}
+ bool operator()(unsigned int a, unsigned int b) const {
+ return scope.meshes_linear[a]->mMaterialIndex < scope.meshes_linear[b]->mMaterialIndex;
+ };
+
+ const TempScope& scope;
+ };
+
+ struct TempMesh
+ {
+ std::map<unsigned int, aiVector3D> points;
+ std::map<unsigned int, aiVector3D> normals;
+ std::map<unsigned int, aiVector2D> uvs;
+ };
+
+ struct TempMaterialMesh
+ {
+ TempMaterialMesh()
+ : pflags()
+ , matid()
+ {}
+
+ std::vector<aiVector3D> positions, normals;
+ std::vector<aiVector2D> uvs;
+
+ std::vector<unsigned int> vcounts;
+ unsigned int pflags;
+ unsigned int matid;
+ };
+
+ struct TempFace
+ {
+ TempFace()
+ : has_uv()
+ , has_normal()
+ {}
+
+ aiVector3D pos;
+ aiVector3D normal;
+ aiVector2D uv;
+ bool has_uv;
+ bool has_normal;
+ };
private:
- void Cleanup();
-
- std::string GetElementName();
- bool ReadElement();
- bool ReadElementUpToClosing(const char* closetag);
- bool SkipToText();
- unsigned int ReadIDAttr();
-
- void ReadWorld(TempScope& scope);
- void ReadLighting(TempScope& scope);
- aiLight* ReadDirectionalLight();
- aiNode* ReadObject(TempScope& scope,bool skipFirst = false,const char* closetag = "object");
- bool ReadMesh(TempScope& scope);
- void ReadMaterial(TempScope& scope);
- aiVector2D ReadVec2();
- aiVector3D ReadVec3();
- aiColor3D ReadCol3();
- aiMatrix4x4 ReadTrafo();
- unsigned int ReadIndexFromText();
- float ReadFloat();
-
- aiMesh* ToOutputMesh(const TempMaterialMesh& m);
- void ReadFaceVertex(const TempMesh& t, TempFace& out);
- unsigned int ResolveMaterialRef(TempScope& scope);
+ void Cleanup();
+
+ std::string GetElementName();
+ bool ReadElement();
+ bool ReadElementUpToClosing(const char* closetag);
+ bool SkipToText();
+ unsigned int ReadIDAttr();
+
+ void ReadWorld(TempScope& scope);
+ void ReadLighting(TempScope& scope);
+ aiLight* ReadDirectionalLight();
+ aiNode* ReadObject(TempScope& scope,bool skipFirst = false,const char* closetag = "object");
+ bool ReadMesh(TempScope& scope);
+ void ReadMaterial(TempScope& scope);
+ aiVector2D ReadVec2();
+ aiVector3D ReadVec3();
+ aiColor3D ReadCol3();
+ aiMatrix4x4 ReadTrafo();
+ unsigned int ReadIndexFromText();
+ float ReadFloat();
+
+ aiMesh* ToOutputMesh(const TempMaterialMesh& m);
+ void ReadFaceVertex(const TempMesh& t, TempFace& out);
+ unsigned int ResolveMaterialRef(TempScope& scope);
private:
private:
- irr::io::IrrXMLReader* reader;
- aiScene* scene;
+ irr::io::IrrXMLReader* reader;
+ aiScene* scene;
};
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/XMLTools.h b/src/3rdparty/assimp/code/XMLTools.h
new file mode 100644
index 000000000..7339a2fc8
--- /dev/null
+++ b/src/3rdparty/assimp/code/XMLTools.h
@@ -0,0 +1,81 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef INCLUDED_ASSIMP_XML_TOOLS_H
+#define INCLUDED_ASSIMP_XML_TOOLS_H
+
+#include <string>
+
+namespace Assimp {
+ // XML escape the 5 XML special characters (",',<,> and &) in |data|
+ // Based on http://stackoverflow.com/questions/5665231
+ std::string XMLEscape(const std::string& data) {
+ std::string buffer;
+
+ const size_t size = data.size();
+ buffer.reserve(size + size / 8);
+ for(size_t i = 0; i < size; ++i) {
+ const char c = data[i];
+ switch(c) {
+ case '&' :
+ buffer.append("&amp;");
+ break;
+ case '\"':
+ buffer.append("&quot;");
+ break;
+ case '\'':
+ buffer.append("&apos;");
+ break;
+ case '<' :
+ buffer.append("&lt;");
+ break;
+ case '>' :
+ buffer.append("&gt;");
+ break;
+ default:
+ buffer.append(&c, 1);
+ break;
+ }
+ }
+ return buffer;
+ }
+}
+
+#endif // INCLUDED_ASSIMP_XML_TOOLS_H
diff --git a/src/3rdparty/assimp/code/assbin_chunks.h b/src/3rdparty/assimp/code/assbin_chunks.h
index 9a2333700..15e4af5e7 100644
--- a/src/3rdparty/assimp/code/assbin_chunks.h
+++ b/src/3rdparty/assimp/code/assbin_chunks.h
@@ -1,11 +1,10 @@
-
#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
@@ -21,7 +20,7 @@ the 'aiScene' data structure returned by the APIs. The focus for the binary form
(<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
+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
@@ -47,7 +46,7 @@ in <tt>&lt;root&gt;/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo
-------------------------------------------------------------------------------
----------------------
-| Header (500 bytes) |
+| Header (512 bytes) |
----------------------
| Variable chunks |
----------------------
@@ -56,76 +55,77 @@ in <tt>&lt;root&gt;/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo
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.
+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
+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.
+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
+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
+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
+integer Assimp compile flags
-short 0 for normal files, 1 for shortened dumps for regression tests
+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
+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
+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] length-of-chunk bytes of data, depending on the chunk type
+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 length-of-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),
+ 1. POD members (i.e. aiMesh::mPrimitiveTypes, aiMesh::mNumVertices),
in order of declaration.
- 2. Array-members (aiMesh::mFaces, aiMesh::mVertices, aiBone::mWeights),
+ 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
+ 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:
+ 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).
+ a ASSBIN_CHUNK_AINODE subchunk following 1.) and 2.) (which is
+ empty for aiScene).
[[aiMesh]]
@@ -133,18 +133,18 @@ The general 'rule' to get from Assimp headers to the serialized layout is:
[number of used uv channels times]
integer mNumUVComponents[n]
- float mTextureCoords[n][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. Unlike the in-memory format, only the used components of the
- UV coordinates are written to disk. If mNumUVComponents[0] is 1, the
- corresponding mTextureCoords array consists of mNumTextureCoords*1
- single floats.
+ -> 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.
+ - 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]]
@@ -171,26 +171,26 @@ The general 'rule' to get from Assimp headers to the serialized layout is:
#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)
+#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
diff --git a/src/3rdparty/assimp/code/fast_atof.h b/src/3rdparty/assimp/code/fast_atof.h
index 3cdb1e81f..f65d72ae0 100644
--- a/src/3rdparty/assimp/code/fast_atof.h
+++ b/src/3rdparty/assimp/code/fast_atof.h
@@ -15,29 +15,40 @@
#ifndef __FAST_A_TO_F_H_INCLUDED__
#define __FAST_A_TO_F_H_INCLUDED__
-#include <math.h>
-#include <limits.h>
+#include <cmath>
+#include <limits>
+#include <stdint.h>
+#include <stdexcept>
+
+#include "StringComparison.h"
+
+
+#ifdef _MSC_VER
+# include <stdint.h>
+#else
+# include <assimp/Compiler/pstdint.h>
+#endif
namespace Assimp
{
-const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
- 0.0,
- 0.1,
- 0.01,
- 0.001,
- 0.0001,
- 0.00001,
- 0.000001,
- 0.0000001,
- 0.00000001,
- 0.000000001,
- 0.0000000001,
- 0.00000000001,
- 0.000000000001,
- 0.0000000000001,
- 0.00000000000001,
- 0.000000000000001
+const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug
+ 0.0,
+ 0.1,
+ 0.01,
+ 0.001,
+ 0.0001,
+ 0.00001,
+ 0.000001,
+ 0.0000001,
+ 0.00000001,
+ 0.000000001,
+ 0.0000000001,
+ 0.00000000001,
+ 0.000000000001,
+ 0.0000000000001,
+ 0.00000000000001,
+ 0.000000000000001
};
@@ -46,19 +57,19 @@ const double fast_atof_table[16] = { // we write [16] here instead of [] to wor
// ------------------------------------------------------------------------------------
inline unsigned int strtoul10( const char* in, const char** out=0)
{
- unsigned int value = 0;
-
- bool running = true;
- while ( running )
- {
- if ( *in < '0' || *in > '9' )
- break;
-
- value = ( value * 10 ) + ( *in - '0' );
- ++in;
- }
- if (out)*out = in;
- return value;
+ unsigned int value = 0;
+
+ bool running = true;
+ while ( running )
+ {
+ if ( *in < '0' || *in > '9' )
+ break;
+
+ value = ( value * 10 ) + ( *in - '0' );
+ ++in;
+ }
+ if (out)*out = in;
+ return value;
}
// ------------------------------------------------------------------------------------
@@ -66,19 +77,19 @@ inline unsigned int strtoul10( const char* in, const char** out=0)
// ------------------------------------------------------------------------------------
inline unsigned int strtoul8( const char* in, const char** out=0)
{
- unsigned int value = 0;
-
- bool running = true;
- while ( running )
- {
- if ( *in < '0' || *in > '7' )
- break;
-
- value = ( value << 3 ) + ( *in - '0' );
- ++in;
- }
- if (out)*out = in;
- return value;
+ unsigned int value = 0;
+
+ bool running = true;
+ while ( running )
+ {
+ if ( *in < '0' || *in > '7' )
+ break;
+
+ value = ( value << 3 ) + ( *in - '0' );
+ ++in;
+ }
+ if (out)*out = in;
+ return value;
}
// ------------------------------------------------------------------------------------
@@ -86,28 +97,28 @@ inline unsigned int strtoul8( const char* in, const char** out=0)
// ------------------------------------------------------------------------------------
inline unsigned int strtoul16( const char* in, const char** out=0)
{
- unsigned int value = 0;
-
- bool running = true;
- while ( running )
- {
- if ( *in >= '0' && *in <= '9' )
- {
- value = ( value << 4u ) + ( *in - '0' );
- }
- else if (*in >= 'A' && *in <= 'F')
- {
- value = ( value << 4u ) + ( *in - 'A' ) + 10;
- }
- else if (*in >= 'a' && *in <= 'f')
- {
- value = ( value << 4u ) + ( *in - 'a' ) + 10;
- }
- else break;
- ++in;
- }
- if (out)*out = in;
- return value;
+ unsigned int value = 0;
+
+ bool running = true;
+ while ( running )
+ {
+ if ( *in >= '0' && *in <= '9' )
+ {
+ value = ( value << 4u ) + ( *in - '0' );
+ }
+ else if (*in >= 'A' && *in <= 'F')
+ {
+ value = ( value << 4u ) + ( *in - 'A' ) + 10;
+ }
+ else if (*in >= 'a' && *in <= 'f')
+ {
+ value = ( value << 4u ) + ( *in - 'a' ) + 10;
+ }
+ else break;
+ ++in;
+ }
+ if (out)*out = in;
+ return value;
}
// ------------------------------------------------------------------------------------
@@ -116,18 +127,18 @@ inline unsigned int strtoul16( const char* in, const char** out=0)
// ------------------------------------------------------------------------------------
inline unsigned int HexDigitToDecimal(char in)
{
- unsigned int out = UINT_MAX;
- if (in >= '0' && in <= '9')
- out = in - '0';
+ unsigned int out = UINT_MAX;
+ if (in >= '0' && in <= '9')
+ out = in - '0';
- else if (in >= 'a' && in <= 'f')
- out = 10u + in - 'a';
+ else if (in >= 'a' && in <= 'f')
+ out = 10u + in - 'a';
- else if (in >= 'A' && in <= 'F')
- out = 10u + in - 'A';
+ else if (in >= 'A' && in <= 'F')
+ out = 10u + in - 'A';
- // return value is UINT_MAX if the input is not a hex digit
- return out;
+ // return value is UINT_MAX if the input is not a hex digit
+ return out;
}
// ------------------------------------------------------------------------------------
@@ -135,7 +146,7 @@ inline unsigned int HexDigitToDecimal(char in)
// ------------------------------------------------------------------------------------
inline uint8_t HexOctetToDecimal(const char* in)
{
- return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]);
+ return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]);
}
@@ -144,15 +155,15 @@ inline uint8_t HexOctetToDecimal(const char* in)
// ------------------------------------------------------------------------------------
inline int strtol10( const char* in, const char** out=0)
{
- bool inv = (*in=='-');
- if (inv || *in=='+')
- ++in;
-
- int value = strtoul10(in,out);
- if (inv) {
- value = -value;
- }
- return value;
+ bool inv = (*in=='-');
+ if (inv || *in=='+')
+ ++in;
+
+ int value = strtoul10(in,out);
+ if (inv) {
+ value = -value;
+ }
+ return value;
}
// ------------------------------------------------------------------------------------
@@ -163,11 +174,11 @@ inline int strtol10( const char* in, const char** out=0)
// ------------------------------------------------------------------------------------
inline unsigned int strtoul_cppstyle( const char* in, const char** out=0)
{
- if ('0' == in[0])
- {
- return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out);
- }
- return strtoul10(in, out);
+ if ('0' == in[0])
+ {
+ return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out);
+ }
+ return strtoul10(in, out);
}
// ------------------------------------------------------------------------------------
@@ -176,48 +187,65 @@ inline unsigned int strtoul_cppstyle( const char* in, const char** out=0)
// ------------------------------------------------------------------------------------
inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0)
{
- unsigned int cur = 0;
- uint64_t value = 0;
-
- if ( *in < '0' || *in > '9' )
- throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
-
- bool running = true;
- while ( running )
- {
- if ( *in < '0' || *in > '9' )
- break;
-
- const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
-
- if (new_value < value) /* numeric overflow, we rely on you */
- throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
-
- value = new_value;
-
- ++in;
- ++cur;
-
- if (max_inout && *max_inout == cur) {
-
- if (out) { /* skip to end */
- while (*in >= '0' && *in <= '9')
- ++in;
- *out = in;
- }
-
- return value;
- }
- }
- if (out)
- *out = in;
-
- if (max_inout)
- *max_inout = cur;
-
- return value;
+ unsigned int cur = 0;
+ uint64_t value = 0;
+
+ if ( *in < '0' || *in > '9' )
+ throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
+
+ bool running = true;
+ while ( running )
+ {
+ if ( *in < '0' || *in > '9' )
+ break;
+
+ const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
+
+ if (new_value < value) /* numeric overflow, we rely on you */
+ throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
+
+ value = new_value;
+
+ ++in;
+ ++cur;
+
+ if (max_inout && *max_inout == cur) {
+
+ if (out) { /* skip to end */
+ while (*in >= '0' && *in <= '9')
+ ++in;
+ *out = in;
+ }
+
+ return value;
+ }
+ }
+ if (out)
+ *out = in;
+
+ if (max_inout)
+ *max_inout = cur;
+
+ return value;
+}
+
+// ------------------------------------------------------------------------------------
+// signed variant of strtoul10_64
+// ------------------------------------------------------------------------------------
+inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0)
+{
+ bool inv = (*in == '-');
+ if (inv || *in == '+')
+ ++in;
+
+ int64_t value = strtoul10_64(in, out, max_inout);
+ if (inv) {
+ value = -value;
+ }
+ return value;
}
+
// Number of relevant decimals for floating-point parsing.
#define AI_FAST_ATOF_RELAVANT_DECIMALS 15
@@ -227,111 +255,148 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
// ------------------------------------------------------------------------------------
template <typename Real>
-inline const char* fast_atoreal_move( const char* c, Real& out, bool check_comma = true)
+inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
{
- Real f;
-
- bool inv = (*c=='-');
- if (inv || *c=='+') {
- ++c;
- }
-
- f = static_cast<Real>( strtoul10_64 ( c, &c) );
- if (*c == '.' || (check_comma && c[0] == ',' && c[1] >= '0' && c[1] <= '9')) // allow for commas, too
- {
- ++c;
-
- // NOTE: The original implementation is highly inaccurate here. The precision of a single
- // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more
- // inaccurate than it would need to be. Casting to double seems to solve the problem.
- // strtol_64 is used to prevent integer overflow.
-
- // Another fix: this tends to become 0 for long numbers if we don't limit the maximum
- // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
- // 1 and 15.
- unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
- double pl = static_cast<double>( strtoul10_64 ( c, &c, &diff ));
-
- pl *= fast_atof_table[diff];
- f += static_cast<Real>( pl );
- }
-
- // A major 'E' must be allowed. Necessary for proper reading of some DXF files.
- // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
- if (*c == 'e' || *c == 'E') {
-
- ++c;
- const bool einv = (*c=='-');
- if (einv || *c=='+') {
- ++c;
- }
-
- // The reason float constants are used here is that we've seen cases where compilers
- // would perform such casts on compile-time constants at runtime, which would be
- // bad considering how frequently fast_atoreal_move<float> is called in Assimp.
- Real exp = static_cast<Real>( strtoul10_64(c, &c) );
- if (einv) {
- exp = -exp;
- }
- f *= std::pow(static_cast<Real>(10.0), exp);
- }
-
- if (inv) {
- f = -f;
- }
- out = f;
- return c;
+ Real f = 0;
+
+ bool inv = (*c == '-');
+ if (inv || *c == '+') {
+ ++c;
+ }
+
+ if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0)
+ {
+ out = std::numeric_limits<Real>::quiet_NaN();
+ c += 3;
+ return c;
+ }
+
+ if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0)
+ {
+ out = std::numeric_limits<Real>::infinity();
+ if (inv) {
+ out = -out;
+ }
+ c += 3;
+ if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0)
+ {
+ c += 5;
+ }
+ return c;
+ }
+
+ if (!(c[0] >= '0' && c[0] <= '9') &&
+ !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9'))
+ {
+ throw std::invalid_argument("Cannot parse string "
+ "as real number: does not start with digit "
+ "or decimal point followed by digit.");
+ }
+
+ if (*c != '.' && (! check_comma || c[0] != ','))
+ {
+ f = static_cast<Real>( strtoul10_64 ( c, &c) );
+ }
+
+ if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')
+ {
+ ++c;
+
+ // NOTE: The original implementation is highly inaccurate here. The precision of a single
+ // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more
+ // inaccurate than it would need to be. Casting to double seems to solve the problem.
+ // strtol_64 is used to prevent integer overflow.
+
+ // Another fix: this tends to become 0 for long numbers if we don't limit the maximum
+ // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
+ // 1 and 15.
+ unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
+ double pl = static_cast<double>( strtoul10_64 ( c, &c, &diff ));
+
+ pl *= fast_atof_table[diff];
+ f += static_cast<Real>( pl );
+ }
+ // For backwards compatibility: eat trailing dots, but not trailing commas.
+ else if (*c == '.') {
+ ++c;
+ }
+
+ // A major 'E' must be allowed. Necessary for proper reading of some DXF files.
+ // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
+ if (*c == 'e' || *c == 'E') {
+
+ ++c;
+ const bool einv = (*c=='-');
+ if (einv || *c=='+') {
+ ++c;
+ }
+
+ // The reason float constants are used here is that we've seen cases where compilers
+ // would perform such casts on compile-time constants at runtime, which would be
+ // bad considering how frequently fast_atoreal_move<float> is called in Assimp.
+ Real exp = static_cast<Real>( strtoul10_64(c, &c) );
+ if (einv) {
+ exp = -exp;
+ }
+ f *= std::pow(static_cast<Real>(10.0), exp);
+ }
+
+ if (inv) {
+ f = -f;
+ }
+ out = f;
+ return c;
}
// ------------------------------------------------------------------------------------
// The same but more human.
inline float fast_atof(const char* c)
{
- float ret;
- fast_atoreal_move<float>(c, ret);
- return ret;
+ float ret;
+ fast_atoreal_move<float>(c, ret);
+ return ret;
}
inline float fast_atof( const char* c, const char** cout)
{
- float ret;
- *cout = fast_atoreal_move<float>(c, ret);
+ float ret;
+ *cout = fast_atoreal_move<float>(c, ret);
- return ret;
+ return ret;
}
inline float fast_atof( const char** inout)
{
- float ret;
- *inout = fast_atoreal_move<float>(*inout, ret);
+ float ret;
+ *inout = fast_atoreal_move<float>(*inout, ret);
- return ret;
+ return ret;
}
inline double fast_atod(const char* c)
{
- double ret;
- fast_atoreal_move<double>(c, ret);
- return ret;
+ double ret;
+ fast_atoreal_move<double>(c, ret);
+ return ret;
}
inline double fast_atod( const char* c, const char** cout)
{
- double ret;
- *cout = fast_atoreal_move<double>(c, ret);
+ double ret;
+ *cout = fast_atoreal_move<double>(c, ret);
- return ret;
+ return ret;
}
inline double fast_atod( const char** inout)
{
- double ret;
- *inout = fast_atoreal_move<double>(*inout, ret);
+ double ret;
+ *inout = fast_atoreal_move<double>(*inout, ret);
- return ret;
+ return ret;
}
} // end of namespace Assimp
diff --git a/src/3rdparty/assimp/code/glTFAsset.h b/src/3rdparty/assimp/code/glTFAsset.h
new file mode 100644
index 000000000..f2d375c6b
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFAsset.h
@@ -0,0 +1,964 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file glTFAsset.h
+ * Declares a glTF class to handle gltf/glb files
+ *
+ * glTF Extensions Support:
+ * KHR_binary_glTF: full
+ * KHR_materials_common: full
+ */
+#ifndef glTFAsset_H_INC
+#define glTFAsset_H_INC
+
+#include <map>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+
+#define RAPIDJSON_HAS_STDSTRING 1
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/document.h>
+#include <rapidjson/error/en.h>
+
+#ifdef ASSIMP_API
+# include <memory>
+# include "DefaultIOSystem.h"
+# include "ByteSwapper.h"
+#else
+# include <memory>
+# define AI_SWAP4(p)
+# define ai_assert
+#endif
+
+
+#if _MSC_VER > 1500 || (defined __GNUC___)
+# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+# else
+# define gltf_unordered_map map
+#endif
+
+#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+# include <unordered_map>
+# if _MSC_VER > 1600
+# define gltf_unordered_map unordered_map
+# else
+# define gltf_unordered_map tr1::unordered_map
+# endif
+#endif
+
+namespace glTF
+{
+#ifdef ASSIMP_API
+ using Assimp::IOStream;
+ using Assimp::IOSystem;
+ using std::shared_ptr;
+#else
+ using std::shared_ptr;
+
+ typedef std::runtime_error DeadlyImportError;
+ typedef std::runtime_error DeadlyExportError;
+
+ enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 };
+ class IOSystem;
+ class IOStream
+ {
+ FILE* f;
+ public:
+ IOStream(FILE* file) : f(file) {}
+ ~IOStream() { fclose(f); f = 0; }
+
+ size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
+ size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
+ int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
+ size_t Tell() const { return ftell(f); }
+
+ size_t FileSize() {
+ long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
+ return size_t((Seek(p, aiOrigin_SET), len));
+ }
+ };
+#endif
+
+ using rapidjson::Value;
+ using rapidjson::Document;
+
+ class Asset;
+ class AssetWriter;
+
+ struct BufferView; // here due to cross-reference
+ struct Texture;
+ struct Light;
+
+
+ // Vec/matrix types, as raw float arrays
+ typedef float (vec3)[3];
+ typedef float (vec4)[4];
+ typedef float (mat4)[16];
+
+
+ namespace Util
+ {
+ void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
+
+ size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
+ inline size_t DecodeBase64(const char* in, uint8_t*& out)
+ {
+ return DecodeBase64(in, strlen(in), out);
+ }
+
+ struct DataURI
+ {
+ const char* mediaType;
+ const char* charset;
+ bool base64;
+ const char* data;
+ size_t dataLength;
+ };
+
+ //! Check if a uri is a data URI
+ inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out);
+ }
+
+
+ //! Magic number for GLB files
+ #define AI_GLB_MAGIC_NUMBER "glTF"
+
+ #ifdef ASSIMP_API
+ #include "./../include/assimp/Compiler/pushpack1.h"
+ #endif
+
+ //! For the KHR_binary_glTF extension (binary .glb file)
+ //! 20-byte header (+ the JSON + a "body" data section)
+ struct GLB_Header
+ {
+ uint8_t magic[4]; //!< Magic number: "glTF"
+ uint32_t version; //!< Version number (always 1 as of the last update)
+ uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
+ uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
+ uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
+ } PACK_STRUCT;
+
+ #ifdef ASSIMP_API
+ #include "./../include/assimp/Compiler/poppack1.h"
+ #endif
+
+
+ //! Values for the GLB_Header::sceneFormat field
+ enum SceneFormat
+ {
+ SceneFormat_JSON = 0
+ };
+
+ //! Values for the mesh primitive modes
+ enum PrimitiveMode
+ {
+ PrimitiveMode_POINTS = 0,
+ PrimitiveMode_LINES = 1,
+ PrimitiveMode_LINE_LOOP = 2,
+ PrimitiveMode_LINE_STRIP = 3,
+ PrimitiveMode_TRIANGLES = 4,
+ PrimitiveMode_TRIANGLE_STRIP = 5,
+ PrimitiveMode_TRIANGLE_FAN = 6
+ };
+
+ //! Values for the Accessor::componentType field
+ enum ComponentType
+ {
+ ComponentType_BYTE = 5120,
+ ComponentType_UNSIGNED_BYTE = 5121,
+ ComponentType_SHORT = 5122,
+ ComponentType_UNSIGNED_SHORT = 5123,
+ ComponentType_FLOAT = 5126
+ };
+
+ inline unsigned int ComponentTypeSize(ComponentType t)
+ {
+ switch (t) {
+ case ComponentType_SHORT:
+ case ComponentType_UNSIGNED_SHORT:
+ return 2;
+
+ case ComponentType_FLOAT:
+ return 4;
+
+ //case Accessor::ComponentType_BYTE:
+ //case Accessor::ComponentType_UNSIGNED_BYTE:
+ default:
+ return 1;
+ }
+ }
+
+ //! Values for the BufferView::target field
+ enum BufferViewTarget
+ {
+ BufferViewTarget_ARRAY_BUFFER = 34962,
+ BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
+ };
+
+ //! Values for the Texture::format and Texture::internalFormat fields
+ enum TextureFormat
+ {
+ TextureFormat_ALPHA = 6406,
+ TextureFormat_RGB = 6407,
+ TextureFormat_RGBA = 6408,
+ TextureFormat_LUMINANCE = 6409,
+ TextureFormat_LUMINANCE_ALPHA = 6410
+ };
+
+ //! Values for the Texture::target field
+ enum TextureTarget
+ {
+ TextureTarget_TEXTURE_2D = 3553
+ };
+
+ //! Values for the Texture::type field
+ enum TextureType
+ {
+ TextureType_UNSIGNED_BYTE = 5121,
+ TextureType_UNSIGNED_SHORT_5_6_5 = 33635,
+ TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819,
+ TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820
+ };
+
+
+ //! Values for the Accessor::type field (helper class)
+ class AttribType
+ {
+ public:
+ enum Value
+ { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 };
+
+ private:
+ static const size_t NUM_VALUES = static_cast<size_t>(MAT4)+1;
+
+ struct Info
+ { const char* name; unsigned int numComponents; };
+
+ template<int N> struct data
+ { static const Info infos[NUM_VALUES]; };
+
+ public:
+ inline static Value FromString(const char* str)
+ {
+ for (size_t i = 0; i < NUM_VALUES; ++i) {
+ if (strcmp(data<0>::infos[i].name, str) == 0) {
+ return static_cast<Value>(i);
+ }
+ }
+ return SCALAR;
+ }
+
+ inline static const char* ToString(Value type)
+ {
+ return data<0>::infos[static_cast<size_t>(type)].name;
+ }
+
+ inline static unsigned int GetNumComponents(Value type)
+ {
+ return data<0>::infos[static_cast<size_t>(type)].numComponents;
+ }
+ };
+
+ // must match the order of the AttribTypeTraits::Value enum!
+ template<int N> const AttribType::Info
+ AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
+ { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
+ };
+
+
+
+ //! A reference to one top-level object, which is valid
+ //! until the Asset instance is destroyed
+ template<class T>
+ class Ref
+ {
+ std::vector<T*>* vector;
+ unsigned int index;
+
+ public:
+ Ref() : vector(0), index(0) {}
+ Ref(std::vector<T*>& vec, unsigned int idx) : vector(&vec), index(idx) {}
+
+ inline unsigned int GetIndex() const
+ { return index; }
+
+ operator bool() const
+ { return vector != 0; }
+
+ T* operator->()
+ { return (*vector)[index]; }
+
+ T& operator*()
+ { return *((*vector)[index]); }
+ };
+
+ //! Helper struct to represent values that might not be present
+ template<class T>
+ struct Nullable
+ {
+ T value;
+ bool isPresent;
+
+ Nullable() : isPresent(false) {}
+ Nullable(T& val) : value(val), isPresent(true) {}
+ };
+
+
+ //! Base classe for all glTF top-level objects
+ struct Object
+ {
+ std::string id; //!< The globally unique ID used to reference this object
+ std::string name; //!< The user-defined name of this object
+
+ //! Objects marked as special are not exported (used to emulate the binary body buffer)
+ virtual bool IsSpecial() const
+ { return false; }
+
+ virtual ~Object() {}
+
+ //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
+ static const char* TranslateId(Asset& r, const char* id)
+ { return id; }
+ };
+
+
+
+ //
+ // Classes for each glTF top-level object type
+ //
+
+ //! A typed view into a BufferView. A BufferView contains raw binary data.
+ //! An accessor provides a typed view into a BufferView or a subset of a BufferView
+ // !similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
+ struct Accessor : public Object
+ {
+ Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
+ unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
+ unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
+ ComponentType componentType; //!< The datatype of components in the attribute. (required)
+ unsigned int count; //!< The number of attributes referenced by this accessor. (required)
+ AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
+ //std::vector<float> max; //!< Maximum value of each component in this attribute.
+ //std::vector<float> min; //!< Minimum value of each component in this attribute.
+
+ unsigned int GetNumComponents();
+ unsigned int GetBytesPerComponent();
+ unsigned int GetElementSize();
+
+ inline uint8_t* GetPointer();
+
+ template<class T>
+ bool ExtractData(T*& outData);
+
+ void WriteData(size_t count, const void* src_buffer, size_t src_stride);
+
+ //! Helper class to iterate the data
+ class Indexer
+ {
+ friend struct Accessor;
+
+ Accessor& accessor;
+ uint8_t* data;
+ size_t elemSize, stride;
+
+ Indexer(Accessor& acc);
+
+ public:
+
+ //! Accesses the i-th value as defined by the accessor
+ template<class T>
+ T GetValue(int i);
+
+ //! Accesses the i-th value as defined by the accessor
+ inline unsigned int GetUInt(int i)
+ {
+ return GetValue<unsigned int>(i);
+ }
+
+ inline bool IsValid() const
+ {
+ return data != 0;
+ }
+ };
+
+ inline Indexer GetIndexer()
+ {
+ return Indexer(*this);
+ }
+
+ Accessor() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ struct Animation : public Object
+ {
+ struct Channel
+ {
+
+ };
+
+ struct Target
+ {
+
+ };
+
+ struct Sampler
+ {
+
+ };
+ };
+
+ //! A buffer points to binary geometry, animation, or skins.
+ struct Buffer : public Object
+ {
+ public:
+
+ enum Type
+ {
+ Type_arraybuffer,
+ Type_text
+ };
+
+ //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
+ size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
+ //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
+
+ Type type;
+
+ private:
+ shared_ptr<uint8_t> mData; //!< Pointer to the data
+ bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
+
+ public:
+ Buffer();
+
+ void Read(Value& obj, Asset& r);
+
+ bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0);
+
+ size_t AppendData(uint8_t* data, size_t length);
+ void Grow(size_t amount);
+
+ uint8_t* GetPointer()
+ { return mData.get(); }
+
+ void MarkAsSpecial()
+ { mIsSpecial = true; }
+
+ bool IsSpecial() const
+ { return mIsSpecial; }
+
+ static const char* TranslateId(Asset& r, const char* id);
+ };
+
+
+ //! A view into a buffer generally representing a subset of the buffer.
+ struct BufferView : public Object
+ {
+ Ref<Buffer> buffer; //! The ID of the buffer. (required)
+ size_t byteOffset; //! The offset into the buffer in bytes. (required)
+ size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
+
+ BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
+
+ BufferView() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ struct Camera : public Object
+ {
+ enum Type
+ {
+ Perspective,
+ Orthographic
+ };
+
+ Type type;
+
+ union
+ {
+ struct {
+ float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
+ float yfov; //!<The floating - point vertical field of view in radians. (required)
+ float zfar; //!<The floating - point distance to the far clipping plane. (required)
+ float znear; //!< The floating - point distance to the near clipping plane. (required)
+ } perspective;
+
+ struct {
+ float xmag; //! The floating-point horizontal magnification of the view. (required)
+ float ymag; //! The floating-point vertical magnification of the view. (required)
+ float zfar; //! The floating-point distance to the far clipping plane. (required)
+ float znear; //! The floating-point distance to the near clipping plane. (required)
+ } ortographic;
+ };
+
+ Camera() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ //! Image data used to create a texture.
+ struct Image : public Object
+ {
+ std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
+
+ Ref<BufferView> bufferView;
+
+ std::string mimeType;
+
+ int width, height;
+
+ private:
+ uint8_t* mData;
+ size_t mDataLength;
+
+ public:
+
+ Image();
+ void Read(Value& obj, Asset& r);
+
+ inline bool HasData() const
+ { return mDataLength > 0; }
+
+ inline size_t GetDataLength() const
+ { return mDataLength; }
+
+ inline const uint8_t* GetData() const
+ { return mData; }
+
+ inline uint8_t* StealData();
+
+ inline void SetData(uint8_t* data, size_t length, Asset& r);
+ };
+
+ //! Holds a material property that can be a texture or a color
+ struct TexProperty
+ {
+ Ref<Texture> texture;
+ vec4 color;
+ };
+
+ //! The material appearance of a primitive.
+ struct Material : public Object
+ {
+ //Ref<Sampler> source; //!< The ID of the technique.
+ //std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values.
+
+ //! Techniques defined by KHR_materials_common
+ enum Technique
+ {
+ Technique_undefined = 0,
+ Technique_BLINN,
+ Technique_PHONG,
+ Technique_LAMBERT,
+ Technique_CONSTANT
+ };
+
+ TexProperty ambient;
+ TexProperty diffuse;
+ TexProperty specular;
+ TexProperty emission;
+
+ bool doubleSided;
+ bool transparent;
+ float transparency;
+ float shininess;
+
+ Technique technique;
+
+ Material() { SetDefaults(); }
+ void Read(Value& obj, Asset& r);
+ void SetDefaults();
+ };
+
+ //! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene.
+ struct Mesh : public Object
+ {
+ typedef std::vector< Ref<Accessor> > AccessorList;
+
+ struct Primitive
+ {
+ PrimitiveMode mode;
+
+ struct Attributes {
+ AccessorList position, normal, texcoord, color, joint, jointmatrix, weight;
+ } attributes;
+
+ Ref<Accessor> indices;
+
+ Ref<Material> material;
+ };
+
+ std::vector<Primitive> primitives;
+
+ Mesh() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Node : public Object
+ {
+ std::vector< Ref<Node> > children;
+ std::vector< Ref<Mesh> > meshes;
+
+ Nullable<mat4> matrix;
+ Nullable<vec3> translation;
+ Nullable<vec4> rotation;
+ Nullable<vec3> scale;
+
+ Ref<Camera> camera;
+ Ref<Light> light;
+
+ Node() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Program : public Object
+ {
+ Program() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ struct Sampler : public Object
+ {
+ Sampler() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Scene : public Object
+ {
+ std::vector< Ref<Node> > nodes;
+
+ Scene() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Shader : public Object
+ {
+ Shader() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Skin : public Object
+ {
+ Skin() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ struct Technique : public Object
+ {
+ struct Parameters
+ {
+
+ };
+
+ struct States
+ {
+
+ };
+
+ struct Functions
+ {
+
+ };
+
+ Technique() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+ //! A texture and its sampler.
+ struct Texture : public Object
+ {
+ //Ref<Sampler> source; //!< The ID of the sampler used by this texture. (required)
+ Ref<Image> source; //!< The ID of the image used by this texture. (required)
+
+ //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
+ //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
+
+ //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
+ //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
+
+ Texture() {}
+ void Read(Value& obj, Asset& r);
+ };
+
+
+ //! A light (from KHR_materials_common extension)
+ struct Light : public Object
+ {
+ enum Type
+ {
+ Type_undefined,
+ Type_ambient,
+ Type_directional,
+ Type_point,
+ Type_spot
+ };
+
+ Type type;
+
+ vec4 color;
+ float distance;
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float falloffAngle;
+ float falloffExponent;
+
+ Light() {}
+ void Read(Value& obj, Asset& r);
+
+ void SetDefaults();
+ };
+
+ //! Base class for LazyDict that acts as an interface
+ class LazyDictBase
+ {
+ public:
+ virtual ~LazyDictBase() {}
+
+ virtual void AttachToDocument(Document& doc) = 0;
+ virtual void DetachFromDocument() = 0;
+
+ virtual void WriteObjects(AssetWriter& writer) = 0;
+ };
+
+
+ template<class T>
+ class LazyDict;
+
+ //! (Implemented in glTFAssetWriter.h)
+ template<class T>
+ void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
+
+
+ //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
+ //! It is the owner the loaded objects, so when it is destroyed it also deletes them
+ template<class T>
+ class LazyDict : public LazyDictBase
+ {
+ friend class Asset;
+ friend class AssetWriter;
+
+ typedef typename std::gltf_unordered_map< std::string, unsigned int > Dict;
+
+ std::vector<T*> mObjs; //! The read objects
+ Dict mObjsById; //! The read objects accesible by id
+ const char* mDictId; //! ID of the dictionary object
+ const char* mExtId; //! ID of the extension defining the dictionary
+ Value* mDict; //! JSON dictionary object
+ Asset& mAsset; //! The asset instance
+
+ void AttachToDocument(Document& doc);
+ void DetachFromDocument();
+
+ void WriteObjects(AssetWriter& writer)
+ { WriteLazyDict<T>(*this, writer); }
+
+ Ref<T> Add(T* obj);
+
+ public:
+ LazyDict(Asset& asset, const char* dictId, const char* extId = 0);
+ ~LazyDict();
+
+ Ref<T> Get(const char* id);
+ Ref<T> Get(unsigned int i);
+
+ Ref<T> Create(const char* id);
+ Ref<T> Create(const std::string& id)
+ { return Create(id.c_str()); }
+
+ inline unsigned int Size() const
+ { return unsigned(mObjs.size()); }
+
+ inline T& operator[](size_t i)
+ { return *mObjs[i]; }
+
+ };
+
+
+ struct AssetMetadata
+ {
+ std::string copyright; //!< A copyright message suitable for display to credit the content creator.
+ std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
+ bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
+
+ struct {
+ std::string api; //!< Specifies the target rendering API (default: "WebGL")
+ std::string version; //!< Specifies the target rendering API (default: "1.0.3")
+ } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
+
+ int version; //!< The glTF format version (should be 1)
+
+ void Read(Document& doc);
+
+ AssetMetadata()
+ : premultipliedAlpha(false)
+ , version(0)
+ {
+ }
+ };
+
+ //
+ // glTF Asset class
+ //
+
+ //! Root object for a glTF asset
+ class Asset
+ {
+ typedef std::gltf_unordered_map<std::string, int> IdMap;
+
+ template<class T>
+ friend class LazyDict;
+
+ friend struct Buffer; // To access OpenFile
+
+ friend class AssetWriter;
+
+ private:
+ IOSystem* mIOSystem;
+
+ std::string mCurrentAssetDir;
+
+ size_t mSceneLength;
+ size_t mBodyOffset, mBodyLength;
+
+ std::vector<LazyDictBase*> mDicts;
+
+ IdMap mUsedIds;
+
+ Ref<Buffer> mBodyBuffer;
+
+ Asset(Asset&);
+ Asset& operator=(const Asset&);
+
+ public:
+
+ //! Keeps info about the enabled extensions
+ struct Extensions
+ {
+ bool KHR_binary_glTF;
+ bool KHR_materials_common;
+
+ } extensionsUsed;
+
+ AssetMetadata asset;
+
+
+ // Dictionaries for each type of object
+
+ LazyDict<Accessor> accessors;
+ LazyDict<Animation> animations;
+ LazyDict<Buffer> buffers;
+ LazyDict<BufferView> bufferViews;
+ LazyDict<Camera> cameras;
+ LazyDict<Image> images;
+ LazyDict<Material> materials;
+ LazyDict<Mesh> meshes;
+ LazyDict<Node> nodes;
+ //LazyDict<Program> programs;
+ //LazyDict<Sampler> samplers;
+ LazyDict<Scene> scenes;
+ //LazyDict<Shader> shaders;
+ //LazyDict<Skin> skins;
+ //LazyDict<Technique> techniques;
+ LazyDict<Texture> textures;
+
+ LazyDict<Light> lights; // KHR_materials_common ext
+
+ Ref<Scene> scene;
+
+ public:
+ Asset(IOSystem* io = 0)
+ : mIOSystem(io)
+ , asset()
+ , accessors (*this, "accessors")
+ , animations (*this, "animations")
+ , buffers (*this, "buffers")
+ , bufferViews (*this, "bufferViews")
+ , cameras (*this, "cameras")
+ , images (*this, "images")
+ , materials (*this, "materials")
+ , meshes (*this, "meshes")
+ , nodes (*this, "nodes")
+ //, programs (*this, "programs")
+ //, samplers (*this, "samplers")
+ , scenes (*this, "scenes")
+ //, shaders (*this, "shaders")
+ //, skins (*this, "skins")
+ //, techniques (*this, "techniques")
+ , textures (*this, "textures")
+ , lights (*this, "lights", "KHR_materials_common")
+ {
+ memset(&extensionsUsed, 0, sizeof(extensionsUsed));
+ }
+
+ //! Main function
+ void Load(const std::string& file, bool isBinary = false);
+
+ //! Enables the "KHR_binary_glTF" extension on the asset
+ void SetAsBinary();
+
+ //! Search for an available name, starting from the given strings
+ std::string FindUniqueID(const std::string& str, const char* suffix);
+
+ Ref<Buffer> GetBodyBuffer()
+ { return mBodyBuffer; }
+
+ private:
+ void ReadBinaryHeader(IOStream& stream);
+
+ void ReadExtensionsUsed(Document& doc);
+
+
+ IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
+ };
+
+}
+
+// Include the implementation of the methods
+#include "glTFAsset.inl"
+
+#endif
diff --git a/src/3rdparty/assimp/code/glTFAsset.inl b/src/3rdparty/assimp/code/glTFAsset.inl
new file mode 100644
index 000000000..d52c825c4
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFAsset.inl
@@ -0,0 +1,1269 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#include "StringUtils.h"
+
+namespace glTF {
+
+namespace {
+
+ //
+ // JSON Value reading helpers
+ //
+
+ template<class T>
+ struct ReadHelper { static bool Read(Value& val, T& out) {
+ return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
+ }};
+
+ template<> struct ReadHelper<bool> { static bool Read(Value& val, bool& out) {
+ return val.IsBool() ? out = val.GetBool(), true : false;
+ }};
+
+ template<> struct ReadHelper<float> { static bool Read(Value& val, float& out) {
+ return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
+ }};
+
+ template<unsigned int N> struct ReadHelper<float[N]> { static bool Read(Value& val, float (&out)[N]) {
+ if (!val.IsArray() || val.Size() != N) return false;
+ for (unsigned int i = 0; i < N; ++i) {
+ if (val[i].IsNumber())
+ out[i] = static_cast<float>(val[i].GetDouble());
+ }
+ return true;
+ }};
+
+ template<> struct ReadHelper<const char*> { static bool Read(Value& val, const char*& out) {
+ return val.IsString() ? (out = val.GetString(), true) : false;
+ }};
+
+ template<> struct ReadHelper<std::string> { static bool Read(Value& val, std::string& out) {
+ return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
+ }};
+
+ template<class T> struct ReadHelper< Nullable<T> > { static bool Read(Value& val, Nullable<T>& out) {
+ return out.isPresent = ReadHelper<T>::Read(val, out.value);
+ }};
+
+ template<class T>
+ inline static bool ReadValue(Value& val, T& out)
+ {
+ return ReadHelper<T>::Read(val, out);
+ }
+
+ template<class T>
+ inline static bool ReadMember(Value& obj, const char* id, T& out)
+ {
+ Value::MemberIterator it = obj.FindMember(id);
+ if (it != obj.MemberEnd()) {
+ return ReadHelper<T>::Read(it->value, out);
+ }
+ return false;
+ }
+
+ template<class T>
+ inline static T MemberOrDefault(Value& obj, const char* id, T defaultValue)
+ {
+ T out;
+ return ReadMember(obj, id, out) ? out : defaultValue;
+ }
+
+ inline Value* FindMember(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd()) ? &it->value : 0;
+ }
+
+ inline Value* FindString(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
+ }
+
+ inline Value* FindArray(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0;
+ }
+
+ inline Value* FindObject(Value& val, const char* id)
+ {
+ Value::MemberIterator it = val.FindMember(id);
+ return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0;
+ }
+}
+
+//
+// LazyDict methods
+//
+
+template<class T>
+inline LazyDict<T>::LazyDict(Asset& asset, const char* dictId, const char* extId)
+ : mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset)
+{
+ asset.mDicts.push_back(this); // register to the list of dictionaries
+}
+
+template<class T>
+inline LazyDict<T>::~LazyDict()
+{
+ for (size_t i = 0; i < mObjs.size(); ++i) {
+ delete mObjs[i];
+ }
+}
+
+
+template<class T>
+inline void LazyDict<T>::AttachToDocument(Document& doc)
+{
+ Value* container = 0;
+
+ if (mExtId) {
+ if (Value* exts = FindObject(doc, "extensions")) {
+ container = FindObject(*exts, mExtId);
+ }
+ }
+ else {
+ container = &doc;
+ }
+
+ if (container) {
+ mDict = FindObject(*container, mDictId);
+ }
+}
+
+template<class T>
+inline void LazyDict<T>::DetachFromDocument()
+{
+ mDict = 0;
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Get(unsigned int i)
+{
+ return Ref<T>(mObjs, i);
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Get(const char* id)
+{
+ id = T::TranslateId(mAsset, id);
+
+ typename Dict::iterator it = mObjsById.find(id);
+ if (it != mObjsById.end()) { // already created?
+ return Ref<T>(mObjs, it->second);
+ }
+
+ // read it from the JSON object
+ if (!mDict) {
+ throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\"");
+ }
+
+ Value::MemberIterator obj = mDict->FindMember(id);
+ if (obj == mDict->MemberEnd()) {
+ throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\"");
+ }
+ if (!obj->value.IsObject()) {
+ throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object");
+ }
+
+ // create an instance of the given type
+ T* inst = new T();
+ inst->id = id;
+ ReadMember(obj->value, "name", inst->name);
+ inst->Read(obj->value, mAsset);
+ return Add(inst);
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Add(T* obj)
+{
+ unsigned int idx = unsigned(mObjs.size());
+ mObjs.push_back(obj);
+ mObjsById[obj->id] = idx;
+ mAsset.mUsedIds[obj->id] = true;
+ return Ref<T>(mObjs, idx);
+}
+
+template<class T>
+Ref<T> LazyDict<T>::Create(const char* id)
+{
+ Asset::IdMap::iterator it = mAsset.mUsedIds.find(id);
+ if (it != mAsset.mUsedIds.end()) {
+ throw DeadlyImportError("GLTF: two objects with the same ID exist");
+ }
+ T* inst = new T();
+ inst->id = id;
+ return Add(inst);
+}
+
+
+//
+// glTF dictionary objects methods
+//
+
+
+inline Buffer::Buffer()
+: byteLength(0), type(Type_arraybuffer), mIsSpecial(false)
+{ }
+
+inline const char* Buffer::TranslateId(Asset& r, const char* id)
+{
+ // Compatibility with old spec
+ if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) {
+ return "binary_glTF";
+ }
+
+ return id;
+}
+
+inline void Buffer::Read(Value& obj, Asset& r)
+{
+ size_t statedLength = MemberOrDefault<size_t>(obj, "byteLength", 0);
+ byteLength = statedLength;
+
+ Value* it = FindString(obj, "uri");
+ if (!it) {
+ if (statedLength > 0) {
+ throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute");
+ }
+ return;
+ }
+
+ const char* uri = it->GetString();
+
+ Util::DataURI dataURI;
+ if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
+ if (dataURI.base64) {
+ uint8_t* data = 0;
+ this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
+ this->mData.reset(data);
+
+ if (statedLength > 0 && this->byteLength != statedLength) {
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + std::to_string(statedLength) +
+ " bytes, but found " + std::to_string(dataURI.dataLength));
+ }
+ }
+ else { // assume raw data
+ if (statedLength != dataURI.dataLength) {
+ throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + std::to_string(statedLength) +
+ " bytes, but found " + std::to_string(dataURI.dataLength));
+ }
+
+ this->mData.reset(new uint8_t[dataURI.dataLength]);
+ memcpy( this->mData.get(), dataURI.data, dataURI.dataLength );
+ }
+ }
+ else { // Local file
+ if (byteLength > 0) {
+ IOStream* file = r.OpenFile(uri, "rb");
+ if (file) {
+ bool ok = LoadFromStream(*file, byteLength);
+ delete file;
+
+ if (!ok)
+ throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" );
+ }
+ else {
+ throw DeadlyImportError("GLTF: could not open referenced file \"" + std::string(uri) + "\"");
+ }
+ }
+ }
+}
+
+inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseOffset)
+{
+ byteLength = length ? length : stream.FileSize();
+
+ if (baseOffset) {
+ stream.Seek(baseOffset, aiOrigin_SET);
+ }
+
+ mData.reset(new uint8_t[byteLength]);
+
+ if (stream.Read(mData.get(), byteLength, 1) != 1) {
+ return false;
+ }
+ return true;
+}
+
+inline size_t Buffer::AppendData(uint8_t* data, size_t length)
+{
+ size_t offset = this->byteLength;
+ Grow(length);
+ memcpy(mData.get() + offset, data, length);
+ return offset;
+}
+
+inline void Buffer::Grow(size_t amount)
+{
+ if (amount <= 0) return;
+ uint8_t* b = new uint8_t[byteLength + amount];
+ if (mData) memcpy(b, mData.get(), byteLength);
+ mData.reset(b);
+ byteLength += amount;
+}
+
+
+inline void BufferView::Read(Value& obj, Asset& r)
+{
+ const char* bufferId = MemberOrDefault<const char*>(obj, "buffer", 0);
+ if (bufferId) {
+ buffer = r.buffers.Get(bufferId);
+ }
+
+ byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
+ byteLength = MemberOrDefault(obj, "byteLength", 0u);
+}
+
+
+
+inline void Accessor::Read(Value& obj, Asset& r)
+{
+ const char* bufferViewId = MemberOrDefault<const char*>(obj, "bufferView", 0);
+ if (bufferViewId) {
+ bufferView = r.bufferViews.Get(bufferViewId);
+ }
+
+ byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
+ byteStride = MemberOrDefault(obj, "byteStride", 0u);
+ componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
+ count = MemberOrDefault(obj, "count", 0u);
+
+ const char* typestr;
+ type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR;
+}
+
+inline unsigned int Accessor::GetNumComponents()
+{
+ return AttribType::GetNumComponents(type);
+}
+
+inline unsigned int Accessor::GetBytesPerComponent()
+{
+ return int(ComponentTypeSize(componentType));
+}
+
+inline unsigned int Accessor::GetElementSize()
+{
+ return GetNumComponents() * GetBytesPerComponent();
+}
+
+inline uint8_t* Accessor::GetPointer()
+{
+ if (!bufferView || !bufferView->buffer) return 0;
+ uint8_t* basePtr = bufferView->buffer->GetPointer();
+ if (!basePtr) return 0;
+
+ size_t offset = byteOffset + bufferView->byteOffset;
+ return basePtr + offset;
+}
+
+namespace {
+ inline void CopyData(size_t count,
+ const uint8_t* src, size_t src_stride,
+ uint8_t* dst, size_t dst_stride)
+ {
+ if (src_stride == dst_stride) {
+ memcpy(dst, src, count * src_stride);
+ }
+ else {
+ size_t sz = std::min(src_stride, dst_stride);
+ for (size_t i = 0; i < count; ++i) {
+ memcpy(dst, src, sz);
+ if (sz < dst_stride) {
+ memset(dst + sz, 0, dst_stride - sz);
+ }
+ src += src_stride;
+ dst += dst_stride;
+ }
+ }
+ }
+}
+
+template<class T>
+bool Accessor::ExtractData(T*& outData)
+{
+ uint8_t* data = GetPointer();
+ if (!data) return false;
+
+ const size_t elemSize = GetElementSize();
+ const size_t totalSize = elemSize * count;
+
+ const size_t stride = byteStride ? byteStride : elemSize;
+
+ const size_t targetElemSize = sizeof(T);
+ ai_assert(elemSize <= targetElemSize);
+
+ ai_assert(count*stride <= bufferView->byteLength);
+
+ outData = new T[count];
+ if (stride == elemSize && targetElemSize == elemSize) {
+ memcpy(outData, data, totalSize);
+ }
+ else {
+ for (size_t i = 0; i < count; ++i) {
+ memcpy(outData + i, data + i*stride, elemSize);
+ }
+ }
+
+ return true;
+}
+
+inline void Accessor::WriteData(size_t count, const void* src_buffer, size_t src_stride)
+{
+ uint8_t* buffer_ptr = bufferView->buffer->GetPointer();
+ size_t offset = byteOffset + bufferView->byteOffset;
+
+ size_t dst_stride = GetNumComponents() * GetBytesPerComponent();
+
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(src_buffer);
+ uint8_t* dst = reinterpret_cast< uint8_t*>(buffer_ptr + offset);
+
+ ai_assert(dst + count*dst_stride <= buffer_ptr + bufferView->buffer->byteLength);
+ CopyData(count, src, src_stride, dst, dst_stride);
+}
+
+
+
+inline Accessor::Indexer::Indexer(Accessor& acc)
+ : accessor(acc)
+ , data(acc.GetPointer())
+ , elemSize(acc.GetElementSize())
+ , stride(acc.byteStride ? acc.byteStride : elemSize)
+{
+
+}
+
+//! Accesses the i-th value as defined by the accessor
+template<class T>
+T Accessor::Indexer::GetValue(int i)
+{
+ ai_assert(data);
+ ai_assert(i*stride < accessor.bufferView->byteLength);
+ T value = T();
+ memcpy(&value, data + i*stride, elemSize);
+ //value >>= 8 * (sizeof(T) - elemSize);
+ return value;
+}
+
+inline Image::Image()
+ : width(0)
+ , height(0)
+ , mData(0)
+ , mDataLength(0)
+{
+
+}
+
+inline void Image::Read(Value& obj, Asset& r)
+{
+ // Check for extensions first (to detect binary embedded data)
+ if (Value* extensions = FindObject(obj, "extensions")) {
+ if (r.extensionsUsed.KHR_binary_glTF) {
+ if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
+
+ width = MemberOrDefault(*ext, "width", 0);
+ height = MemberOrDefault(*ext, "height", 0);
+
+ ReadMember(*ext, "mimeType", mimeType);
+
+ const char* bufferViewId;
+ if (ReadMember(*ext, "bufferView", bufferViewId)) {
+ Ref<BufferView> bv = r.bufferViews.Get(bufferViewId);
+ if (bv) {
+ mDataLength = bv->byteLength;
+ mData = new uint8_t[mDataLength];
+ memcpy(mData, bv->buffer->GetPointer() + bv->byteOffset, mDataLength);
+ }
+ }
+ }
+ }
+ }
+
+ if (!mDataLength) {
+ if (Value* uri = FindString(obj, "uri")) {
+ const char* uristr = uri->GetString();
+
+ Util::DataURI dataURI;
+ if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
+ mimeType = dataURI.mediaType;
+ if (dataURI.base64) {
+ mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, mData);
+ }
+ }
+ else {
+ this->uri = uristr;
+ }
+ }
+ }
+}
+
+inline uint8_t* Image::StealData()
+{
+ uint8_t* data = mData;
+ mDataLength = 0;
+ mData = 0;
+ return data;
+}
+
+inline void Image::SetData(uint8_t* data, size_t length, Asset& r)
+{
+ Ref<Buffer> b = r.GetBodyBuffer();
+ if (b) { // binary file: append to body
+ std::string bvId = r.FindUniqueID(this->id, "imgdata");
+ bufferView = r.bufferViews.Create(bvId);
+
+ bufferView->buffer = b;
+ bufferView->byteLength = length;
+ bufferView->byteOffset = b->AppendData(data, length);
+ }
+ else { // text file: will be stored as a data uri
+ this->mData = data;
+ this->mDataLength = length;
+ }
+}
+
+inline void Texture::Read(Value& obj, Asset& r)
+{
+ const char* sourcestr;
+ if (ReadMember(obj, "source", sourcestr)) {
+ source = r.images.Get(sourcestr);
+ }
+}
+
+namespace {
+ inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out)
+ {
+ if (Value* prop = FindMember(vals, propName)) {
+ if (prop->IsString()) {
+ out.texture = r.textures.Get(prop->GetString());
+ }
+ else {
+ ReadValue(*prop, out.color);
+ }
+ }
+ }
+}
+
+inline void Material::Read(Value& material, Asset& r)
+{
+ SetDefaults();
+
+ if (Value* values = FindObject(material, "values")) {
+ ReadMaterialProperty(r, *values, "ambient", this->ambient);
+ ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
+ ReadMaterialProperty(r, *values, "specular", this->specular);
+
+ ReadMember(*values, "shininess", shininess);
+ }
+
+ if (Value* extensions = FindObject(material, "extensions")) {
+ if (r.extensionsUsed.KHR_materials_common) {
+ if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
+ if (Value* tnq = FindString(*ext, "technique")) {
+ const char* t = tnq->GetString();
+ if (strcmp(t, "BLINN") == 0) technique = Technique_BLINN;
+ else if (strcmp(t, "PHONG") == 0) technique = Technique_PHONG;
+ else if (strcmp(t, "LAMBERT") == 0) technique = Technique_LAMBERT;
+ else if (strcmp(t, "CONSTANT") == 0) technique = Technique_CONSTANT;
+ }
+
+ if (Value* values = FindObject(*ext, "values")) {
+ ReadMaterialProperty(r, *values, "ambient", this->ambient);
+ ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
+ ReadMaterialProperty(r, *values, "specular", this->specular);
+
+ ReadMember(*values, "doubleSided", doubleSided);
+ ReadMember(*values, "transparent", transparent);
+ ReadMember(*values, "transparency", transparency);
+ ReadMember(*values, "shininess", shininess);
+ }
+ }
+ }
+ }
+}
+
+namespace {
+ void SetVector(vec4& v, float x, float y, float z, float w)
+ { v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
+}
+
+inline void Material::SetDefaults()
+{
+ SetVector(ambient.color, 0, 0, 0, 1);
+ SetVector(diffuse.color, 0, 0, 0, 1);
+ SetVector(specular.color, 0, 0, 0, 1);
+ SetVector(emission.color, 0, 0, 0, 1);
+
+ doubleSided = false;
+ transparent = false;
+ transparency = 1.0;
+ shininess = 0.0;
+
+ technique = Technique_undefined;
+}
+
+namespace {
+
+ template<int N>
+ inline int Compare(const char* attr, const char (&str)[N]) {
+ return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0;
+ }
+
+ inline bool GetAttribVector(Mesh::Primitive& p, const char* attr, Mesh::AccessorList*& v, int& pos)
+ {
+ if ((pos = Compare(attr, "POSITION"))) {
+ v = &(p.attributes.position);
+ }
+ else if ((pos = Compare(attr, "NORMAL"))) {
+ v = &(p.attributes.normal);
+ }
+ else if ((pos = Compare(attr, "TEXCOORD"))) {
+ v = &(p.attributes.texcoord);
+ }
+ else if ((pos = Compare(attr, "COLOR"))) {
+ v = &(p.attributes.color);
+ }
+ else if ((pos = Compare(attr, "JOINT"))) {
+ v = &(p.attributes.joint);
+ }
+ else if ((pos = Compare(attr, "JOINTMATRIX"))) {
+ v = &(p.attributes.jointmatrix);
+ }
+ else if ((pos = Compare(attr, "WEIGHT"))) {
+ v = &(p.attributes.weight);
+ }
+ else return false;
+ return true;
+ }
+}
+
+inline void Mesh::Read(Value& obj, Asset& r)
+{
+ if (Value* primitives = FindArray(obj, "primitives")) {
+ this->primitives.resize(primitives->Size());
+ for (unsigned int i = 0; i < primitives->Size(); ++i) {
+ Value& primitive = (*primitives)[i];
+
+ Primitive& prim = this->primitives[i];
+ prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES);
+
+ if (Value* attrs = FindObject(primitive, "attributes")) {
+ for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
+ if (!it->value.IsString()) continue;
+ const char* attr = it->name.GetString();
+ // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX,
+ // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
+
+ int undPos = 0;
+ Mesh::AccessorList* vec = 0;
+ if (GetAttribVector(prim, attr, vec, undPos)) {
+ size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
+ if ((*vec).size() <= idx) (*vec).resize(idx + 1);
+ (*vec)[idx] = r.accessors.Get(it->value.GetString());
+ }
+ }
+ }
+
+ if (Value* indices = FindString(primitive, "indices")) {
+ prim.indices = r.accessors.Get(indices->GetString());
+ }
+
+ if (Value* material = FindString(primitive, "material")) {
+ prim.material = r.materials.Get(material->GetString());
+ }
+ }
+ }
+}
+
+
+inline void Camera::Read(Value& obj, Asset& r)
+{
+ type = MemberOrDefault(obj, "type", Camera::Perspective);
+
+ const char* subobjId = (type == Camera::Orthographic) ? "ortographic" : "perspective";
+
+ Value* it = FindObject(obj, subobjId);
+ if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
+
+ if (type == Camera::Perspective) {
+ perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
+ perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f);
+ perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
+ perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
+ }
+ else {
+ ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
+ ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
+ ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
+ ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
+ }
+}
+
+inline void Light::Read(Value& obj, Asset& r)
+{
+ SetDefaults();
+
+ if (Value* type = FindString(obj, "type")) {
+ const char* t = type->GetString();
+ if (strcmp(t, "ambient") == 0) this->type = Type_ambient;
+ else if (strcmp(t, "directional") == 0) this->type = Type_directional;
+ else if (strcmp(t, "point") == 0) this->type = Type_point;
+ else if (strcmp(t, "spot") == 0) this->type = Type_spot;
+
+ if (this->type != Type_undefined) {
+ if (Value* vals = FindString(obj, t)) {
+ ReadMember(*vals, "color", color);
+
+ ReadMember(*vals, "constantAttenuation", constantAttenuation);
+ ReadMember(*vals, "linearAttenuation", linearAttenuation);
+ ReadMember(*vals, "quadraticAttenuation", quadraticAttenuation);
+ ReadMember(*vals, "distance", distance);
+
+ ReadMember(*vals, "falloffAngle", falloffAngle);
+ ReadMember(*vals, "falloffExponent", falloffExponent);
+ }
+ }
+ }
+}
+
+inline void Light::SetDefaults()
+{
+ #ifndef M_PI
+ const float M_PI = 3.14159265358979323846f;
+ #endif
+
+ type = Type_undefined;
+
+ SetVector(color, 0.f, 0.f, 0.f, 1.f);
+
+ constantAttenuation = 0.f;
+ linearAttenuation = 1.f;
+ quadraticAttenuation = 1.f;
+ distance = 0.f;
+
+ falloffAngle = static_cast<float>(M_PI / 2.f);
+ falloffExponent = 0.f;
+}
+
+inline void Node::Read(Value& obj, Asset& r)
+{
+ if (Value* children = FindArray(obj, "children")) {
+ this->children.reserve(children->Size());
+ for (unsigned int i = 0; i < children->Size(); ++i) {
+ Value& child = (*children)[i];
+ if (child.IsString()) {
+ // get/create the child node
+ Ref<Node> chn = r.nodes.Get(child.GetString());
+ if (chn) this->children.push_back(chn);
+ }
+ }
+ }
+
+
+ if (Value* matrix = FindArray(obj, "matrix")) {
+ ReadValue(*matrix, this->matrix);
+ }
+ else {
+ ReadMember(obj, "translation", translation);
+ ReadMember(obj, "scale", scale);
+ ReadMember(obj, "rotation", rotation);
+ }
+
+ if (Value* meshes = FindArray(obj, "meshes")) {
+ unsigned numMeshes = (unsigned)meshes->Size();
+
+ std::vector<unsigned int> meshList;
+
+ this->meshes.reserve(numMeshes);
+ for (unsigned i = 0; i < numMeshes; ++i) {
+ if ((*meshes)[i].IsString()) {
+ Ref<Mesh> mesh = r.meshes.Get((*meshes)[i].GetString());
+ if (mesh) this->meshes.push_back(mesh);
+ }
+ }
+ }
+
+ if (Value* camera = FindString(obj, "camera")) {
+ this->camera = r.cameras.Get(camera->GetString());
+ if (this->camera)
+ this->camera->id = this->id;
+ }
+
+ // TODO load "skeletons", "skin", "jointName"
+
+ if (Value* extensions = FindObject(obj, "extensions")) {
+ if (r.extensionsUsed.KHR_materials_common) {
+
+ if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
+ if (Value* light = FindString(*ext, "light")) {
+ this->light = r.lights.Get(light->GetString());
+ }
+ }
+
+ }
+ }
+}
+
+inline void Scene::Read(Value& obj, Asset& r)
+{
+ if (Value* array = FindArray(obj, "nodes")) {
+ for (unsigned int i = 0; i < array->Size(); ++i) {
+ if (!(*array)[i].IsString()) continue;
+ Ref<Node> node = r.nodes.Get((*array)[i].GetString());
+ if (node)
+ this->nodes.push_back(node);
+ }
+ }
+}
+
+
+inline void AssetMetadata::Read(Document& doc)
+{
+ // read the version, etc.
+ int statedVersion = 0;
+ if (Value* obj = FindObject(doc, "asset")) {
+ ReadMember(*obj, "copyright", copyright);
+ ReadMember(*obj, "generator", generator);
+
+ premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false);
+ statedVersion = MemberOrDefault(*obj, "version", 0);
+
+ if (Value* profile = FindObject(*obj, "profile")) {
+ ReadMember(*profile, "api", this->profile.api);
+ ReadMember(*profile, "version", this->profile.version);
+ }
+ }
+
+ version = std::max(statedVersion, version);
+ if (version == 0) {
+ // if missing version, we'll assume version 1...
+ version = 1;
+ }
+
+ if (version != 1) {
+ char msg[128];
+ ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %d", version);
+ throw DeadlyImportError(msg);
+ }
+}
+
+
+
+//
+// Asset methods implementation
+//
+
+inline void Asset::ReadBinaryHeader(IOStream& stream)
+{
+ GLB_Header header;
+ if (stream.Read(&header, sizeof(header), 1) != 1) {
+ throw DeadlyImportError("GLTF: Unable to read the file header");
+ }
+
+ if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
+ throw DeadlyImportError("GLTF: Invalid binary glTF file");
+ }
+
+ AI_SWAP4(header.version);
+ asset.version = header.version;
+ if (header.version != 1) {
+ throw DeadlyImportError("GLTF: Unsupported binary glTF version");
+ }
+
+ AI_SWAP4(header.sceneFormat);
+ if (header.sceneFormat != SceneFormat_JSON) {
+ throw DeadlyImportError("GLTF: Unsupported binary glTF scene format");
+ }
+
+ AI_SWAP4(header.length);
+ AI_SWAP4(header.sceneLength);
+
+ mSceneLength = static_cast<size_t>(header.sceneLength);
+
+ mBodyOffset = sizeof(header)+mSceneLength;
+ mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
+
+ mBodyLength = header.length - mBodyOffset;
+}
+
+inline void Asset::Load(const std::string& pFile, bool isBinary)
+{
+ mCurrentAssetDir.clear();
+ int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
+ if (pos != int(std::string::npos)) mCurrentAssetDir = pFile.substr(0, pos + 1);
+
+ shared_ptr<IOStream> stream(OpenFile(pFile.c_str(), "rb", true));
+ if (!stream) {
+ throw DeadlyImportError("GLTF: Could not open file for reading");
+ }
+
+ // is binary? then read the header
+ if (isBinary) {
+ SetAsBinary(); // also creates the body buffer
+ ReadBinaryHeader(*stream);
+ }
+ else {
+ mSceneLength = stream->FileSize();
+ mBodyLength = 0;
+ }
+
+
+ // read the scene data
+
+ std::vector<char> sceneData(mSceneLength + 1);
+ sceneData[mSceneLength] = '\0';
+
+ if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
+ throw DeadlyImportError("GLTF: Could not read the file contents");
+ }
+
+
+ // parse the JSON document
+
+ Document doc;
+ doc.ParseInsitu(&sceneData[0]);
+
+ if (doc.HasParseError()) {
+ char buffer[32];
+ ai_snprintf(buffer, 32, "%d", static_cast<int>(doc.GetErrorOffset()));
+ throw DeadlyImportError(std::string("GLTF: JSON parse error, offset ") + buffer + ": "
+ + GetParseError_En(doc.GetParseError()));
+ }
+
+ if (!doc.IsObject()) {
+ throw DeadlyImportError("GLTF: JSON document root must be a JSON object");
+ }
+
+ // Fill the buffer instance for the current file embedded contents
+ if (mBodyLength > 0) {
+ if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) {
+ throw DeadlyImportError("GLTF: Unable to read gltf file");
+ }
+ }
+
+
+ // Load the metadata
+ asset.Read(doc);
+ ReadExtensionsUsed(doc);
+
+ // Prepare the dictionaries
+ for (size_t i = 0; i < mDicts.size(); ++i) {
+ mDicts[i]->AttachToDocument(doc);
+ }
+
+
+
+ // Read the "scene" property, which specifies which scene to load
+ // and recursively load everything referenced by it
+ if (Value* scene = FindString(doc, "scene")) {
+ this->scene = scenes.Get(scene->GetString());
+ }
+
+ // Clean up
+ for (size_t i = 0; i < mDicts.size(); ++i) {
+ mDicts[i]->DetachFromDocument();
+ }
+}
+
+inline void Asset::SetAsBinary()
+{
+ if (!extensionsUsed.KHR_binary_glTF) {
+ extensionsUsed.KHR_binary_glTF = true;
+ mBodyBuffer = buffers.Create("binary_glTF");
+ mBodyBuffer->MarkAsSpecial();
+ }
+}
+
+
+inline void Asset::ReadExtensionsUsed(Document& doc)
+{
+ Value* extsUsed = FindArray(doc, "extensionsUsed");
+ if (!extsUsed) return;
+
+ std::gltf_unordered_map<std::string, bool> exts;
+
+ for (unsigned int i = 0; i < extsUsed->Size(); ++i) {
+ if ((*extsUsed)[i].IsString()) {
+ exts[(*extsUsed)[i].GetString()] = true;
+ }
+ }
+
+ #define CHECK_EXT(EXT) \
+ if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
+
+ CHECK_EXT(KHR_binary_glTF);
+ CHECK_EXT(KHR_materials_common);
+
+ #undef CHECK_EXT
+}
+
+inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool absolute)
+{
+ #ifdef ASSIMP_API
+ return mIOSystem->Open(path, mode);
+ #else
+ if (path.size() < 2) return 0;
+ if (!absolute && path[1] != ':' && path[0] != '/') { // relative?
+ path = mCurrentAssetDir + path;
+ }
+ FILE* f = fopen(path.c_str(), mode);
+ return f ? new IOStream(f) : 0;
+ #endif
+}
+
+inline std::string Asset::FindUniqueID(const std::string& str, const char* suffix)
+{
+ std::string id = str;
+
+ if (!id.empty()) {
+ if (mUsedIds.find(id) == mUsedIds.end())
+ return id;
+
+ id += "_";
+ }
+
+ id += suffix;
+
+ Asset::IdMap::iterator it = mUsedIds.find(id);
+ if (it == mUsedIds.end())
+ return id;
+
+ char buffer[256];
+ int offset = ai_snprintf(buffer, sizeof(buffer), "%s_", id.c_str());
+ for (int i = 0; it != mUsedIds.end(); ++i) {
+ ai_snprintf(buffer + offset, sizeof(buffer) - offset, "%d", i);
+ id = buffer;
+ it = mUsedIds.find(id);
+ }
+
+ return id;
+}
+
+namespace Util {
+
+ inline
+ bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
+ if ( NULL == const_uri ) {
+ return false;
+ }
+
+ if (const_uri[0] != 0x10) { // we already parsed this uri?
+ if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
+ return false;
+ }
+
+ // set defaults
+ out.mediaType = "text/plain";
+ out.charset = "US-ASCII";
+ out.base64 = false;
+
+ char* uri = const_cast<char*>(const_uri);
+ if (uri[0] != 0x10) {
+ uri[0] = 0x10;
+ uri[1] = uri[2] = uri[3] = uri[4] = 0;
+
+ size_t i = 5, j;
+ if (uri[i] != ';' && uri[i] != ',') { // has media type?
+ uri[1] = char(i);
+ for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
+ // nothing to do!
+ }
+ }
+ while (uri[i] == ';' && i < uriLen) {
+ uri[i++] = '\0';
+ for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
+ // nothing to do!
+ }
+
+ if ( strncmp( uri + j, "charset=", 8 ) == 0 ) {
+ uri[2] = char(j + 8);
+ } else if ( strncmp( uri + j, "base64", 6 ) == 0 ) {
+ uri[3] = char(j);
+ }
+ }
+ if (i < uriLen) {
+ uri[i++] = '\0';
+ uri[4] = char(i);
+ } else {
+ uri[1] = uri[2] = uri[3] = 0;
+ uri[4] = 5;
+ }
+ }
+
+ if ( uri[ 1 ] != 0 ) {
+ out.mediaType = uri + uri[ 1 ];
+ }
+ if ( uri[ 2 ] != 0 ) {
+ out.charset = uri + uri[ 2 ];
+ }
+ if ( uri[ 3 ] != 0 ) {
+ out.base64 = true;
+ }
+ out.data = uri + uri[4];
+ out.dataLength = (uri + uriLen) - out.data;
+
+ return true;
+ }
+
+ template<bool B>
+ struct DATA
+ {
+ static const uint8_t tableDecodeBase64[128];
+ };
+
+ template<bool B>
+ const uint8_t DATA<B>::tableDecodeBase64[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0,
+ 0, 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, 0, 0, 0, 0, 0
+ };
+
+ inline char EncodeCharBase64(uint8_t b)
+ {
+ return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
+ }
+
+ inline uint8_t DecodeCharBase64(char c)
+ {
+ return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
+ /*if (c >= 'A' && c <= 'Z') return c - 'A';
+ if (c >= 'a' && c <= 'z') return c - 'a' + 26;
+ if (c >= '0' && c <= '9') return c - '0' + 52;
+ if (c == '+') return 62;
+ if (c == '/') return 63;
+ return 64; // '-' */
+ }
+
+ inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
+ {
+ ai_assert(inLength % 4 == 0);
+
+ if (inLength < 4) {
+ out = 0;
+ return 0;
+ }
+
+ int nEquals = int(in[inLength - 1] == '=') +
+ int(in[inLength - 2] == '=');
+
+ size_t outLength = (inLength * 3) / 4 - nEquals;
+ out = new uint8_t[outLength];
+ memset(out, 0, outLength);
+
+ size_t i, j = 0;
+
+ for (i = 0; i + 4 < inLength; i += 4) {
+ uint8_t b0 = DecodeCharBase64(in[i]);
+ uint8_t b1 = DecodeCharBase64(in[i + 1]);
+ uint8_t b2 = DecodeCharBase64(in[i + 2]);
+ uint8_t b3 = DecodeCharBase64(in[i + 3]);
+
+ out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+ out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+ out[j++] = (uint8_t)((b2 << 6) | b3);
+ }
+
+ {
+ uint8_t b0 = DecodeCharBase64(in[i]);
+ uint8_t b1 = DecodeCharBase64(in[i + 1]);
+ uint8_t b2 = DecodeCharBase64(in[i + 2]);
+ uint8_t b3 = DecodeCharBase64(in[i + 3]);
+
+ out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+ if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+ if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
+ }
+
+ return outLength;
+ }
+
+
+
+ inline void EncodeBase64(
+ const uint8_t* in, size_t inLength,
+ std::string& out)
+ {
+ size_t outLength = ((inLength + 2) / 3) * 4;
+
+ size_t j = out.size();
+ out.resize(j + outLength);
+
+ for (size_t i = 0; i < inLength; i += 3) {
+ uint8_t b = (in[i] & 0xFC) >> 2;
+ out[j++] = EncodeCharBase64(b);
+
+ b = (in[i] & 0x03) << 4;
+ if (i + 1 < inLength) {
+ b |= (in[i + 1] & 0xF0) >> 4;
+ out[j++] = EncodeCharBase64(b);
+
+ b = (in[i + 1] & 0x0F) << 2;
+ if (i + 2 < inLength) {
+ b |= (in[i + 2] & 0xC0) >> 6;
+ out[j++] = EncodeCharBase64(b);
+
+ b = in[i + 2] & 0x3F;
+ out[j++] = EncodeCharBase64(b);
+ }
+ else {
+ out[j++] = EncodeCharBase64(b);
+ out[j++] = '=';
+ }
+ }
+ else {
+ out[j++] = EncodeCharBase64(b);
+ out[j++] = '=';
+ out[j++] = '=';
+ }
+ }
+ }
+
+}
+
+}
+
+
diff --git a/src/3rdparty/assimp/code/glTFAssetWriter.h b/src/3rdparty/assimp/code/glTFAssetWriter.h
new file mode 100644
index 000000000..370d2c0ab
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFAssetWriter.h
@@ -0,0 +1,89 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file glTFWriter.h
+ * Declares a class to write gltf/glb files
+ *
+ * glTF Extensions Support:
+ * KHR_binary_glTF: full
+ * KHR_materials_common: full
+ */
+#ifndef glTFAssetWriter_H_INC
+#define glTFAssetWriter_H_INC
+
+#include "glTFAsset.h"
+
+namespace glTF
+{
+
+using rapidjson::MemoryPoolAllocator;
+
+class AssetWriter
+{
+ template<class T>
+ friend void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
+
+private:
+
+ void WriteBinaryData(IOStream* outfile, size_t sceneLength);
+
+ void WriteMetadata();
+ void WriteExtensionsUsed();
+
+ template<class T>
+ void WriteObjects(LazyDict<T>& d);
+
+public:
+ Document mDoc;
+ Asset& mAsset;
+
+ MemoryPoolAllocator<>& mAl;
+
+ AssetWriter(Asset& asset);
+
+ void WriteFile(const char* path);
+};
+
+}
+
+// Include the implementation of the methods
+#include "glTFAssetWriter.inl"
+
+#endif
diff --git a/src/3rdparty/assimp/code/glTFAssetWriter.inl b/src/3rdparty/assimp/code/glTFAssetWriter.inl
new file mode 100644
index 000000000..595cb8a81
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFAssetWriter.inl
@@ -0,0 +1,492 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/prettywriter.h>
+
+namespace glTF {
+
+ using rapidjson::StringBuffer;
+ using rapidjson::PrettyWriter;
+ using rapidjson::Writer;
+ using rapidjson::StringRef;
+ using rapidjson::StringRef;
+
+ namespace {
+
+ template<size_t N>
+ inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
+ val.SetArray();
+ val.Reserve(N, al);
+ for (decltype(N) i = 0; i < N; ++i) {
+ val.PushBack(r[i], al);
+ }
+ return val;
+ };
+
+ template<class T>
+ inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
+ if (v.empty()) return;
+ Value lst;
+ lst.SetArray();
+ lst.Reserve(unsigned(v.size()), al);
+ for (size_t i = 0; i < v.size(); ++i) {
+ lst.PushBack(StringRef(v[i]->id), al);
+ }
+ obj.AddMember(StringRef(fieldId), lst, al);
+ };
+
+
+ }
+
+ inline void Write(Value& obj, Accessor& a, AssetWriter& w)
+ {
+ obj.AddMember("bufferView", Value(a.bufferView->id, w.mAl).Move(), w.mAl);
+ obj.AddMember("byteOffset", a.byteOffset, w.mAl);
+ obj.AddMember("byteStride", a.byteStride, w.mAl);
+ obj.AddMember("componentType", int(a.componentType), w.mAl);
+ obj.AddMember("count", a.count, w.mAl);
+ obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
+ }
+
+ inline void Write(Value& obj, Animation& a, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Buffer& b, AssetWriter& w)
+ {
+ std::string dataURI = "data:application/octet-stream;base64,";
+ Util::EncodeBase64(b.GetPointer(), b.byteLength, dataURI);
+
+ const char* type;
+ switch (b.type) {
+ case Buffer::Type_text:
+ type = "text"; break;
+ default:
+ type = "arraybuffer";
+ }
+
+ obj.AddMember("byteLength", b.byteLength, w.mAl);
+ obj.AddMember("type", StringRef(type), w.mAl);
+ obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl);
+ }
+
+ inline void Write(Value& obj, BufferView& bv, AssetWriter& w)
+ {
+ obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl);
+ obj.AddMember("byteOffset", bv.byteOffset, w.mAl);
+ obj.AddMember("byteLength", bv.byteLength, w.mAl);
+ obj.AddMember("target", int(bv.target), w.mAl);
+ }
+
+ inline void Write(Value& obj, Camera& c, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Image& img, AssetWriter& w)
+ {
+ std::string uri;
+ if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) {
+ Value exts, ext;
+ exts.SetObject();
+ ext.SetObject();
+
+ ext.AddMember("bufferView", StringRef(img.bufferView->id), w.mAl);
+
+ if (!img.mimeType.empty())
+ ext.AddMember("mimeType", StringRef(img.mimeType), w.mAl);
+
+ exts.AddMember("KHR_binary_glTF", ext, w.mAl);
+ obj.AddMember("extensions", exts, w.mAl);
+ return;
+ }
+ else if (img.HasData()) {
+ uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
+ uri += ";base64,";
+ Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
+ }
+ else {
+ uri = img.uri;
+ }
+
+ obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl);
+ }
+
+ namespace {
+ inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al)
+ {
+ if (prop.texture)
+ obj.AddMember(StringRef(propName), Value(prop.texture->id, al).Move(), al);
+ else {
+ Value col;
+ obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al);
+ }
+ }
+ }
+
+ inline void Write(Value& obj, Material& m, AssetWriter& w)
+ {
+ Value v;
+ v.SetObject();
+ {
+ WriteColorOrTex(v, m.ambient, "ambient", w.mAl);
+ WriteColorOrTex(v, m.diffuse, "diffuse", w.mAl);
+ WriteColorOrTex(v, m.specular, "specular", w.mAl);
+ WriteColorOrTex(v, m.emission, "emission", w.mAl);
+
+ v.AddMember("shininess", m.shininess, w.mAl);
+ }
+ obj.AddMember("values", v, w.mAl);
+ }
+
+ namespace {
+ inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst,
+ const char* semantic, bool forceNumber = false)
+ {
+ if (lst.empty()) return;
+ if (lst.size() == 1 && !forceNumber) {
+ attrs.AddMember(StringRef(semantic), Value(lst[0]->id, w.mAl).Move(), w.mAl);
+ }
+ else {
+ for (size_t i = 0; i < lst.size(); ++i) {
+ char buffer[32];
+ ai_snprintf(buffer, 32, "%s_%d", semantic, int(i));
+ attrs.AddMember(Value(buffer, w.mAl).Move(), Value(lst[i]->id, w.mAl).Move(), w.mAl);
+ }
+ }
+ }
+ }
+
+ inline void Write(Value& obj, Mesh& m, AssetWriter& w)
+ {
+ Value primitives;
+ primitives.SetArray();
+ primitives.Reserve(unsigned(m.primitives.size()), w.mAl);
+
+ for (size_t i = 0; i < m.primitives.size(); ++i) {
+ Mesh::Primitive& p = m.primitives[i];
+ Value prim;
+ prim.SetObject();
+ {
+ prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl);
+
+ if (p.material)
+ prim.AddMember("material", p.material->id, w.mAl);
+
+ if (p.indices)
+ prim.AddMember("indices", Value(p.indices->id, w.mAl).Move(), w.mAl);
+
+ Value attrs;
+ attrs.SetObject();
+ {
+ WriteAttrs(w, attrs, p.attributes.position, "POSITION");
+ WriteAttrs(w, attrs, p.attributes.normal, "NORMAL");
+ WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true);
+ WriteAttrs(w, attrs, p.attributes.color, "COLOR");
+ WriteAttrs(w, attrs, p.attributes.joint, "JOINT");
+ WriteAttrs(w, attrs, p.attributes.jointmatrix, "JOINTMATRIX");
+ WriteAttrs(w, attrs, p.attributes.weight, "WEIGHT");
+ }
+ prim.AddMember("attributes", attrs, w.mAl);
+ }
+ primitives.PushBack(prim, w.mAl);
+ }
+
+ obj.AddMember("primitives", primitives, w.mAl);
+ }
+
+ inline void Write(Value& obj, Node& n, AssetWriter& w)
+ {
+
+ if (n.matrix.isPresent) {
+ Value val;
+ obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl);
+ }
+
+ if (n.translation.isPresent) {
+ Value val;
+ obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl);
+ }
+
+ if (n.scale.isPresent) {
+ Value val;
+ obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl);
+ }
+ if (n.rotation.isPresent) {
+ Value val;
+ obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl);
+ }
+
+ AddRefsVector(obj, "children", n.children, w.mAl);
+
+ AddRefsVector(obj, "meshes", n.meshes, w.mAl);
+ }
+
+ inline void Write(Value& obj, Program& b, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Sampler& b, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& scene, Scene& s, AssetWriter& w)
+ {
+ AddRefsVector(scene, "nodes", s.nodes, w.mAl);
+ }
+
+ inline void Write(Value& obj, Shader& b, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Skin& b, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Technique& b, AssetWriter& w)
+ {
+
+ }
+
+ inline void Write(Value& obj, Texture& tex, AssetWriter& w)
+ {
+ if (tex.source) {
+ obj.AddMember("source", Value(tex.source->id, w.mAl).Move(), w.mAl);
+ }
+ }
+
+ inline void Write(Value& obj, Light& b, AssetWriter& w)
+ {
+
+ }
+
+
+ inline AssetWriter::AssetWriter(Asset& a)
+ : mDoc()
+ , mAsset(a)
+ , mAl(mDoc.GetAllocator())
+ {
+ mDoc.SetObject();
+
+ WriteMetadata();
+ WriteExtensionsUsed();
+
+ // Dump the contents of the dictionaries
+ for (size_t i = 0; i < a.mDicts.size(); ++i) {
+ a.mDicts[i]->WriteObjects(*this);
+ }
+
+ // Add the target scene field
+ if (mAsset.scene) {
+ mDoc.AddMember("scene", StringRef(mAsset.scene->id), mAl);
+ }
+ }
+
+ inline void AssetWriter::WriteFile(const char* path)
+ {
+ bool isBinary = mAsset.extensionsUsed.KHR_binary_glTF;
+
+ std::unique_ptr<IOStream> outfile
+ (mAsset.OpenFile(path, isBinary ? "wb" : "wt", true));
+
+ if (outfile == 0) {
+ throw DeadlyExportError("Could not open output file: " + std::string(path));
+ }
+
+ if (isBinary) {
+ // we will write the header later, skip its size
+ outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
+ }
+
+ StringBuffer docBuffer;
+
+ bool pretty = true;
+ if (!isBinary && pretty) {
+ PrettyWriter<StringBuffer> writer(docBuffer);
+ mDoc.Accept(writer);
+ }
+ else {
+ Writer<StringBuffer> writer(docBuffer);
+ mDoc.Accept(writer);
+ }
+
+ if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
+ throw DeadlyExportError("Failed to write scene data!");
+ }
+
+ if (isBinary) {
+ WriteBinaryData(outfile.get(), docBuffer.GetSize());
+ }
+ }
+
+ inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength)
+ {
+ //
+ // write the body data
+ //
+
+ size_t bodyLength = 0;
+ if (Ref<Buffer> b = mAsset.GetBodyBuffer()) {
+ bodyLength = b->byteLength;
+
+ if (bodyLength > 0) {
+ size_t bodyOffset = sizeof(GLB_Header) + sceneLength;
+ bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4
+
+ outfile->Seek(bodyOffset, aiOrigin_SET);
+
+ if (outfile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
+ throw DeadlyExportError("Failed to write body data!");
+ }
+ }
+ }
+
+
+ //
+ // write the header
+ //
+
+ GLB_Header header;
+ memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
+
+ header.version = 1;
+ AI_SWAP4(header.version);
+
+ header.length = uint32_t(sizeof(header) + sceneLength + bodyLength);
+ AI_SWAP4(header.length);
+
+ header.sceneLength = uint32_t(sceneLength);
+ AI_SWAP4(header.sceneLength);
+
+ header.sceneFormat = SceneFormat_JSON;
+ AI_SWAP4(header.sceneFormat);
+
+ outfile->Seek(0, aiOrigin_SET);
+
+ if (outfile->Write(&header, 1, sizeof(header)) != sizeof(header)) {
+ throw DeadlyExportError("Failed to write the header!");
+ }
+ }
+
+
+ inline void AssetWriter::WriteMetadata()
+ {
+ Value asset;
+ asset.SetObject();
+ {
+ asset.AddMember("version", mAsset.asset.version, mAl);
+
+ asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
+ }
+ mDoc.AddMember("asset", asset, mAl);
+ }
+
+ inline void AssetWriter::WriteExtensionsUsed()
+ {
+ Value exts;
+ exts.SetArray();
+ {
+ if (false)
+ exts.PushBack(StringRef("KHR_binary_glTF"), mAl);
+
+ if (false)
+ exts.PushBack(StringRef("KHR_materials_common"), mAl);
+ }
+
+ if (!exts.Empty())
+ mDoc.AddMember("extensionsUsed", exts, mAl);
+ }
+
+ template<class T>
+ void AssetWriter::WriteObjects(LazyDict<T>& d)
+ {
+ if (d.mObjs.empty()) return;
+
+ Value* container = &mDoc;
+
+ if (d.mExtId) {
+ Value* exts = FindObject(mDoc, "extensions");
+ if (!exts) {
+ mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator());
+ exts = FindObject(mDoc, "extensions");
+ }
+
+ if (!(container = FindObject(*exts, d.mExtId))) {
+ exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator());
+ container = FindObject(*exts, d.mExtId);
+ }
+ }
+
+ Value* dict;
+ if (!(dict = FindObject(*container, d.mDictId))) {
+ container->AddMember(StringRef(d.mDictId), Value().SetObject().Move(), mDoc.GetAllocator());
+ dict = FindObject(*container, d.mDictId);
+ }
+
+ for (size_t i = 0; i < d.mObjs.size(); ++i) {
+ if (d.mObjs[i]->IsSpecial()) continue;
+
+ Value obj;
+ obj.SetObject();
+
+ if (!d.mObjs[i]->name.empty()) {
+ obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl);
+ }
+
+ Write(obj, *d.mObjs[i], *this);
+
+ dict->AddMember(StringRef(d.mObjs[i]->id), obj, mAl);
+ }
+ }
+
+ template<class T>
+ void WriteLazyDict(LazyDict<T>& d, AssetWriter& w)
+ {
+ w.WriteObjects(d);
+ }
+
+}
diff --git a/src/3rdparty/assimp/code/glTFExporter.cpp b/src/3rdparty/assimp/code/glTFExporter.cpp
new file mode 100644
index 000000000..7f0c086cf
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFExporter.cpp
@@ -0,0 +1,366 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
+
+#include "glTFExporter.h"
+
+#include "Exceptional.h"
+#include "StringComparison.h"
+#include "ByteSwapper.h"
+
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+
+#include <memory>
+
+#include "glTFAssetWriter.h"
+
+using namespace rapidjson;
+
+using namespace Assimp;
+using namespace glTF;
+
+namespace Assimp {
+
+ // ------------------------------------------------------------------------------------------------
+ // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp
+ void ExportSceneGLTF(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+ {
+ // invoke the exporter
+ glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, false);
+ }
+
+ // ------------------------------------------------------------------------------------------------
+ // Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp
+ void ExportSceneGLB(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+ {
+ // invoke the exporter
+ glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, true);
+ }
+
+} // end of namespace Assimp
+
+
+
+glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
+ const ExportProperties* pProperties, bool isBinary)
+ : mFilename(filename)
+ , mIOSystem(pIOSystem)
+ , mScene(pScene)
+ , mProperties(pProperties)
+{
+ std::unique_ptr<Asset> asset(new glTF::Asset(pIOSystem));
+ mAsset = asset.get();
+
+ if (isBinary) {
+ asset->SetAsBinary();
+ }
+
+ ExportMetadata();
+
+ //for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {}
+
+ //for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {}
+
+ //for (unsigned int i = 0; i < pScene->mNumLights; ++i) {}
+
+
+ ExportMaterials();
+
+ ExportMeshes();
+
+ //for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {}
+
+
+ if (mScene->mRootNode) {
+ ExportNode(mScene->mRootNode);
+ }
+
+ ExportScene();
+
+
+ glTF::AssetWriter writer(*mAsset);
+ writer.WriteFile(filename);
+}
+
+
+static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o)
+{
+ o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1;
+ o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2;
+ o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3;
+ o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4;
+}
+
+inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
+ unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
+{
+ if (!count || !data) return Ref<Accessor>();
+
+ unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
+ unsigned int numCompsOut = AttribType::GetNumComponents(typeOut);
+ unsigned int bytesPerComp = ComponentTypeSize(compType);
+
+ size_t offset = buffer->byteLength;
+ size_t length = count * numCompsOut * bytesPerComp;
+ buffer->Grow(length);
+
+ // bufferView
+ Ref<BufferView> bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view"));
+ bv->buffer = buffer;
+ bv->byteOffset = unsigned(offset);
+ bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
+ bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
+
+ // accessor
+ Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
+ acc->bufferView = bv;
+ acc->byteOffset = 0;
+ acc->byteStride = 0;
+ acc->componentType = compType;
+ acc->count = count;
+ acc->type = typeOut;
+
+ // copy the data
+ acc->WriteData(count, data, numCompsIn*bytesPerComp);
+
+ return acc;
+}
+
+namespace {
+ void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
+ if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
+ }
+}
+
+void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
+{
+ aiString tex;
+ aiColor4D col;
+ if (mat->GetTextureCount(tt) > 0) {
+ if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) {
+ std::string path = tex.C_Str();
+
+ if (path.size() > 0) {
+ if (path[0] != '*') {
+ std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
+ if (it != mTexturesByPath.end()) {
+ prop.texture = mAsset->textures.Get(it->second);
+ }
+ }
+
+ if (!prop.texture) {
+ std::string texId = mAsset->FindUniqueID("", "texture");
+ prop.texture = mAsset->textures.Create(texId);
+ mTexturesByPath[path] = prop.texture.GetIndex();
+
+ std::string imgId = mAsset->FindUniqueID("", "image");
+ prop.texture->source = mAsset->images.Create(imgId);
+
+ if (path[0] == '*') { // embedded
+ aiTexture* tex = mScene->mTextures[atoi(&path[1])];
+
+ uint8_t* data = reinterpret_cast<uint8_t*>(tex->pcData);
+ prop.texture->source->SetData(data, tex->mWidth, *mAsset);
+
+ if (tex->achFormatHint[0]) {
+ std::string mimeType = "image/";
+ mimeType += (memcmp(tex->achFormatHint, "jpg", 3) == 0) ? "jpeg" : tex->achFormatHint;
+ prop.texture->source->mimeType = mimeType;
+ }
+ }
+ else {
+ prop.texture->source->uri = path;
+ }
+ }
+ }
+ }
+ }
+
+ if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
+ prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a;
+ }
+}
+
+void glTFExporter::ExportMaterials()
+{
+ aiString aiName;
+ for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
+ const aiMaterial* mat = mScene->mMaterials[i];
+
+
+ std::string name;
+ if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
+ name = aiName.C_Str();
+ }
+ name = mAsset->FindUniqueID(name, "material");
+
+ Ref<Material> m = mAsset->materials.Create(name);
+
+ GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT);
+ GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE);
+ GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR);
+ GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE);
+
+ GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS);
+ }
+}
+
+void glTFExporter::ExportMeshes()
+{
+ for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) {
+ const aiMesh* aim = mScene->mMeshes[i];
+
+ std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh");
+ Ref<Mesh> m = mAsset->meshes.Create(meshId);
+ m->primitives.resize(1);
+ Mesh::Primitive& p = m->primitives.back();
+
+ p.material = mAsset->materials.Get(aim->mMaterialIndex);
+
+ std::string bufferId = mAsset->FindUniqueID(meshId, "buffer");
+
+ Ref<Buffer> b = mAsset->GetBodyBuffer();
+ if (!b) {
+ b = mAsset->buffers.Create(bufferId);
+ }
+
+ Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if (v) p.attributes.position.push_back(v);
+
+ Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+ if (n) p.attributes.normal.push_back(n);
+
+ for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+ if (aim->mNumUVComponents[i] > 0) {
+ AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
+ Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, true);
+ if (tc) p.attributes.texcoord.push_back(tc);
+ }
+ }
+
+ if (aim->mNumFaces > 0) {
+ unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices;
+ std::vector<uint16_t> indices;
+ indices.resize(aim->mNumFaces * nIndicesPerFace);
+ for (size_t i = 0; i < aim->mNumFaces; ++i) {
+ for (size_t j = 0; j < nIndicesPerFace; ++j) {
+ indices[i*nIndicesPerFace + j] = uint16_t(aim->mFaces[i].mIndices[j]);
+ }
+ }
+ p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true);
+ }
+
+ switch (aim->mPrimitiveTypes) {
+ case aiPrimitiveType_POLYGON:
+ p.mode = PrimitiveMode_TRIANGLES; break; // TODO implement this
+ case aiPrimitiveType_LINE:
+ p.mode = PrimitiveMode_LINES; break;
+ case aiPrimitiveType_POINT:
+ p.mode = PrimitiveMode_POINTS; break;
+ default: // aiPrimitiveType_TRIANGLE
+ p.mode = PrimitiveMode_TRIANGLES;
+ }
+ }
+}
+
+unsigned int glTFExporter::ExportNode(const aiNode* n)
+{
+ Ref<Node> node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node"));
+
+ if (!n->mTransformation.IsIdentity()) {
+ node->matrix.isPresent = true;
+ CopyValue(n->mTransformation, node->matrix.value);
+ }
+
+ for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
+ node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
+ }
+
+ for (unsigned int i = 0; i < n->mNumChildren; ++i) {
+ unsigned int idx = ExportNode(n->mChildren[i]);
+ node->children.push_back(mAsset->nodes.Get(idx));
+ }
+
+ return node.GetIndex();
+}
+
+
+void glTFExporter::ExportScene()
+{
+ const char* sceneName = "defaultScene";
+ Ref<Scene> scene = mAsset->scenes.Create(sceneName);
+
+ // root node will be the first one exported (idx 0)
+ if (mAsset->nodes.Size() > 0) {
+ scene->nodes.push_back(mAsset->nodes.Get(0u));
+ }
+
+ // set as the default scene
+ mAsset->scene = scene;
+}
+
+void glTFExporter::ExportMetadata()
+{
+ glTF::AssetMetadata& asset = mAsset->asset;
+ asset.version = 1;
+
+ char buffer[256];
+ ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)",
+ aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision());
+
+ asset.generator = buffer;
+}
+
+
+
+
+
+
+
+#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
diff --git a/src/3rdparty/assimp/code/glTFExporter.h b/src/3rdparty/assimp/code/glTFExporter.h
new file mode 100644
index 000000000..884d1fe38
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFExporter.h
@@ -0,0 +1,108 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file GltfExporter.h
+* Declares the exporter class to write a scene to a gltf/glb file
+*/
+#ifndef AI_GLTFEXPORTER_H_INC
+#define AI_GLTFEXPORTER_H_INC
+
+#include <assimp/types.h>
+#include <assimp/material.h>
+#include <sstream>
+#include <vector>
+#include <map>
+
+#include <memory>
+
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+
+namespace glTF
+{
+ class Asset;
+
+ struct TexProperty;
+}
+
+namespace Assimp
+{
+ class IOSystem;
+ class IOStream;
+ class ExportProperties;
+
+ // ------------------------------------------------------------------------------------------------
+ /** Helper class to export a given scene to an glTF file. */
+ // ------------------------------------------------------------------------------------------------
+ class glTFExporter
+ {
+ public:
+ /// Constructor for a specific scene to export
+ glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
+ const ExportProperties* pProperties, bool binary);
+
+ private:
+
+ const char* mFilename;
+ IOSystem* mIOSystem;
+ const aiScene* mScene;
+ const ExportProperties* mProperties;
+
+ std::map<std::string, unsigned int> mTexturesByPath;
+
+ glTF::Asset* mAsset;
+
+ std::vector<unsigned char> mBodyData;
+
+ void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
+
+ void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
+ void ExportMetadata();
+ void ExportMaterials();
+ void ExportMeshes();
+ unsigned int ExportNode(const aiNode* node);
+ void ExportScene();
+ };
+
+}
+
+#endif
diff --git a/src/3rdparty/assimp/code/glTFImporter.cpp b/src/3rdparty/assimp/code/glTFImporter.cpp
new file mode 100644
index 000000000..6a6619b81
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFImporter.cpp
@@ -0,0 +1,654 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#include "glTFImporter.h"
+
+#include "StringComparison.h"
+
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <assimp/ai_assert.h>
+#include <assimp/DefaultLogger.hpp>
+#include <memory>
+
+#include "MakeVerboseFormat.h"
+
+#include "glTFAsset.h"
+// This is included here so WriteLazyDict<T>'s definition is found.
+#include "glTFAssetWriter.h"
+
+using namespace Assimp;
+using namespace glTF;
+
+
+//
+// glTFImporter
+//
+
+static const aiImporterDesc desc = {
+ "glTF Importer",
+ "",
+ "",
+ "",
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour
+ | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+ 0,
+ 0,
+ 0,
+ 0,
+ "gltf glb"
+};
+
+glTFImporter::glTFImporter()
+: BaseImporter()
+, meshOffsets()
+, embeddedTexIdxs()
+, mScene( NULL ) {
+ // empty
+}
+
+glTFImporter::~glTFImporter() {
+ // empty
+}
+
+const aiImporterDesc* glTFImporter::GetInfo() const
+{
+ return &desc;
+}
+
+bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+ const std::string& extension = GetExtension(pFile);
+
+ if (extension == "gltf" || extension == "glb")
+ return true;
+
+ if ((checkSig || !extension.length()) && pIOHandler) {
+ char buffer[4];
+
+ std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile));
+ if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) {
+ if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) {
+ return true; // Has GLB header
+ }
+ else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0
+ || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) {
+ // seems a JSON file, and we're the only format that can read them
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+//static void CopyValue(const glTF::vec3& v, aiColor3D& out)
+//{
+// out.r = v[0]; out.g = v[1]; out.b = v[2];
+//}
+
+static void CopyValue(const glTF::vec4& v, aiColor4D& out)
+{
+ out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
+}
+
+static void CopyValue(const glTF::vec4& v, aiColor3D& out)
+{
+ out.r = v[0]; out.g = v[1]; out.b = v[2];
+}
+
+static void CopyValue(const glTF::vec3& v, aiVector3D& out)
+{
+ out.x = v[0]; out.y = v[1]; out.z = v[2];
+}
+
+static void CopyValue(const glTF::vec4& v, aiQuaternion& out)
+{
+ out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
+}
+
+static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o)
+{
+ o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
+ o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
+ o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
+ o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
+}
+
+inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF::TexProperty prop, aiMaterial* mat,
+ aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx)
+{
+ if (prop.texture) {
+ if (prop.texture->source) {
+ aiString uri(prop.texture->source->uri);
+
+ int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
+ if (texIdx != -1) { // embedded
+ // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
+ uri.data[0] = '*';
+ uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
+ }
+
+ mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
+ }
+ }
+ else {
+ aiColor4D col;
+ CopyValue(prop.color, col);
+ if (col.r != 1.f || col.g != 1.f || col.b != 1.f || col.a != 1.f) {
+ mat->AddProperty(&col, 1, pKey, type, idx);
+ }
+ }
+}
+
+void glTFImporter::ImportMaterials(glTF::Asset& r)
+{
+ mScene->mNumMaterials = unsigned(r.materials.Size());
+ mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials];
+
+ for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
+ aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial();
+
+ Material& mat = r.materials[i];
+
+ /*if (!mat.name.empty())*/ {
+ aiString str(mat.id /*mat.name*/);
+ aimat->AddProperty(&str, AI_MATKEY_NAME);
+ }
+
+ SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
+ SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
+ SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
+
+ if (mat.shininess > 0.f) {
+ aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);
+ }
+ }
+
+ if (mScene->mNumMaterials == 0) {
+ mScene->mNumMaterials = 1;
+ mScene->mMaterials = new aiMaterial*[1];
+ mScene->mMaterials[0] = new aiMaterial();
+ }
+}
+
+
+static inline void SetFace(aiFace& face, int a)
+{
+ face.mNumIndices = 1;
+ face.mIndices = new unsigned int[1];
+ face.mIndices[0] = a;
+}
+
+static inline void SetFace(aiFace& face, int a, int b)
+{
+ face.mNumIndices = 2;
+ face.mIndices = new unsigned int[2];
+ face.mIndices[0] = a;
+ face.mIndices[1] = b;
+}
+
+static inline void SetFace(aiFace& face, int a, int b, int c)
+{
+ face.mNumIndices = 3;
+ face.mIndices = new unsigned int[3];
+ face.mIndices[0] = a;
+ face.mIndices[1] = b;
+ face.mIndices[2] = c;
+}
+
+static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
+{
+ for (unsigned i = 0; i < nFaces; ++i) {
+ for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
+ unsigned idx = faces[i].mIndices[j];
+ if (idx >= nVerts)
+ return false;
+ }
+ }
+ return true;
+}
+
+void glTFImporter::ImportMeshes(glTF::Asset& r)
+{
+ std::vector<aiMesh*> meshes;
+
+ unsigned int k = 0;
+
+ for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
+ Mesh& mesh = r.meshes[m];
+
+ meshOffsets.push_back(k);
+ k += unsigned(mesh.primitives.size());
+
+ for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
+ Mesh::Primitive& prim = mesh.primitives[p];
+
+ aiMesh* aim = new aiMesh();
+ meshes.push_back(aim);
+
+ aim->mName = mesh.id;
+ if (mesh.primitives.size() > 1) {
+ size_t& len = aim->mName.length;
+ aim->mName.data[len] = '-';
+ len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
+ }
+
+ switch (prim.mode) {
+ case PrimitiveMode_POINTS:
+ aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
+ break;
+
+ case PrimitiveMode_LINES:
+ case PrimitiveMode_LINE_LOOP:
+ case PrimitiveMode_LINE_STRIP:
+ aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
+ break;
+
+ case PrimitiveMode_TRIANGLES:
+ case PrimitiveMode_TRIANGLE_STRIP:
+ case PrimitiveMode_TRIANGLE_FAN:
+ aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+ break;
+ }
+
+ Mesh::Primitive::Attributes& attr = prim.attributes;
+ if (attr.position.size() > 0 && attr.position[0]) {
+ aim->mNumVertices = attr.position[0]->count;
+ attr.position[0]->ExtractData(aim->mVertices);
+ }
+
+ if (attr.normal.size() > 0 && attr.normal[0]) {
+ attr.normal[0]->ExtractData(aim->mNormals);
+ }
+
+ for (size_t tc = 0; tc < attr.texcoord.size() && tc <= AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
+ attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
+ aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
+
+ aiVector3D* values = aim->mTextureCoords[tc];
+ for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
+ values[i].y = 1 - values[i].y; // Flip Y coords
+ }
+ }
+
+
+ if (prim.indices) {
+ aiFace* faces = 0;
+ unsigned int nFaces = 0;
+
+ unsigned int count = prim.indices->count;
+
+ Accessor::Indexer data = prim.indices->GetIndexer();
+ ai_assert(data.IsValid());
+
+ switch (prim.mode) {
+ case PrimitiveMode_POINTS: {
+ nFaces = count;
+ faces = new aiFace[nFaces];
+ for (unsigned int i = 0; i < count; ++i) {
+ SetFace(faces[i], data.GetUInt(i));
+ }
+ break;
+ }
+
+ case PrimitiveMode_LINES: {
+ nFaces = count / 2;
+ faces = new aiFace[nFaces];
+ for (unsigned int i = 0; i < count; i += 2) {
+ SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
+ }
+ break;
+ }
+
+ case PrimitiveMode_LINE_LOOP:
+ case PrimitiveMode_LINE_STRIP: {
+ nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
+ faces = new aiFace[nFaces];
+ SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
+ for (unsigned int i = 2; i < count; ++i) {
+ SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
+ }
+ if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
+ SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
+ }
+ break;
+ }
+
+ case PrimitiveMode_TRIANGLES: {
+ nFaces = count / 3;
+ faces = new aiFace[nFaces];
+ for (unsigned int i = 0; i < count; i += 3) {
+ SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
+ }
+ break;
+ }
+ case PrimitiveMode_TRIANGLE_STRIP: {
+ nFaces = count - 2;
+ faces = new aiFace[nFaces];
+ SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
+ for (unsigned int i = 3; i < count; ++i) {
+ SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
+ }
+ break;
+ }
+ case PrimitiveMode_TRIANGLE_FAN:
+ nFaces = count - 2;
+ faces = new aiFace[nFaces];
+ SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
+ for (unsigned int i = 3; i < count; ++i) {
+ SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
+ }
+ break;
+ }
+
+ if (faces) {
+ aim->mFaces = faces;
+ aim->mNumFaces = nFaces;
+ ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
+ }
+ }
+
+
+ if (prim.material) {
+ aim->mMaterialIndex = prim.material.GetIndex();
+ }
+ }
+ }
+
+ meshOffsets.push_back(k);
+
+ CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
+}
+
+void glTFImporter::ImportCameras(glTF::Asset& r)
+{
+ if (!r.cameras.Size()) return;
+
+ mScene->mNumCameras = r.cameras.Size();
+ mScene->mCameras = new aiCamera*[r.cameras.Size()];
+
+ for (size_t i = 0; i < r.cameras.Size(); ++i) {
+ Camera& cam = r.cameras[i];
+
+ aiCamera* aicam = mScene->mCameras[i] = new aiCamera();
+
+ if (cam.type == Camera::Perspective) {
+
+ aicam->mAspect = cam.perspective.aspectRatio;
+ aicam->mHorizontalFOV = cam.perspective.yfov * aicam->mAspect;
+ aicam->mClipPlaneFar = cam.perspective.zfar;
+ aicam->mClipPlaneNear = cam.perspective.znear;
+ }
+ else {
+ // assimp does not support orthographic cameras
+ }
+ }
+}
+
+void glTFImporter::ImportLights(glTF::Asset& r)
+{
+ if (!r.lights.Size()) return;
+
+ mScene->mNumLights = r.lights.Size();
+ mScene->mLights = new aiLight*[r.lights.Size()];
+
+ for (size_t i = 0; i < r.lights.Size(); ++i) {
+ Light& l = r.lights[i];
+
+ aiLight* ail = mScene->mLights[i] = new aiLight();
+
+ switch (l.type) {
+ case Light::Type_directional:
+ ail->mType = aiLightSource_DIRECTIONAL; break;
+
+ case Light::Type_spot:
+ ail->mType = aiLightSource_SPOT; break;
+
+ case Light::Type_ambient:
+ ail->mType = aiLightSource_AMBIENT; break;
+
+ default: // Light::Type_point
+ ail->mType = aiLightSource_POINT; break;
+ }
+
+ CopyValue(l.color, ail->mColorAmbient);
+ CopyValue(l.color, ail->mColorDiffuse);
+ CopyValue(l.color, ail->mColorSpecular);
+
+ ail->mAngleOuterCone = l.falloffAngle;
+ ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all
+
+ ail->mAttenuationConstant = l.constantAttenuation;
+ ail->mAttenuationLinear = l.linearAttenuation;
+ ail->mAttenuationQuadratic = l.quadraticAttenuation;
+ }
+}
+
+
+aiNode* ImportNode(aiScene* pScene, glTF::Asset& r, std::vector<unsigned int>& meshOffsets, glTF::Ref<glTF::Node>& ptr)
+{
+ Node& node = *ptr;
+
+ aiNode* ainode = new aiNode(node.id);
+
+ if (!node.children.empty()) {
+ ainode->mNumChildren = unsigned(node.children.size());
+ ainode->mChildren = new aiNode*[ainode->mNumChildren];
+
+ for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
+ aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]);
+ child->mParent = ainode;
+ ainode->mChildren[i] = child;
+ }
+ }
+
+ aiMatrix4x4& matrix = ainode->mTransformation;
+ if (node.matrix.isPresent) {
+ CopyValue(node.matrix.value, matrix);
+ }
+ else {
+ if (node.translation.isPresent) {
+ aiVector3D trans;
+ CopyValue(node.translation.value, trans);
+ aiMatrix4x4 t;
+ aiMatrix4x4::Translation(trans, t);
+ matrix = t * matrix;
+ }
+
+ if (node.scale.isPresent) {
+ aiVector3D scal(1.f);
+ CopyValue(node.scale.value, scal);
+ aiMatrix4x4 s;
+ aiMatrix4x4::Scaling(scal, s);
+ matrix = s * matrix;
+ }
+
+
+ if (node.rotation.isPresent) {
+ aiQuaternion rot;
+ CopyValue(node.rotation.value, rot);
+ matrix = aiMatrix4x4(rot.GetMatrix()) * matrix;
+ }
+ }
+
+ if (!node.meshes.empty()) {
+ int count = 0;
+ for (size_t i = 0; i < node.meshes.size(); ++i) {
+ int idx = node.meshes[i].GetIndex();
+ count += meshOffsets[idx + 1] - meshOffsets[idx];
+ }
+
+ ainode->mNumMeshes = count;
+ ainode->mMeshes = new unsigned int[count];
+
+ int k = 0;
+ for (size_t i = 0; i < node.meshes.size(); ++i) {
+ int idx = node.meshes[i].GetIndex();
+ for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) {
+ ainode->mMeshes[k] = j;
+ }
+ }
+ }
+
+ if (node.camera) {
+ pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
+ }
+
+ if (node.light) {
+ pScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
+ }
+
+ return ainode;
+}
+
+void glTFImporter::ImportNodes(glTF::Asset& r)
+{
+ if (!r.scene) return;
+
+ std::vector< Ref<Node> > rootNodes = r.scene->nodes;
+
+ // The root nodes
+ unsigned int numRootNodes = unsigned(rootNodes.size());
+ if (numRootNodes == 1) { // a single root node: use it
+ mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
+ }
+ else if (numRootNodes > 1) { // more than one root node: create a fake root
+ aiNode* root = new aiNode("ROOT");
+ root->mChildren = new aiNode*[numRootNodes];
+ for (unsigned int i = 0; i < numRootNodes; ++i) {
+ aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
+ node->mParent = root;
+ root->mChildren[root->mNumChildren++] = node;
+ }
+ mScene->mRootNode = root;
+ }
+
+ //if (!mScene->mRootNode) {
+ // mScene->mRootNode = new aiNode("EMPTY");
+ //}
+}
+
+void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r)
+{
+ embeddedTexIdxs.resize(r.images.Size(), -1);
+
+ int numEmbeddedTexs = 0;
+ for (size_t i = 0; i < r.images.Size(); ++i) {
+ if (r.images[i].HasData())
+ numEmbeddedTexs += 1;
+ }
+
+ if (numEmbeddedTexs == 0)
+ return;
+
+ mScene->mTextures = new aiTexture*[numEmbeddedTexs];
+
+ // Add the embedded textures
+ for (size_t i = 0; i < r.images.Size(); ++i) {
+ Image img = r.images[i];
+ if (!img.HasData()) continue;
+
+ int idx = mScene->mNumTextures++;
+ embeddedTexIdxs[i] = idx;
+
+ aiTexture* tex = mScene->mTextures[idx] = new aiTexture();
+
+ size_t length = img.GetDataLength();
+ void* data = img.StealData();
+
+ tex->mWidth = static_cast<unsigned int>(length);
+ tex->mHeight = 0;
+ tex->pcData = reinterpret_cast<aiTexel*>(data);
+
+ if (!img.mimeType.empty()) {
+ const char* ext = strchr(img.mimeType.c_str(), '/') + 1;
+ if (ext) {
+ if (strcmp(ext, "jpeg") == 0) ext = "jpg";
+
+ size_t len = strlen(ext);
+ if (len <= 3) {
+ strcpy(tex->achFormatHint, ext);
+ }
+ }
+ }
+ }
+}
+
+void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
+
+ this->mScene = pScene;
+
+ // read the asset file
+ glTF::Asset asset(pIOHandler);
+ asset.Load(pFile, GetExtension(pFile) == "glb");
+
+
+ //
+ // Copy the data out
+ //
+
+ ImportEmbeddedTextures(asset);
+ ImportMaterials(asset);
+
+ ImportMeshes(asset);
+
+ ImportCameras(asset);
+ ImportLights(asset);
+
+ ImportNodes(asset);
+
+ // TODO: it does not split the loaded vertices, should it?
+ //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+ Assimp::MakeVerboseFormatProcess process;
+ process.Execute(pScene);
+
+
+ if (pScene->mNumMeshes == 0) {
+ pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+ }
+}
+
+#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
diff --git a/src/3rdparty/assimp/code/glTFImporter.h b/src/3rdparty/assimp/code/glTFImporter.h
new file mode 100644
index 000000000..5d06730a5
--- /dev/null
+++ b/src/3rdparty/assimp/code/glTFImporter.h
@@ -0,0 +1,90 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_GLTFIMPORTER_H_INC
+#define AI_GLTFIMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include "DefaultIOSystem.h"
+
+struct aiNode;
+
+
+namespace glTF
+{
+ class Asset;
+}
+
+namespace Assimp {
+
+/**
+ * Load the glTF format.
+ * https://github.com/KhronosGroup/glTF/tree/master/specification
+ */
+class glTFImporter : public BaseImporter{
+public:
+ glTFImporter();
+ virtual ~glTFImporter();
+ virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
+
+protected:
+ virtual const aiImporterDesc* GetInfo() const;
+ virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
+
+private:
+
+ std::vector<unsigned int> meshOffsets;
+
+ std::vector<int> embeddedTexIdxs;
+
+ aiScene* mScene;
+
+ void ImportEmbeddedTextures(glTF::Asset& a);
+ void ImportMaterials(glTF::Asset& a);
+ void ImportMeshes(glTF::Asset& a);
+ void ImportCameras(glTF::Asset& a);
+ void ImportLights(glTF::Asset& a);
+ void ImportNodes(glTF::Asset& a);
+
+};
+
+} // Namespace assimp
+
+#endif // AI_GLTFIMPORTER_H_INC
+
diff --git a/src/3rdparty/assimp/code/irrXMLWrapper.h b/src/3rdparty/assimp/code/irrXMLWrapper.h
index b06b426f8..41e418811 100644
--- a/src/3rdparty/assimp/code/irrXMLWrapper.h
+++ b/src/3rdparty/assimp/code/irrXMLWrapper.h
@@ -2,11 +2,11 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+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
@@ -23,16 +23,16 @@ 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
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
@@ -44,7 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// some long includes ....
#include "./../contrib/irrXML/irrXML.h"
#include "./../include/assimp/IOStream.hpp"
-namespace Assimp {
+#include "BaseImporter.h"
+#include <vector>
+
+namespace Assimp {
// ---------------------------------------------------------------------------------
/** @brief Utility class to make IrrXML work together with our custom IO system
@@ -53,86 +56,86 @@ namespace Assimp {
* Construct IrrXML-Reader in BaseImporter::InternReadFile():
* @code
* // open the file
- * boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+ * std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
* if( file.get() == NULL) {
- * throw DeadlyImportError( "Failed to open file " + pFile + ".");
+ * throw DeadlyImportError( "Failed to open file " + pFile + ".");
* }
*
* // generate a XML reader for it
- * boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
+ * std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get()));
* mReader = irr::io::createIrrXMLReader( mIOWrapper.get());
* if( !mReader) {
* ThrowException( "xxxx: Unable to open file.");
* }
* @endcode
**/
-class CIrrXML_IOStreamReader
- : public irr::io::IFileReadCallBack
+class CIrrXML_IOStreamReader
+ : public irr::io::IFileReadCallBack
{
public:
- // ----------------------------------------------------------------------------------
- //! Construction from an existing IOStream
- CIrrXML_IOStreamReader(IOStream* _stream)
- : stream (_stream)
- , t (0)
- {
-
- // Map the buffer into memory and convert it to UTF8. IrrXML provides its
- // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus,
- // it is not suitable for our purposes and we have to do it BEFORE IrrXML
- // gets the buffer. Sadly, this forces us to map the whole file into
- // memory.
-
- data.resize(stream->FileSize());
- stream->Read(&data[0],data.size(),1);
-
- // Remove null characters from the input sequence otherwise the parsing will utterly fail
- unsigned int size = 0;
- unsigned int size_max = data.size();
- for(unsigned int i = 0; i < size_max; i++) {
- if(data[i] != '\0') {
- data[size++] = data[i];
- }
- }
- data.resize(size);
-
- BaseImporter::ConvertToUTF8(data);
- }
-
- // ----------------------------------------------------------------------------------
- //! Virtual destructor
- virtual ~CIrrXML_IOStreamReader() {};
-
- // ----------------------------------------------------------------------------------
- //! Reads an amount of bytes from the file.
- /** @param buffer: Pointer to output buffer.
- * @param sizeToRead: Amount of bytes to read
- * @return Returns how much bytes were read. */
- virtual int read(void* buffer, int sizeToRead) {
- if(sizeToRead<0) {
- return 0;
- }
- if(t+sizeToRead>data.size()) {
- sizeToRead = data.size()-t;
- }
-
- memcpy(buffer,&data.front()+t,sizeToRead);
-
- t += sizeToRead;
- return sizeToRead;
- }
-
- // ----------------------------------------------------------------------------------
- //! Returns size of file in bytes
- virtual int getSize() {
- return (int)data.size();
- }
+ // ----------------------------------------------------------------------------------
+ //! Construction from an existing IOStream
+ explicit CIrrXML_IOStreamReader(IOStream* _stream)
+ : stream (_stream)
+ , t (0)
+ {
+
+ // Map the buffer into memory and convert it to UTF8. IrrXML provides its
+ // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus,
+ // it is not suitable for our purposes and we have to do it BEFORE IrrXML
+ // gets the buffer. Sadly, this forces us to map the whole file into
+ // memory.
+
+ data.resize(stream->FileSize());
+ stream->Read(&data[0],data.size(),1);
+
+ // Remove null characters from the input sequence otherwise the parsing will utterly fail
+ unsigned int size = 0;
+ unsigned int size_max = data.size();
+ for(unsigned int i = 0; i < size_max; i++) {
+ if(data[i] != '\0') {
+ data[size++] = data[i];
+ }
+ }
+ data.resize(size);
+
+ BaseImporter::ConvertToUTF8(data);
+ }
+
+ // ----------------------------------------------------------------------------------
+ //! Virtual destructor
+ virtual ~CIrrXML_IOStreamReader() {}
+
+ // ----------------------------------------------------------------------------------
+ //! Reads an amount of bytes from the file.
+ /** @param buffer: Pointer to output buffer.
+ * @param sizeToRead: Amount of bytes to read
+ * @return Returns how much bytes were read. */
+ virtual int read(void* buffer, int sizeToRead) {
+ if(sizeToRead<0) {
+ return 0;
+ }
+ if(t+sizeToRead>data.size()) {
+ sizeToRead = data.size()-t;
+ }
+
+ memcpy(buffer,&data.front()+t,sizeToRead);
+
+ t += sizeToRead;
+ return sizeToRead;
+ }
+
+ // ----------------------------------------------------------------------------------
+ //! Returns size of file in bytes
+ virtual int getSize() {
+ return (int)data.size();
+ }
private:
- IOStream* stream;
- std::vector<char> data;
- size_t t;
+ IOStream* stream;
+ std::vector<char> data;
+ size_t t;
}; // ! class CIrrXML_IOStreamReader
diff --git a/src/3rdparty/assimp/code/qnan.h b/src/3rdparty/assimp/code/qnan.h
index 4c86cd822..02412bf21 100644
--- a/src/3rdparty/assimp/code/qnan.h
+++ b/src/3rdparty/assimp/code/qnan.h
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+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
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
@@ -25,16 +25,16 @@ conditions are met:
derived from this software without specific prior
written permission of the assimp team.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
@@ -52,59 +52,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_QNAN_H_INCLUDED
#define AI_QNAN_H_INCLUDED
+#include <assimp/defs.h>
+#include <limits>
+#include <stdint.h>
+
// ---------------------------------------------------------------------------
-/** Data structure to represent the bit pattern of a 32 Bit
+/** Data structure to represent the bit pattern of a 32 Bit
* IEEE 754 floating-point number. */
union _IEEESingle
{
- float Float;
- struct
- {
- uint32_t Frac : 23;
- uint32_t Exp : 8;
- uint32_t Sign : 1;
- } IEEE;
+ float Float;
+ struct
+ {
+ uint32_t Frac : 23;
+ uint32_t Exp : 8;
+ uint32_t Sign : 1;
+ } IEEE;
} ;
// ---------------------------------------------------------------------------
-/** Check whether a given float is qNaN.
+/** Check whether a given float is qNaN.
* @param in Input value */
-AI_FORCE_INLINE bool is_qnan(float in)
+AI_FORCE_INLINE bool is_qnan(float in)
{
- // the straightforward solution does not work:
- // return (in != in);
- // compiler generates code like this
- // load <in> to <register-with-different-width>
- // compare <register-with-different-width> against <in>
-
- // FIXME: Use <float> stuff instead? I think fpclassify needs C99
- return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 &&
- reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac);
+ // the straightforward solution does not work:
+ // return (in != in);
+ // compiler generates code like this
+ // load <in> to <register-with-different-width>
+ // compare <register-with-different-width> against <in>
+
+ // FIXME: Use <float> stuff instead? I think fpclassify needs C99
+ return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 &&
+ reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac);
}
// ---------------------------------------------------------------------------
-/** Check whether a float is NOT qNaN.
+/** Check whether a float is NOT qNaN.
* @param in Input value */
-AI_FORCE_INLINE bool is_not_qnan(float in)
+AI_FORCE_INLINE bool is_not_qnan(float in)
{
- return !is_qnan(in);
+ return !is_qnan(in);
}
// ---------------------------------------------------------------------------
-/** @brief check whether a float is either NaN or (+/-) INF.
+/** @brief check whether a float is either NaN or (+/-) INF.
*
* Denorms return false, they're treated like normal values.
* @param in Input value */
AI_FORCE_INLINE bool is_special_float(float in)
{
- return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1);
+ return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1);
}
// ---------------------------------------------------------------------------
/** @brief Get a fresh qnan. */
AI_FORCE_INLINE float get_qnan()
{
- return std::numeric_limits<float>::quiet_NaN();
+ return std::numeric_limits<float>::quiet_NaN();
}
#endif // !! AI_QNAN_H_INCLUDED